main_test.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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(capsys, argv: list, expected_frame: pandas.DataFrame,
  13. subjects_dir: typing.Optional[str] = None):
  14. if subjects_dir:
  15. os.environ['SUBJECTS_DIR'] = subjects_dir
  16. elif 'SUBJECTS_DIR' in os.environ:
  17. del os.environ['SUBJECTS_DIR']
  18. with unittest.mock.patch('sys.argv', [''] + argv):
  19. assert freesurfer_volume_reader.__main__.main() == 0
  20. out, _ = capsys.readouterr()
  21. resulted_frame = pandas.read_csv(io.StringIO(out)).drop(columns=['source_path'])
  22. if 'correction' in resulted_frame:
  23. resulted_frame['correction'] = resulted_frame['correction'].astype('object')
  24. assert_volume_frames_equal(
  25. left=expected_frame,
  26. # pandas.DataFrame.drop(columns=[...], ...) >= pandas0.21.0
  27. right=resulted_frame,
  28. )
  29. @pytest.mark.parametrize(('args', 'root_dir_paths', 'expected_csv_path'), [
  30. ([],
  31. [os.path.join(SUBJECTS_DIR, 'alice')],
  32. os.path.join(SUBJECTS_DIR, 'alice', 'freesurfer-hippocampal-volumes.csv')),
  33. ([],
  34. [os.path.join(SUBJECTS_DIR, 'bert')],
  35. os.path.join(SUBJECTS_DIR, 'bert', 'freesurfer-hippocampal-volumes.csv')),
  36. ([],
  37. [os.path.join(SUBJECTS_DIR, 'alice'),
  38. os.path.join(SUBJECTS_DIR, 'bert')],
  39. os.path.join(SUBJECTS_DIR, 'freesurfer-hippocampal-volumes.csv')),
  40. ([],
  41. [SUBJECTS_DIR],
  42. os.path.join(SUBJECTS_DIR, 'freesurfer-hippocampal-volumes.csv')),
  43. (['--source-types', 'freesurfer-hipposf'],
  44. [os.path.join(SUBJECTS_DIR, 'alice')],
  45. os.path.join(SUBJECTS_DIR, 'alice', 'freesurfer-hippocampal-volumes.csv')),
  46. (['--source-types', 'freesurfer-hipposf'],
  47. [SUBJECTS_DIR],
  48. os.path.join(SUBJECTS_DIR, 'freesurfer-hippocampal-volumes.csv')),
  49. (['--source-types', 'ashs'],
  50. [os.path.join(SUBJECTS_DIR, 'alice')],
  51. os.path.join(SUBJECTS_DIR, 'alice', 'ashs-hippocampal-volumes.csv')),
  52. (['--source-types', 'ashs'],
  53. [os.path.join(SUBJECTS_DIR, 'bert')],
  54. os.path.join(SUBJECTS_DIR, 'bert', 'ashs-hippocampal-volumes.csv')),
  55. (['--source-types', 'ashs'],
  56. [os.path.join(SUBJECTS_DIR, 'alice'),
  57. os.path.join(SUBJECTS_DIR, 'bert')],
  58. os.path.join(SUBJECTS_DIR, 'ashs-hippocampal-volumes.csv')),
  59. (['--source-types', 'ashs'],
  60. [SUBJECTS_DIR],
  61. os.path.join(SUBJECTS_DIR, 'ashs-hippocampal-volumes.csv')),
  62. (['--source-types', 'ashs', 'freesurfer-hipposf'],
  63. [os.path.join(SUBJECTS_DIR, 'alice')],
  64. os.path.join(SUBJECTS_DIR, 'alice', 'all-hippocampal-volumes.csv')),
  65. (['--source-types', 'freesurfer-hipposf', 'ashs'],
  66. [os.path.join(SUBJECTS_DIR, 'alice')],
  67. os.path.join(SUBJECTS_DIR, 'alice', 'all-hippocampal-volumes.csv')),
  68. (['--source-types', 'ashs', 'freesurfer-hipposf'],
  69. [os.path.join(SUBJECTS_DIR, 'alice'),
  70. os.path.join(SUBJECTS_DIR, 'bert')],
  71. os.path.join(SUBJECTS_DIR, 'all-hippocampal-volumes.csv')),
  72. (['--source-types', 'ashs', 'freesurfer-hipposf'],
  73. [SUBJECTS_DIR],
  74. os.path.join(SUBJECTS_DIR, 'all-hippocampal-volumes.csv')),
  75. ])
  76. def test_main_root_dir_param(capsys, args, root_dir_paths: list, expected_csv_path):
  77. assert_main_volume_frame_equals(
  78. argv=args + ['--'] + root_dir_paths,
  79. expected_frame=pandas.read_csv(expected_csv_path),
  80. capsys=capsys,
  81. )
  82. @pytest.mark.parametrize(('args', 'root_dir_path', 'expected_csv_path'), [
  83. ([],
  84. SUBJECTS_DIR,
  85. os.path.join(SUBJECTS_DIR, 'freesurfer-hippocampal-volumes.csv')),
  86. ([],
  87. os.path.join(SUBJECTS_DIR, 'bert'),
  88. os.path.join(SUBJECTS_DIR, 'bert', 'freesurfer-hippocampal-volumes.csv')),
  89. (['--source-types', 'freesurfer-hipposf'],
  90. SUBJECTS_DIR,
  91. os.path.join(SUBJECTS_DIR, 'freesurfer-hippocampal-volumes.csv')),
  92. (['--source-types', 'freesurfer-hipposf'],
  93. os.path.join(SUBJECTS_DIR, 'bert'),
  94. os.path.join(SUBJECTS_DIR, 'bert', 'freesurfer-hippocampal-volumes.csv')),
  95. (['--source-types', 'freesurfer-hipposf'],
  96. os.path.join(SUBJECTS_DIR, 'bert', 'mri'),
  97. os.path.join(SUBJECTS_DIR, 'bert', 'freesurfer-hippocampal-volumes.csv')),
  98. (['--source-types', 'ashs'],
  99. SUBJECTS_DIR,
  100. os.path.join(SUBJECTS_DIR, 'ashs-hippocampal-volumes.csv')),
  101. (['--source-types', 'ashs'],
  102. os.path.join(SUBJECTS_DIR, 'bert'),
  103. os.path.join(SUBJECTS_DIR, 'bert', 'ashs-hippocampal-volumes.csv')),
  104. (['--source-types', 'ashs'],
  105. os.path.join(SUBJECTS_DIR, 'bert', 'final'),
  106. os.path.join(SUBJECTS_DIR, 'bert', 'ashs-hippocampal-volumes.csv')),
  107. (['--source-types', 'ashs'],
  108. os.path.join(SUBJECTS_DIR, 'alice'),
  109. os.path.join(SUBJECTS_DIR, 'alice', 'ashs-hippocampal-volumes.csv')),
  110. (['--source-types', 'ashs', 'freesurfer-hipposf'],
  111. os.path.join(SUBJECTS_DIR, 'alice'),
  112. os.path.join(SUBJECTS_DIR, 'alice', 'all-hippocampal-volumes.csv')),
  113. (['--source-types', 'freesurfer-hipposf', 'ashs'],
  114. os.path.join(SUBJECTS_DIR, 'alice'),
  115. os.path.join(SUBJECTS_DIR, 'alice', 'all-hippocampal-volumes.csv')),
  116. (['--source-types', 'freesurfer-hipposf', 'ashs'],
  117. SUBJECTS_DIR,
  118. os.path.join(SUBJECTS_DIR, 'all-hippocampal-volumes.csv')),
  119. ])
  120. def test_main_root_dir_env(capsys, args, root_dir_path, expected_csv_path):
  121. assert_main_volume_frame_equals(
  122. argv=args,
  123. subjects_dir=root_dir_path,
  124. expected_frame=pandas.read_csv(expected_csv_path),
  125. capsys=capsys,
  126. )
  127. @pytest.mark.timeout(8)
  128. @pytest.mark.parametrize(('args', 'root_dir_path', 'subjects_dir', 'expected_csv_path'), [
  129. ([],
  130. os.path.join(SUBJECTS_DIR, 'bert'),
  131. os.path.join(SUBJECTS_DIR, 'alice'),
  132. os.path.join(SUBJECTS_DIR, 'bert', 'freesurfer-hippocampal-volumes.csv')),
  133. (['--source-types', 'ashs'],
  134. os.path.join(SUBJECTS_DIR, 'bert'),
  135. os.path.join(SUBJECTS_DIR, 'alice'),
  136. os.path.join(SUBJECTS_DIR, 'bert', 'ashs-hippocampal-volumes.csv')),
  137. ([],
  138. os.path.join(SUBJECTS_DIR, 'bert'),
  139. os.path.abspath(os.sep),
  140. os.path.join(SUBJECTS_DIR, 'bert', 'freesurfer-hippocampal-volumes.csv')),
  141. ])
  142. def test_main_root_dir_overwrite_env(capsys, args, root_dir_path, subjects_dir, expected_csv_path):
  143. assert_main_volume_frame_equals(
  144. argv=args + ['--', root_dir_path],
  145. subjects_dir=subjects_dir,
  146. expected_frame=pandas.read_csv(expected_csv_path),
  147. capsys=capsys,
  148. )
  149. def test_main_root_dir_filename_regex_freesurfer(capsys):
  150. expected_volume_frame = pandas.read_csv(
  151. os.path.join(SUBJECTS_DIR, 'bert', 'freesurfer-hippocampal-volumes.csv'))
  152. assert_main_volume_frame_equals(
  153. argv=['--freesurfer-hipposf-filename-regex', r'^.*-T1-T2\.v10\.txt$',
  154. os.path.join(SUBJECTS_DIR, 'bert')],
  155. expected_frame=expected_volume_frame[expected_volume_frame['analysis_id'] == 'T2'].copy(),
  156. capsys=capsys,
  157. )
  158. def test_main_root_dir_filename_regex_ashs(capsys):
  159. expected_volume_frame = pandas.read_csv(
  160. os.path.join(SUBJECTS_DIR, 'bert', 'ashs-hippocampal-volumes.csv'))
  161. assert_main_volume_frame_equals(
  162. argv=['--ashs-filename-regex', r'_nogray_volumes.txt$',
  163. '--source-types', 'ashs', '--',
  164. os.path.join(SUBJECTS_DIR, 'bert')],
  165. expected_frame=expected_volume_frame[expected_volume_frame['correction']
  166. == 'nogray'].copy(),
  167. capsys=capsys,
  168. )
  169. def test_main_root_dir_filename_regex_combined(capsys):
  170. expected_volume_frame = pandas.read_csv(
  171. os.path.join(SUBJECTS_DIR, 'alice', 'all-hippocampal-volumes.csv'))
  172. expected_volume_frame = expected_volume_frame[
  173. # pylint: disable=singleton-comparison
  174. (expected_volume_frame['T1_input'] == True)
  175. | ((expected_volume_frame['source_type'] == 'ashs')
  176. & expected_volume_frame['correction'].isnull())
  177. ]
  178. assert_main_volume_frame_equals(
  179. argv=['--ashs-filename-regex', r'^alice_left_heur_',
  180. '--freesurfer-hipposf-filename-regex', r'hippoSfVolumes-T1.v10.txt$',
  181. '--source-types', 'ashs', 'freesurfer-hipposf',
  182. '--', os.path.join(SUBJECTS_DIR, 'alice')],
  183. expected_frame=expected_volume_frame.copy(),
  184. capsys=capsys,
  185. )
  186. def test_main_no_files_found(capsys):
  187. with unittest.mock.patch('sys.argv', ['', '--freesurfer-hipposf-filename-regex', r'^21$',
  188. '--', SUBJECTS_DIR]):
  189. assert os.EX_NOINPUT == freesurfer_volume_reader.__main__.main()
  190. out, err = capsys.readouterr()
  191. assert not out
  192. assert err == 'Did not find any volume files matching the specified criteria.\n'
  193. def test_main_module_script_no_files_found():
  194. proc_info = subprocess.run(['python', '-m', 'freesurfer_volume_reader',
  195. '--freesurfer-hipposf-filename-regex', r'^21$',
  196. '--', SUBJECTS_DIR],
  197. check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  198. assert os.EX_NOINPUT == proc_info.returncode
  199. assert not proc_info.stdout
  200. assert 'not find any volume files' in proc_info.stderr.rstrip().decode()
  201. def test_script_no_files_found():
  202. proc_info = subprocess.run(['freesurfer-volume-reader',
  203. '--freesurfer-hipposf-filename-regex', r'^21$',
  204. '--', SUBJECTS_DIR],
  205. check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  206. assert os.EX_NOINPUT == proc_info.returncode
  207. assert not proc_info.stdout
  208. assert 'not find any volume files' in proc_info.stderr.rstrip().decode()
  209. def test_main_module_script_help():
  210. subprocess.run(['python', '-m', 'freesurfer_volume_reader', '--help'],
  211. check=True)
  212. def test_main_module_script_version():
  213. proc_info = subprocess.run(['python', '-m', 'freesurfer_volume_reader', '--version'],
  214. check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  215. assert proc_info.stdout.rstrip() == freesurfer_volume_reader.__version__.encode()
  216. assert not proc_info.stderr