main_test.py 12 KB

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