|
4 | 4 | from glob import glob
|
5 | 5 |
|
6 | 6 | import pytest
|
7 |
| -from .utils import TESTS_DATA_PATH |
8 |
| - |
9 |
| -from heudiconv.convert import (update_complex_name, |
10 |
| - update_multiecho_name, |
11 |
| - update_uncombined_name, |
12 |
| - DW_IMAGE_IN_FMAP_FOLDER_WARNING, |
13 |
| - ) |
14 | 7 | from heudiconv.bids import BIDSError
|
15 | 8 | from heudiconv.cli.run import main as runner
|
| 9 | +from heudiconv.convert import ( |
| 10 | + DW_IMAGE_IN_FMAP_FOLDER_WARNING, |
| 11 | + update_complex_name, |
| 12 | + update_multiecho_name, |
| 13 | + update_uncombined_name, |
| 14 | +) |
| 15 | + |
| 16 | +from .utils import TESTS_DATA_PATH |
16 | 17 |
|
17 | 18 |
|
18 | 19 | def test_update_complex_name():
|
19 | 20 | """Unit testing for heudiconv.convert.update_complex_name(), which updates
|
20 | 21 | filenames with the part field if appropriate.
|
21 | 22 | """
|
22 | 23 | # Standard name update
|
23 |
| - fn = 'sub-X_ses-Y_task-Z_run-01_sbref' |
| 24 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_sbref' |
24 | 25 | metadata = {'ImageType': ['ORIGINAL', 'PRIMARY', 'P', 'MB', 'TE3', 'ND', 'MOSAIC']}
|
25 |
| - suffix = 3 |
26 | 26 | out_fn_true = 'sub-X_ses-Y_task-Z_run-01_part-phase_sbref'
|
27 |
| - out_fn_test = update_complex_name(metadata, fn, suffix) |
| 27 | + out_fn_test = update_complex_name(metadata, base_fn) |
28 | 28 | assert out_fn_test == out_fn_true
|
| 29 | + |
29 | 30 | # Catch an unsupported type and *do not* update
|
30 |
| - fn = 'sub-X_ses-Y_task-Z_run-01_phase' |
31 |
| - out_fn_test = update_complex_name(metadata, fn, suffix) |
32 |
| - assert out_fn_test == fn |
33 |
| - # Data type is missing from metadata so use suffix |
34 |
| - fn = 'sub-X_ses-Y_task-Z_run-01_sbref' |
| 31 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_phase' |
| 32 | + out_fn_test = update_complex_name(metadata, base_fn) |
| 33 | + assert out_fn_test == base_fn |
| 34 | + |
| 35 | + # Data type is missing from metadata so raise a RuntimeError |
| 36 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_sbref' |
35 | 37 | metadata = {'ImageType': ['ORIGINAL', 'PRIMARY', 'MB', 'TE3', 'ND', 'MOSAIC']}
|
36 |
| - out_fn_true = 'sub-X_ses-Y_task-Z_run-01_part-3_sbref' |
37 |
| - out_fn_test = update_complex_name(metadata, fn, suffix) |
38 |
| - assert out_fn_test == out_fn_true |
39 |
| - # Catch existing field with value that *does not match* metadata |
40 |
| - # and raise Exception |
41 |
| - fn = 'sub-X_ses-Y_task-Z_run-01_part-mag_sbref' |
| 38 | + with pytest.raises(RuntimeError): |
| 39 | + update_complex_name(metadata, base_fn) |
| 40 | + |
| 41 | + # Catch existing field with value (part is already in the filename) |
| 42 | + # that *does not match* metadata and raise Exception |
| 43 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_part-mag_sbref' |
42 | 44 | metadata = {'ImageType': ['ORIGINAL', 'PRIMARY', 'P', 'MB', 'TE3', 'ND', 'MOSAIC']}
|
43 |
| - suffix = 3 |
44 | 45 | with pytest.raises(BIDSError):
|
45 |
| - assert update_complex_name(metadata, fn, suffix) |
| 46 | + update_complex_name(metadata, base_fn) |
| 47 | + |
| 48 | + # Catch existing field with value (part is already in the filename) |
| 49 | + # that *does match* metadata and do not update |
| 50 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_part-phase_sbref' |
| 51 | + metadata = {'ImageType': ['ORIGINAL', 'PRIMARY', 'P', 'MB', 'TE3', 'ND', 'MOSAIC']} |
| 52 | + out_fn_test = update_complex_name(metadata, base_fn) |
| 53 | + assert out_fn_test == base_fn |
46 | 54 |
|
47 | 55 |
|
48 | 56 | def test_update_multiecho_name():
|
49 | 57 | """Unit testing for heudiconv.convert.update_multiecho_name(), which updates
|
50 | 58 | filenames with the echo field if appropriate.
|
51 | 59 | """
|
52 | 60 | # Standard name update
|
53 |
| - fn = 'sub-X_ses-Y_task-Z_run-01_bold' |
| 61 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_bold' |
54 | 62 | metadata = {'EchoTime': 0.01,
|
55 | 63 | 'EchoNumber': 1}
|
56 | 64 | echo_times = [0.01, 0.02, 0.03]
|
57 | 65 | out_fn_true = 'sub-X_ses-Y_task-Z_run-01_echo-1_bold'
|
58 |
| - out_fn_test = update_multiecho_name(metadata, fn, echo_times) |
| 66 | + out_fn_test = update_multiecho_name(metadata, base_fn, echo_times) |
59 | 67 | assert out_fn_test == out_fn_true
|
| 68 | + |
60 | 69 | # EchoNumber field is missing from metadata, so use echo_times
|
61 | 70 | metadata = {'EchoTime': 0.01}
|
62 |
| - out_fn_test = update_multiecho_name(metadata, fn, echo_times) |
| 71 | + out_fn_test = update_multiecho_name(metadata, base_fn, echo_times) |
63 | 72 | assert out_fn_test == out_fn_true
|
| 73 | + |
64 | 74 | # Catch an unsupported type and *do not* update
|
65 |
| - fn = 'sub-X_ses-Y_task-Z_run-01_phasediff' |
66 |
| - out_fn_test = update_multiecho_name(metadata, fn, echo_times) |
67 |
| - assert out_fn_test == fn |
| 75 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_phasediff' |
| 76 | + out_fn_test = update_multiecho_name(metadata, base_fn, echo_times) |
| 77 | + assert out_fn_test == base_fn |
| 78 | + |
| 79 | + # EchoTime is missing, but use EchoNumber (which is the first thing it checks) |
| 80 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_bold' |
| 81 | + out_fn_true = 'sub-X_ses-Y_task-Z_run-01_echo-1_bold' |
| 82 | + metadata = {'EchoNumber': 1} |
| 83 | + echo_times = [False, 0.02, 0.03] |
| 84 | + out_fn_test = update_multiecho_name(metadata, base_fn, echo_times) |
| 85 | + assert out_fn_test == out_fn_true |
| 86 | + |
| 87 | + # Both EchoTime and EchoNumber are missing, which raises a KeyError |
| 88 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_bold' |
| 89 | + metadata = {} |
| 90 | + echo_times = [False, 0.02, 0.03] |
| 91 | + with pytest.raises(KeyError): |
| 92 | + update_multiecho_name(metadata, base_fn, echo_times) |
| 93 | + |
| 94 | + # Providing echo times as something other than a list should raise a TypeError |
| 95 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_bold' |
| 96 | + with pytest.raises(TypeError): |
| 97 | + update_multiecho_name(metadata, base_fn, set(echo_times)) |
68 | 98 |
|
69 | 99 |
|
70 | 100 | def test_update_uncombined_name():
|
71 | 101 | """Unit testing for heudiconv.convert.update_uncombined_name(), which updates
|
72 | 102 | filenames with the ch field if appropriate.
|
73 | 103 | """
|
74 | 104 | # Standard name update
|
75 |
| - fn = 'sub-X_ses-Y_task-Z_run-01_bold' |
| 105 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_bold' |
76 | 106 | metadata = {'CoilString': 'H1'}
|
77 | 107 | channel_names = ['H1', 'H2', 'H3', 'HEA;HEP']
|
78 | 108 | out_fn_true = 'sub-X_ses-Y_task-Z_run-01_ch-01_bold'
|
79 |
| - out_fn_test = update_uncombined_name(metadata, fn, channel_names) |
| 109 | + out_fn_test = update_uncombined_name(metadata, base_fn, channel_names) |
80 | 110 | assert out_fn_test == out_fn_true
|
81 |
| - # CoilString field has no number in it |
| 111 | + |
| 112 | + # CoilString field has no number in it, so we index the channel_names list |
82 | 113 | metadata = {'CoilString': 'HEA;HEP'}
|
83 | 114 | out_fn_true = 'sub-X_ses-Y_task-Z_run-01_ch-04_bold'
|
84 |
| - out_fn_test = update_uncombined_name(metadata, fn, channel_names) |
| 115 | + out_fn_test = update_uncombined_name(metadata, base_fn, channel_names) |
85 | 116 | assert out_fn_test == out_fn_true
|
86 | 117 |
|
| 118 | + # Extract the number from the CoilString and use that |
| 119 | + channel_names = ['H1', 'B1', 'H3', 'HEA;HEP'] |
| 120 | + metadata = {'CoilString': 'H1'} |
| 121 | + out_fn_true = 'sub-X_ses-Y_task-Z_run-01_ch-01_bold' |
| 122 | + out_fn_test = update_uncombined_name(metadata, base_fn, channel_names) |
| 123 | + assert out_fn_test == out_fn_true |
| 124 | + |
| 125 | + # NOTE: Extracting the number does not protect against multiple coils with the same number |
| 126 | + # (but, say, different letters) |
| 127 | + # Note that this is still "ch-01" |
| 128 | + metadata = {'CoilString': 'B1'} |
| 129 | + out_fn_true = 'sub-X_ses-Y_task-Z_run-01_ch-01_bold' |
| 130 | + out_fn_test = update_uncombined_name(metadata, base_fn, channel_names) |
| 131 | + assert out_fn_test == out_fn_true |
| 132 | + |
| 133 | + # Providing echo times as something other than a list should raise a TypeError |
| 134 | + base_fn = 'sub-X_ses-Y_task-Z_run-01_bold' |
| 135 | + with pytest.raises(TypeError): |
| 136 | + update_uncombined_name(metadata, base_fn, set(channel_names)) |
| 137 | + |
87 | 138 |
|
88 | 139 | def test_b0dwi_for_fmap(tmpdir, caplog):
|
89 | 140 | """Make sure we raise a warning when .bvec and .bval files
|
|
0 commit comments