main_test.py 12 KB

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