ashs_test.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. # pylint: disable=missing-module-docstring
  2. import os
  3. import re
  4. import pandas
  5. import pytest
  6. from freesurfer_volume_reader.ashs import (
  7. IntracranialVolumeFile,
  8. HippocampalSubfieldsVolumeFile,
  9. )
  10. # pylint: disable=wrong-import-order; false positive
  11. from conftest import SUBJECTS_DIR, assert_volume_frames_equal
  12. @pytest.mark.parametrize(
  13. ("volume_file_path", "expected_subject"),
  14. [
  15. ("bert_icv.txt", "bert"),
  16. ("final/bert_icv.txt", "bert"),
  17. ("ashs/subjects/bert/final/bert_icv.txt", "bert"),
  18. (
  19. "ashs/subjects/alice/final/long_subject_name_42_icv.txt",
  20. "long_subject_name_42",
  21. ),
  22. ],
  23. )
  24. def test_intracranial_volume_file_init(volume_file_path, expected_subject):
  25. volume_file = IntracranialVolumeFile(path=volume_file_path)
  26. assert os.path.abspath(volume_file_path) == volume_file.absolute_path
  27. assert expected_subject == volume_file.subject
  28. @pytest.mark.parametrize(
  29. "volume_file_path", ["_icv.txt", "bert_ICV.txt", "bert_icv.csv", "bert_ICV.txt.zip"]
  30. )
  31. def test_intracranial_volume_file_init_invalid_filename(volume_file_path):
  32. with pytest.raises(Exception):
  33. IntracranialVolumeFile(path=volume_file_path)
  34. @pytest.mark.parametrize(
  35. ("volume_file_path", "expected_volume"),
  36. [
  37. (os.path.join(SUBJECTS_DIR, "bert", "final", "bert_icv.txt"), 1234560),
  38. (os.path.join(SUBJECTS_DIR, "bert", "final", "bert_icv.txt"), 1.23456e06),
  39. (os.path.join(SUBJECTS_DIR, "bert", "final", "bert_icv.txt"), 1.23456e06),
  40. (
  41. os.path.join(SUBJECTS_DIR, "bert", "final", "bert_icv.txt"),
  42. float("1.23456e+06"),
  43. ),
  44. (os.path.join(SUBJECTS_DIR, "alice", "final", "alice_icv.txt"), 1543200),
  45. ],
  46. )
  47. def test_intracranial_volume_file_read_volume_mm3(volume_file_path, expected_volume):
  48. volume_file = IntracranialVolumeFile(path=volume_file_path)
  49. assert expected_volume == pytest.approx(volume_file.read_volume_mm3())
  50. @pytest.mark.parametrize(
  51. "volume_file_path", [os.path.join(SUBJECTS_DIR, "noone", "final", "noone_icv.txt")]
  52. )
  53. def test_intracranial_volume_file_read_volume_mm3_not_found(volume_file_path):
  54. volume_file = IntracranialVolumeFile(path=volume_file_path)
  55. with pytest.raises(FileNotFoundError):
  56. volume_file.read_volume_mm3()
  57. @pytest.mark.parametrize(
  58. ("volume_file_path", "expected_series"),
  59. [
  60. (
  61. os.path.join(SUBJECTS_DIR, "bert", "final", "bert_icv.txt"),
  62. pandas.Series(
  63. data=[1234560.0],
  64. name="intercranial_volume_mm^3",
  65. index=pandas.Index(data=["bert"], name="subject"),
  66. ),
  67. ),
  68. (
  69. os.path.join(SUBJECTS_DIR, "alice", "final", "alice_icv.txt"),
  70. pandas.Series(
  71. data=[1543200.0],
  72. name="intercranial_volume_mm^3",
  73. index=pandas.Index(data=["alice"], name="subject"),
  74. ),
  75. ),
  76. ],
  77. )
  78. def test_intracranial_volume_file_read_volume_series_single(
  79. volume_file_path, expected_series
  80. ):
  81. volume_file = IntracranialVolumeFile(path=volume_file_path)
  82. pandas.testing.assert_series_equal(
  83. left=expected_series,
  84. right=volume_file.read_volume_series(),
  85. check_dtype=True,
  86. check_names=True,
  87. )
  88. @pytest.mark.parametrize(
  89. ("volume_file_paths", "expected_series"),
  90. [
  91. (
  92. [
  93. os.path.join(SUBJECTS_DIR, "bert", "final", "bert_icv.txt"),
  94. os.path.join(SUBJECTS_DIR, "alice", "final", "alice_icv.txt"),
  95. ],
  96. pandas.Series(
  97. data=[1234560.0, 1543200.0],
  98. name="intercranial_volume_mm^3",
  99. index=pandas.Index(data=["bert", "alice"], name="subject"),
  100. ),
  101. )
  102. ],
  103. )
  104. def test_intracranial_volume_file_read_volume_series_concat(
  105. volume_file_paths, expected_series
  106. ):
  107. volume_series = pandas.concat(
  108. IntracranialVolumeFile(path=p).read_volume_series() for p in volume_file_paths
  109. )
  110. pandas.testing.assert_series_equal(
  111. left=expected_series, right=volume_series, check_dtype=True, check_names=True
  112. )
  113. @pytest.mark.parametrize(
  114. "volume_file_path", [os.path.join(SUBJECTS_DIR, "bert", "final", "BERT_icv.txt")]
  115. )
  116. def test_intracranial_volume_file_read_volume_series_not_found(volume_file_path):
  117. volume_file = IntracranialVolumeFile(path=volume_file_path)
  118. with pytest.raises(FileNotFoundError):
  119. volume_file.read_volume_series()
  120. @pytest.mark.parametrize(
  121. ("root_dir_path", "expected_file_paths"),
  122. [
  123. (
  124. os.path.join(SUBJECTS_DIR, "bert"),
  125. {os.path.join(SUBJECTS_DIR, "bert", "final", "bert_icv.txt")},
  126. ),
  127. (
  128. os.path.join(SUBJECTS_DIR, "alice"),
  129. {os.path.join(SUBJECTS_DIR, "alice", "final", "alice_icv.txt")},
  130. ),
  131. (
  132. SUBJECTS_DIR,
  133. {
  134. os.path.join(SUBJECTS_DIR, "alice", "final", "alice_icv.txt"),
  135. os.path.join(SUBJECTS_DIR, "bert", "final", "bert_icv.txt"),
  136. },
  137. ),
  138. ],
  139. )
  140. def test_intracranial_volume_file_find(root_dir_path, expected_file_paths):
  141. volume_files_iterator = IntracranialVolumeFile.find(root_dir_path=root_dir_path)
  142. assert expected_file_paths == set(f.absolute_path for f in volume_files_iterator)
  143. @pytest.mark.parametrize(
  144. ("root_dir_path", "filename_pattern", "expected_file_paths"),
  145. [
  146. (
  147. SUBJECTS_DIR,
  148. r"^\w{4,6}_icv.txt$",
  149. {
  150. os.path.join(SUBJECTS_DIR, "alice", "final", "alice_icv.txt"),
  151. os.path.join(SUBJECTS_DIR, "bert", "final", "bert_icv.txt"),
  152. },
  153. ),
  154. (
  155. SUBJECTS_DIR,
  156. r"^\w{5,6}_icv.txt$",
  157. {os.path.join(SUBJECTS_DIR, "alice", "final", "alice_icv.txt")},
  158. ),
  159. (SUBJECTS_DIR, r"^\w{7,}_icv.txt$", set()),
  160. ],
  161. )
  162. def test_intracranial_volume_file_find_pattern(
  163. root_dir_path, filename_pattern, expected_file_paths
  164. ):
  165. volume_files_iterator = IntracranialVolumeFile.find(
  166. root_dir_path=root_dir_path, filename_regex=re.compile(filename_pattern)
  167. )
  168. assert expected_file_paths == set(f.absolute_path for f in volume_files_iterator)
  169. @pytest.mark.parametrize(
  170. ("volume_file_path", "expected_attrs"),
  171. [
  172. (
  173. "ashs/final/bert_left_heur_volumes.txt",
  174. {"subject": "bert", "hemisphere": "left", "correction": None},
  175. ),
  176. (
  177. "ashs/final/bert_left_corr_nogray_volumes.txt",
  178. {"subject": "bert", "hemisphere": "left", "correction": "nogray"},
  179. ),
  180. (
  181. "ashs/final/bert_left_corr_usegray_volumes.txt",
  182. {"subject": "bert", "hemisphere": "left", "correction": "usegray"},
  183. ),
  184. (
  185. "ashs/final/bert_right_heur_volumes.txt",
  186. {"subject": "bert", "hemisphere": "right", "correction": None},
  187. ),
  188. (
  189. "ashs/final/bert_right_corr_nogray_volumes.txt",
  190. {"subject": "bert", "hemisphere": "right", "correction": "nogray"},
  191. ),
  192. (
  193. "ashs/final/bert_right_corr_usegray_volumes.txt",
  194. {"subject": "bert", "hemisphere": "right", "correction": "usegray"},
  195. ),
  196. (
  197. "somewhere/else/bert_right_heur_volumes.txt",
  198. {"subject": "bert", "hemisphere": "right", "correction": None},
  199. ),
  200. (
  201. "somewhere/else/bert_right_corr_nogray_volumes.txt",
  202. {"subject": "bert", "hemisphere": "right", "correction": "nogray"},
  203. ),
  204. (
  205. "bert_right_heur_volumes.txt",
  206. {"subject": "bert", "hemisphere": "right", "correction": None},
  207. ),
  208. (
  209. "/foo/bar/alice_20190503_right_corr_nogray_volumes.txt",
  210. {
  211. "subject": "alice_20190503",
  212. "hemisphere": "right",
  213. "correction": "nogray",
  214. },
  215. ),
  216. ],
  217. )
  218. def test_hippocampal_subfields_volume_file_init(volume_file_path, expected_attrs):
  219. volume_file = HippocampalSubfieldsVolumeFile(path=volume_file_path)
  220. assert os.path.abspath(volume_file_path) == volume_file.absolute_path
  221. for attr, value in expected_attrs.items():
  222. assert value == getattr(volume_file, attr)
  223. @pytest.mark.parametrize(
  224. "volume_file_path",
  225. [
  226. "bert_middle_heur_volumes.txt",
  227. "bert_right_hear_volumes.txt",
  228. "bert_right_heur_volumes.nii",
  229. "bert_left_lfseg_corr_usegray.nii.gz",
  230. ],
  231. )
  232. def test_hippocampal_subfields_volume_file_init_invalid(volume_file_path):
  233. with pytest.raises(Exception): # pylint: disable=duplicate-code; freesurfer tests
  234. HippocampalSubfieldsVolumeFile(path=volume_file_path)
  235. @pytest.mark.parametrize(
  236. ("volume_file_path", "expected_volumes"),
  237. [
  238. (
  239. os.path.join(
  240. SUBJECTS_DIR, "bert", "final", "bert_left_corr_nogray_volumes.txt"
  241. ),
  242. {
  243. "CA1": 678.901,
  244. "CA2+3": 123.456,
  245. "DG": 901.234,
  246. "ERC": 789.012,
  247. "PHC": 2345.876,
  248. "PRC": 2345.678,
  249. "SUB": 457.789,
  250. },
  251. )
  252. ],
  253. )
  254. def test_hippocampal_subfields_volume_file_read_volumes_mm3(
  255. volume_file_path, expected_volumes
  256. ):
  257. volume_file = HippocampalSubfieldsVolumeFile(path=volume_file_path)
  258. assert expected_volumes == volume_file.read_volumes_mm3()
  259. def test_hippocampal_subfields_volume_file_read_volumes_mm3_not_found():
  260. volume_file = HippocampalSubfieldsVolumeFile(
  261. path=os.path.join(
  262. SUBJECTS_DIR, "nobert", "final", "bert_left_corr_nogray_volumes.txt"
  263. )
  264. )
  265. with pytest.raises(FileNotFoundError):
  266. volume_file.read_volumes_mm3()
  267. @pytest.mark.parametrize(
  268. ("volume_file_path", "expected_dataframe"),
  269. [
  270. (
  271. os.path.join(SUBJECTS_DIR, "alice", "final", "alice_left_heur_volumes.txt"),
  272. pandas.DataFrame(
  273. {
  274. "subfield": ["CA1", "CA2+3", "DG", "ERC", "PHC", "PRC", "SUB"],
  275. "volume_mm^3": [
  276. 679.904,
  277. 124.459,
  278. 902.237,
  279. 789.012,
  280. 2346.879,
  281. 2346.671,
  282. 458.782,
  283. ],
  284. "subject": "alice",
  285. "hemisphere": "left",
  286. "correction": None,
  287. }
  288. ),
  289. )
  290. ],
  291. )
  292. def test_hippocampal_subfields_volume_file_read_volumes_dataframe(
  293. volume_file_path: str, expected_dataframe: pandas.DataFrame
  294. ):
  295. volume_file = HippocampalSubfieldsVolumeFile(path=volume_file_path)
  296. assert_volume_frames_equal(
  297. left=expected_dataframe, right=volume_file.read_volumes_dataframe()
  298. )
  299. def test_hippocampal_subfields_volume_file_read_volumes_dataframe_not_found():
  300. volume_file = HippocampalSubfieldsVolumeFile(
  301. path=os.path.join(
  302. SUBJECTS_DIR, "nobert", "final", "bert_left_corr_nogray_volumes.txt"
  303. )
  304. )
  305. with pytest.raises(FileNotFoundError):
  306. volume_file.read_volumes_dataframe()
  307. @pytest.mark.parametrize(
  308. ("root_dir_path", "expected_file_paths"),
  309. [
  310. (
  311. os.path.join(SUBJECTS_DIR, "alice"),
  312. {
  313. os.path.join(
  314. SUBJECTS_DIR, "alice", "final", "alice_left_heur_volumes.txt"
  315. ),
  316. os.path.join(
  317. SUBJECTS_DIR, "alice", "final", "alice_left_corr_nogray_volumes.txt"
  318. ),
  319. },
  320. ),
  321. (
  322. os.path.join(SUBJECTS_DIR, "bert"),
  323. {
  324. os.path.join(
  325. SUBJECTS_DIR, "bert", "final", "bert_left_corr_nogray_volumes.txt"
  326. ),
  327. os.path.join(
  328. SUBJECTS_DIR, "bert", "final", "bert_left_corr_usegray_volumes.txt"
  329. ),
  330. os.path.join(
  331. SUBJECTS_DIR, "bert", "final", "bert_left_heur_volumes.txt"
  332. ),
  333. os.path.join(
  334. SUBJECTS_DIR, "bert", "final", "bert_right_corr_nogray_volumes.txt"
  335. ),
  336. },
  337. ),
  338. (
  339. SUBJECTS_DIR,
  340. {
  341. os.path.join(
  342. SUBJECTS_DIR, "alice", "final", "alice_left_heur_volumes.txt"
  343. ),
  344. os.path.join(
  345. SUBJECTS_DIR, "alice", "final", "alice_left_corr_nogray_volumes.txt"
  346. ),
  347. os.path.join(
  348. SUBJECTS_DIR, "bert", "final", "bert_left_corr_nogray_volumes.txt"
  349. ),
  350. os.path.join(
  351. SUBJECTS_DIR, "bert", "final", "bert_left_corr_usegray_volumes.txt"
  352. ),
  353. os.path.join(
  354. SUBJECTS_DIR, "bert", "final", "bert_left_heur_volumes.txt"
  355. ),
  356. os.path.join(
  357. SUBJECTS_DIR, "bert", "final", "bert_right_corr_nogray_volumes.txt"
  358. ),
  359. },
  360. ),
  361. ],
  362. )
  363. def test_hippocampal_subfields_volume_file_find(root_dir_path, expected_file_paths):
  364. volume_files_iterator = HippocampalSubfieldsVolumeFile.find(
  365. root_dir_path=root_dir_path
  366. )
  367. assert expected_file_paths == set(f.absolute_path for f in volume_files_iterator)
  368. @pytest.mark.parametrize(
  369. ("root_dir_path", "filename_pattern", "expected_file_paths"),
  370. [
  371. (
  372. SUBJECTS_DIR,
  373. r"^bert_right_",
  374. {
  375. os.path.join(
  376. SUBJECTS_DIR, "bert", "final", "bert_right_corr_nogray_volumes.txt"
  377. )
  378. },
  379. ),
  380. (
  381. SUBJECTS_DIR,
  382. r"_nogray_volumes.txt$",
  383. {
  384. os.path.join(
  385. SUBJECTS_DIR, "alice", "final", "alice_left_corr_nogray_volumes.txt"
  386. ),
  387. os.path.join(
  388. SUBJECTS_DIR, "bert", "final", "bert_left_corr_nogray_volumes.txt"
  389. ),
  390. os.path.join(
  391. SUBJECTS_DIR, "bert", "final", "bert_right_corr_nogray_volumes.txt"
  392. ),
  393. },
  394. ),
  395. ],
  396. )
  397. def test_hippocampal_subfields_volume_file_find_pattern(
  398. root_dir_path, filename_pattern, expected_file_paths
  399. ):
  400. volume_files_iterator = HippocampalSubfieldsVolumeFile.find(
  401. root_dir_path=root_dir_path, filename_regex=re.compile(filename_pattern)
  402. )
  403. assert expected_file_paths == set(f.absolute_path for f in volume_files_iterator)