main_test.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. import io
  2. import os
  3. import subprocess
  4. import typing
  5. import unittest.mock
  6. import pandas
  7. import pandas.util.testing
  8. import pytest
  9. import freesurfer_volume_reader
  10. import freesurfer_volume_reader.__main__
  11. from conftest import SUBJECTS_DIR, assert_volume_frames_equal
  12. def assert_main_volume_frame_equals(
  13. capsys,
  14. argv: list,
  15. expected_frame: pandas.DataFrame,
  16. subjects_dir: typing.Optional[str] = None,
  17. ):
  18. if subjects_dir:
  19. os.environ["SUBJECTS_DIR"] = subjects_dir
  20. elif "SUBJECTS_DIR" in os.environ:
  21. del os.environ["SUBJECTS_DIR"]
  22. with unittest.mock.patch("sys.argv", [""] + argv):
  23. assert freesurfer_volume_reader.__main__.main() == 0
  24. out, _ = capsys.readouterr()
  25. resulted_frame = pandas.read_csv(io.StringIO(out)).drop(columns=["source_path"])
  26. if "correction" in resulted_frame:
  27. resulted_frame["correction"] = resulted_frame["correction"].astype("object")
  28. assert_volume_frames_equal(
  29. left=expected_frame,
  30. # pandas.DataFrame.drop(columns=[...], ...) >= pandas0.21.0
  31. right=resulted_frame,
  32. )
  33. @pytest.mark.parametrize(
  34. ("args", "root_dir_paths", "expected_csv_path"),
  35. [
  36. (
  37. [],
  38. [os.path.join(SUBJECTS_DIR, "alice")],
  39. os.path.join(SUBJECTS_DIR, "alice", "freesurfer-hippocampal-volumes.csv"),
  40. ),
  41. (
  42. [],
  43. [os.path.join(SUBJECTS_DIR, "bert")],
  44. os.path.join(SUBJECTS_DIR, "bert", "freesurfer-hippocampal-volumes.csv"),
  45. ),
  46. (
  47. [],
  48. [os.path.join(SUBJECTS_DIR, "alice"), os.path.join(SUBJECTS_DIR, "bert")],
  49. os.path.join(SUBJECTS_DIR, "freesurfer-hippocampal-volumes.csv"),
  50. ),
  51. (
  52. [],
  53. [SUBJECTS_DIR],
  54. os.path.join(SUBJECTS_DIR, "freesurfer-hippocampal-volumes.csv"),
  55. ),
  56. (
  57. ["--source-types", "freesurfer-hipposf"],
  58. [os.path.join(SUBJECTS_DIR, "alice")],
  59. os.path.join(SUBJECTS_DIR, "alice", "freesurfer-hippocampal-volumes.csv"),
  60. ),
  61. (
  62. ["--source-types", "freesurfer-hipposf"],
  63. [SUBJECTS_DIR],
  64. os.path.join(SUBJECTS_DIR, "freesurfer-hippocampal-volumes.csv"),
  65. ),
  66. (
  67. ["--source-types", "ashs"],
  68. [os.path.join(SUBJECTS_DIR, "alice")],
  69. os.path.join(SUBJECTS_DIR, "alice", "ashs-hippocampal-volumes.csv"),
  70. ),
  71. (
  72. ["--source-types", "ashs"],
  73. [os.path.join(SUBJECTS_DIR, "bert")],
  74. os.path.join(SUBJECTS_DIR, "bert", "ashs-hippocampal-volumes.csv"),
  75. ),
  76. (
  77. ["--source-types", "ashs"],
  78. [os.path.join(SUBJECTS_DIR, "alice"), os.path.join(SUBJECTS_DIR, "bert")],
  79. os.path.join(SUBJECTS_DIR, "ashs-hippocampal-volumes.csv"),
  80. ),
  81. (
  82. ["--source-types", "ashs"],
  83. [SUBJECTS_DIR],
  84. os.path.join(SUBJECTS_DIR, "ashs-hippocampal-volumes.csv"),
  85. ),
  86. (
  87. ["--source-types", "ashs", "freesurfer-hipposf"],
  88. [os.path.join(SUBJECTS_DIR, "alice")],
  89. os.path.join(SUBJECTS_DIR, "alice", "all-hippocampal-volumes.csv"),
  90. ),
  91. (
  92. ["--source-types", "freesurfer-hipposf", "ashs"],
  93. [os.path.join(SUBJECTS_DIR, "alice")],
  94. os.path.join(SUBJECTS_DIR, "alice", "all-hippocampal-volumes.csv"),
  95. ),
  96. (
  97. ["--source-types", "ashs", "freesurfer-hipposf"],
  98. [os.path.join(SUBJECTS_DIR, "alice"), os.path.join(SUBJECTS_DIR, "bert")],
  99. os.path.join(SUBJECTS_DIR, "all-hippocampal-volumes.csv"),
  100. ),
  101. (
  102. ["--source-types", "ashs", "freesurfer-hipposf"],
  103. [SUBJECTS_DIR],
  104. os.path.join(SUBJECTS_DIR, "all-hippocampal-volumes.csv"),
  105. ),
  106. ],
  107. )
  108. def test_main_root_dir_param(capsys, args, root_dir_paths: list, expected_csv_path):
  109. assert_main_volume_frame_equals(
  110. argv=args + ["--"] + root_dir_paths,
  111. expected_frame=pandas.read_csv(expected_csv_path),
  112. capsys=capsys,
  113. )
  114. @pytest.mark.parametrize(
  115. ("args", "root_dir_path", "expected_csv_path"),
  116. [
  117. (
  118. [],
  119. SUBJECTS_DIR,
  120. os.path.join(SUBJECTS_DIR, "freesurfer-hippocampal-volumes.csv"),
  121. ),
  122. (
  123. [],
  124. os.path.join(SUBJECTS_DIR, "bert"),
  125. os.path.join(SUBJECTS_DIR, "bert", "freesurfer-hippocampal-volumes.csv"),
  126. ),
  127. (
  128. ["--source-types", "freesurfer-hipposf"],
  129. SUBJECTS_DIR,
  130. os.path.join(SUBJECTS_DIR, "freesurfer-hippocampal-volumes.csv"),
  131. ),
  132. (
  133. ["--source-types", "freesurfer-hipposf"],
  134. os.path.join(SUBJECTS_DIR, "bert"),
  135. os.path.join(SUBJECTS_DIR, "bert", "freesurfer-hippocampal-volumes.csv"),
  136. ),
  137. (
  138. ["--source-types", "freesurfer-hipposf"],
  139. os.path.join(SUBJECTS_DIR, "bert", "mri"),
  140. os.path.join(SUBJECTS_DIR, "bert", "freesurfer-hippocampal-volumes.csv"),
  141. ),
  142. (
  143. ["--source-types", "ashs"],
  144. SUBJECTS_DIR,
  145. os.path.join(SUBJECTS_DIR, "ashs-hippocampal-volumes.csv"),
  146. ),
  147. (
  148. ["--source-types", "ashs"],
  149. os.path.join(SUBJECTS_DIR, "bert"),
  150. os.path.join(SUBJECTS_DIR, "bert", "ashs-hippocampal-volumes.csv"),
  151. ),
  152. (
  153. ["--source-types", "ashs"],
  154. os.path.join(SUBJECTS_DIR, "bert", "final"),
  155. os.path.join(SUBJECTS_DIR, "bert", "ashs-hippocampal-volumes.csv"),
  156. ),
  157. (
  158. ["--source-types", "ashs"],
  159. os.path.join(SUBJECTS_DIR, "alice"),
  160. os.path.join(SUBJECTS_DIR, "alice", "ashs-hippocampal-volumes.csv"),
  161. ),
  162. (
  163. ["--source-types", "ashs", "freesurfer-hipposf"],
  164. os.path.join(SUBJECTS_DIR, "alice"),
  165. os.path.join(SUBJECTS_DIR, "alice", "all-hippocampal-volumes.csv"),
  166. ),
  167. (
  168. ["--source-types", "freesurfer-hipposf", "ashs"],
  169. os.path.join(SUBJECTS_DIR, "alice"),
  170. os.path.join(SUBJECTS_DIR, "alice", "all-hippocampal-volumes.csv"),
  171. ),
  172. (
  173. ["--source-types", "freesurfer-hipposf", "ashs"],
  174. SUBJECTS_DIR,
  175. os.path.join(SUBJECTS_DIR, "all-hippocampal-volumes.csv"),
  176. ),
  177. ],
  178. )
  179. def test_main_root_dir_env(capsys, args, root_dir_path, expected_csv_path):
  180. assert_main_volume_frame_equals(
  181. argv=args,
  182. subjects_dir=root_dir_path,
  183. expected_frame=pandas.read_csv(expected_csv_path),
  184. capsys=capsys,
  185. )
  186. @pytest.mark.timeout(8)
  187. @pytest.mark.parametrize(
  188. ("args", "root_dir_path", "subjects_dir", "expected_csv_path"),
  189. [
  190. (
  191. [],
  192. os.path.join(SUBJECTS_DIR, "bert"),
  193. os.path.join(SUBJECTS_DIR, "alice"),
  194. os.path.join(SUBJECTS_DIR, "bert", "freesurfer-hippocampal-volumes.csv"),
  195. ),
  196. (
  197. ["--source-types", "ashs"],
  198. os.path.join(SUBJECTS_DIR, "bert"),
  199. os.path.join(SUBJECTS_DIR, "alice"),
  200. os.path.join(SUBJECTS_DIR, "bert", "ashs-hippocampal-volumes.csv"),
  201. ),
  202. (
  203. [],
  204. os.path.join(SUBJECTS_DIR, "bert"),
  205. os.path.abspath(os.sep),
  206. os.path.join(SUBJECTS_DIR, "bert", "freesurfer-hippocampal-volumes.csv"),
  207. ),
  208. ],
  209. )
  210. def test_main_root_dir_overwrite_env(
  211. capsys, args, root_dir_path, subjects_dir, expected_csv_path
  212. ):
  213. assert_main_volume_frame_equals(
  214. argv=args + ["--", root_dir_path],
  215. subjects_dir=subjects_dir,
  216. expected_frame=pandas.read_csv(expected_csv_path),
  217. capsys=capsys,
  218. )
  219. def test_main_root_dir_filename_regex_freesurfer(capsys):
  220. expected_volume_frame = pandas.read_csv(
  221. os.path.join(SUBJECTS_DIR, "bert", "freesurfer-hippocampal-volumes.csv")
  222. )
  223. assert_main_volume_frame_equals(
  224. argv=[
  225. "--freesurfer-hipposf-filename-regex",
  226. r"^.*-T1-T2\.v10\.txt$",
  227. os.path.join(SUBJECTS_DIR, "bert"),
  228. ],
  229. expected_frame=expected_volume_frame[
  230. expected_volume_frame["analysis_id"] == "T2"
  231. ].copy(),
  232. capsys=capsys,
  233. )
  234. def test_main_root_dir_filename_regex_ashs(capsys):
  235. expected_volume_frame = pandas.read_csv(
  236. os.path.join(SUBJECTS_DIR, "bert", "ashs-hippocampal-volumes.csv")
  237. )
  238. assert_main_volume_frame_equals(
  239. argv=[
  240. "--ashs-filename-regex",
  241. r"_nogray_volumes.txt$",
  242. "--source-types",
  243. "ashs",
  244. "--",
  245. os.path.join(SUBJECTS_DIR, "bert"),
  246. ],
  247. expected_frame=expected_volume_frame[
  248. expected_volume_frame["correction"] == "nogray"
  249. ].copy(),
  250. capsys=capsys,
  251. )
  252. def test_main_root_dir_filename_regex_combined(capsys):
  253. expected_volume_frame = pandas.read_csv(
  254. os.path.join(SUBJECTS_DIR, "alice", "all-hippocampal-volumes.csv")
  255. )
  256. expected_volume_frame = expected_volume_frame[
  257. # pylint: disable=singleton-comparison
  258. (expected_volume_frame["T1_input"] == True)
  259. | (
  260. (expected_volume_frame["source_type"] == "ashs")
  261. & expected_volume_frame["correction"].isnull()
  262. )
  263. ]
  264. assert_main_volume_frame_equals(
  265. argv=[
  266. "--ashs-filename-regex",
  267. r"^alice_left_heur_",
  268. "--freesurfer-hipposf-filename-regex",
  269. r"hippoSfVolumes-T1.v10.txt$",
  270. "--source-types",
  271. "ashs",
  272. "freesurfer-hipposf",
  273. "--",
  274. os.path.join(SUBJECTS_DIR, "alice"),
  275. ],
  276. expected_frame=expected_volume_frame.copy(),
  277. capsys=capsys,
  278. )
  279. def test_main_no_files_found(capsys):
  280. with unittest.mock.patch(
  281. "sys.argv",
  282. ["", "--freesurfer-hipposf-filename-regex", r"^21$", "--", SUBJECTS_DIR],
  283. ):
  284. assert os.EX_NOINPUT == freesurfer_volume_reader.__main__.main()
  285. out, err = capsys.readouterr()
  286. assert not out
  287. assert err == "Did not find any volume files matching the specified criteria.\n"
  288. def test_main_module_script_no_files_found():
  289. proc_info = subprocess.run(
  290. [
  291. "python",
  292. "-m",
  293. "freesurfer_volume_reader",
  294. "--freesurfer-hipposf-filename-regex",
  295. r"^21$",
  296. "--",
  297. SUBJECTS_DIR,
  298. ],
  299. check=False,
  300. stdout=subprocess.PIPE,
  301. stderr=subprocess.PIPE,
  302. )
  303. assert os.EX_NOINPUT == proc_info.returncode
  304. assert not proc_info.stdout
  305. assert "not find any volume files" in proc_info.stderr.rstrip().decode()
  306. def test_script_no_files_found():
  307. proc_info = subprocess.run(
  308. [
  309. "freesurfer-volume-reader",
  310. "--freesurfer-hipposf-filename-regex",
  311. r"^21$",
  312. "--",
  313. SUBJECTS_DIR,
  314. ],
  315. check=False,
  316. stdout=subprocess.PIPE,
  317. stderr=subprocess.PIPE,
  318. )
  319. assert os.EX_NOINPUT == proc_info.returncode
  320. assert not proc_info.stdout
  321. assert "not find any volume files" in proc_info.stderr.rstrip().decode()
  322. def test_main_module_script_help():
  323. subprocess.run(["python", "-m", "freesurfer_volume_reader", "--help"], check=True)
  324. def test_main_module_script_version():
  325. proc_info = subprocess.run(
  326. ["python", "-m", "freesurfer_volume_reader", "--version"],
  327. check=True,
  328. stdout=subprocess.PIPE,
  329. stderr=subprocess.PIPE,
  330. )
  331. assert proc_info.stdout.rstrip() == freesurfer_volume_reader.__version__.encode()
  332. assert not proc_info.stderr