def test_load_json(tmpdir, caplog): # test invalid json ifname = 'invalid.json' invalid_json_file = str(tmpdir / ifname) create_tree(str(tmpdir), {ifname: u"I'm Jason Bourne"}) with pytest.raises(JSONDecodeError): load_json(str(invalid_json_file)) assert ifname in caplog.text # test valid json vcontent = {"secret": "spy"} vfname = "valid.json" valid_json_file = str(tmpdir / vfname) save_json(valid_json_file, vcontent) assert load_json(valid_json_file) == vcontent
def test_load_json(tmpdir, caplog): # test invalid json ifname = 'invalid.json' invalid_json_file = str(tmpdir / ifname) create_tree(str(tmpdir), {ifname: u"I'm Jason Bourne"}) with pytest.raises(JSONDecodeError): load_json(str(invalid_json_file)) # and even if we ask to retry a few times -- should be the same with pytest.raises(JSONDecodeError): load_json(str(invalid_json_file), retry=3) with pytest.raises(FileNotFoundError): load_json("absent123not.there", retry=3) assert ifname in caplog.text # test valid json vcontent = {"secret": "spy"} vfname = "valid.json" valid_json_file = str(tmpdir / vfname) save_json(valid_json_file, vcontent) assert load_json(valid_json_file) == vcontent calls = [0] json_load = json.load def json_load_patched(fp): calls[0] += 1 if calls[0] == 1: # just reuse bad file load_json(str(invalid_json_file)) elif calls[0] == 2: raise FileNotFoundError() else: return json_load(fp) with mock.patch.object(json, 'load', json_load_patched): assert load_json(valid_json_file, retry=3) == vcontent
def create_dummy_magnitude_phase_bids_session(session_path): """ Creates a dummy BIDS session, with slim json files and empty nii.gz The fmap files are a magnitude/phase pair The json files have ShimSettings We just need to test a very simple case to make sure the mag/phase have the same "IntendedFor" field: Parameters: ---------- session_path : str or os.path path to the session (or subject) level folder Returns: ------- session_struct : dict Structure of the directory that was created expected_result : dict dictionary with fmap names as keys and the expected "IntendedFor" as values. expected_fmap_groups : dict dictionary with the expected fmap groups """ session_parent, session_basename = op.split(session_path.rstrip(op.sep)) if session_basename.startswith('ses-'): prefix = op.split(session_parent)[1] + '_' + session_basename else: prefix = session_basename # 1) Simulate the file structure for a session: # Generate some random ShimSettings: dwi_shims = [random() for i in range(SHIM_LENGTH)] func_shims_A = [random() for i in range(SHIM_LENGTH)] func_shims_B = [random() for i in range(SHIM_LENGTH)] # Dict with the file structure for the session: # -dwi: dwi_struct = { '{p}_acq-A_run-{r}_dwi.nii.gz'.format(p=prefix, r=runNo): '' for runNo in [1, 2] } dwi_struct.update({ '{p}_acq-A_run-{r}_dwi.json'.format(p=prefix, r=runNo): { 'ShimSetting': dwi_shims } for runNo in [1, 2] }) # -func: func_struct = { '{p}_acq-{a}_bold.nii.gz'.format(p=prefix, a=acq): '' for acq in ['A', 'B', 'unmatched'] } func_struct.update({ '{p}_acq-A_bold.json'.format(p=prefix): { 'ShimSetting': func_shims_A }, '{p}_acq-B_bold.json'.format(p=prefix): { 'ShimSetting': func_shims_B }, '{p}_acq-unmatched_bold.json'.format(p=prefix): { 'ShimSetting': [random() for i in range(SHIM_LENGTH)] }, }) # -fmap: # * Case 1 in https://bids-specification.readthedocs.io/en/stable/04-modality-specific-files/01-magnetic-resonance-imaging-data.html#fieldmap-data fmap_struct = { '{p}_acq-case1_{s}.nii.gz'.format(p=prefix, s=suffix): '' for suffix in ['phasediff', 'magnitude1', 'magnitude2'] } expected_fmap_groups = { '{p}_acq-case1'.format(p=prefix): [ '{p}_acq-case1_phasediff.json'.format( p=op.join(session_path, 'fmap', prefix)) ] } fmap_struct.update({ '{p}_acq-case1_phasediff.json'.format(p=prefix): { 'ShimSetting': dwi_shims } }) # * Case 2: fmap_struct.update({ '{p}_acq-case2_{s}.nii.gz'.format(p=prefix, s=suffix): '' for suffix in ['magnitude1', 'magnitude2', 'phase1', 'phase2'] }) expected_fmap_groups.update({ '{p}_acq-case2'.format(p=prefix): [ '{p}_acq-case2_phase{n}.json'.format(p=op.join( session_path, 'fmap', prefix), n=n) for n in [1, 2] ] }) fmap_struct.update({ '{p}_acq-case2_phase{n}.json'.format(p=prefix, n=n): { 'ShimSetting': func_shims_A } for n in [1, 2] }) # * Case 3: fmap_struct.update({ '{p}_acq-case3_{s}.nii.gz'.format(p=prefix, s=suffix): '' for suffix in ['magnitude', 'fieldmap'] }) expected_fmap_groups.update({ '{p}_acq-case3'.format(p=prefix): [ '{p}_acq-case3_fieldmap.json'.format( p=op.join(session_path, 'fmap', prefix)) ] }) fmap_struct.update({ '{p}_acq-case3_fieldmap.json'.format(p=prefix): { 'ShimSetting': func_shims_B } }) # structure for the full session (init the OrderedDict as a list to preserve order): session_struct = OrderedDict([ ('fmap', fmap_struct), ('dwi', dwi_struct), ('func', func_struct), ]) # add "_scans.tsv" file to the session_struct scans_file_content = generate_scans_tsv(session_struct) session_struct.update( {'{p}_scans.tsv'.format(p=prefix): scans_file_content}) create_tree(session_path, session_struct) # 2) Now, let's create a dict with the fmap groups compatible for each run # -dwi: each of the runs (1, 2) is compatible with case1 fmap: expected_compatible_fmaps = { '{p}_acq-A_run-{r}_dwi.json'.format(p=op.join(session_path, 'dwi', prefix), r=runNo): { key: val for key, val in expected_fmap_groups.items() if key in ['{p}_acq-case1'.format(p=prefix)] } for runNo in [1, 2] } # -func: acq-A is compatible w/ fmap case2; acq-B w/ fmap case3 expected_compatible_fmaps.update({ '{p}_acq-{a}_bold.json'.format(p=op.join(session_path, 'func', prefix), a=acq): { key: val for key, val in expected_fmap_groups.items() if key in ['{p}_acq-case{c}'.format(p=prefix, c=caseNo)] } for caseNo, acq in { '2': 'A', '3': 'B' }.items() }) # -func (cont): acq-unmatched is empty expected_compatible_fmaps.update( { '{p}_acq-unmatched_bold.json'.format(p=op.join( session_path, 'func', prefix)): {} }) # 3) Now, let's create a dict with what we expect for the "IntendedFor": sub_match = re.findall('(sub-([a-zA-Z0-9]*))', session_path) sub_str = sub_match[0][0] expected_prefix = session_path.split(sub_str)[-1].split(op.sep)[-1] # dict, with fmap names as keys and the expected "IntendedFor" as values. expected_result = { '{p}_acq-case1_{s}.json'.format(p=prefix, s='phasediff'): [ op.join(expected_prefix, 'dwi', '{p}_acq-A_run-{r}_dwi.nii.gz'.format(p=prefix, r=r)) for r in [1, 2] ] } expected_result.update({ '{p}_acq-case2_phase{n}.json'.format(p=prefix, n=n): # populate_intended_for writes lists: [ op.join(expected_prefix, 'func', '{p}_acq-A_bold.nii.gz'.format(p=prefix)) ] for n in [1, 2] }) expected_result.update({ '{p}_acq-case3_fieldmap.json'.format(p=prefix): # populate_intended_for writes lists: [ op.join(expected_prefix, 'func', '{p}_acq-B_bold.nii.gz'.format(p=prefix)) ] }) return session_struct, expected_result, expected_fmap_groups, expected_compatible_fmaps
def create_dummy_no_shim_settings_custom_label_bids_session( session_path, label_size=4, label_seed=LABEL_SEED): """ Creates a dummy BIDS session, with slim json files and empty nii.gz The fmap files are pepolar The json files don't have ShimSettings The fmap files have a custom ACQ label matching: - TASK label for <func> modality - ACQ label for any other modality (e.g. <dwi>) Parameters: ---------- session_path : str or os.path path to the session (or subject) level folder label_size : int, optional size of the random label label_seed : int, optional seed for the random label creation Returns: ------- session_struct : dict Structure of the directory that was created expected_result : dict dictionary with fmap names as keys and the expected "IntendedFor" as values. None it returns a third argument (None) to have the same signature as create_dummy_pepolar_bids_session """ session_parent, session_basename = op.split(session_path.rstrip(op.sep)) if session_basename.startswith('ses-'): prefix = op.split(session_parent)[1] + '_' + session_basename else: prefix = session_basename # 1) Simulate the file structure for a session: # Dict with the file structure for the session. # All json files will be empty. # -anat: anat_struct = { f'{prefix}_{mod}.{ext}': dummy_content for ext, dummy_content in zip(['nii.gz', 'json'], ['', {}]) for mod in ['T1w', 'T2w'] } # -dwi: label_seed += 1 DWI_LABEL = gen_rand_label(label_size, label_seed) dwi_struct = { f'{prefix}_acq-{DWI_LABEL}_run-{runNo}_dwi.{ext}': dummy_content for ext, dummy_content in zip(['nii.gz', 'json'], ['', {}]) for runNo in [1, 2] } # -func: label_seed += 1 FUNC_LABEL = gen_rand_label(label_size, label_seed) func_struct = { f'{prefix}_task-{FUNC_LABEL}_acq-{acq}_bold.{ext}': dummy_content for ext, dummy_content in zip(['nii.gz', 'json'], ['', {}]) for acq in ['A', 'B'] } # -fmap: fmap_struct = { f'{prefix}_acq-{acq}_dir-{d}_run-{r}_epi.{ext}': dummy_content for ext, dummy_content in zip(['nii.gz', 'json'], ['', {}]) for acq in [DWI_LABEL, FUNC_LABEL] for d in ['AP', 'PA'] for r in [1, 2] } expected_fmap_groups = { f'{prefix}_acq-{acq}_run-{r}_epi': [ f'{op.join(session_path, "fmap", prefix)}_acq-{acq}_dir-{d}_run-{r}_epi.json' for d in ['AP', 'PA'] ] for acq in [DWI_LABEL, FUNC_LABEL] for r in [1, 2] } # structure for the full session (init the OrderedDict as a list to preserve order): session_struct = OrderedDict([ ('fmap', fmap_struct), ('anat', anat_struct), ('dwi', dwi_struct), ('func', func_struct), ]) # add "_scans.tsv" file to the session_struct scans_file_content = generate_scans_tsv(session_struct) session_struct.update( {'{p}_scans.tsv'.format(p=prefix): scans_file_content}) create_tree(session_path, session_struct) # 2) Now, let's create a dict with the fmap groups compatible for each run # -anat: empty expected_compatible_fmaps = { f'{op.join(session_path, "anat", prefix)}_{mod}.json': {} for mod in ['T1w', 'T2w'] } # -dwi: each of the runs (1, 2) is compatible with both of the dwi fmaps (1, 2): expected_compatible_fmaps.update({ f'{op.join(session_path, "dwi", prefix)}_acq-{DWI_LABEL}_run-{runNo}_dwi.json': { key: val for key, val in expected_fmap_groups.items() if key in [f'{prefix}_acq-{DWI_LABEL}_run-{r}_epi' for r in [1, 2]] } for runNo in [1, 2] }) # -func: each of the acq (A, B) is compatible w/ both fmap fMRI runs (1, 2) expected_compatible_fmaps.update({ f'{op.join(session_path, "func", prefix)}_task-{FUNC_LABEL}_acq-{acq}_bold.json': { key: val for key, val in expected_fmap_groups.items() if key in [f'{prefix}_acq-{FUNC_LABEL}_run-{r}_epi' for r in [1, 2]] } for acq in ['A', 'B'] }) # 3) Now, let's create a dict with what we expect for the "IntendedFor": # NOTE: The "expected_prefix" (the beginning of the path to the # "IntendedFor") should be relative to the subject level (see: # https://bids-specification.readthedocs.io/en/stable/04-modality-specific-files/01-magnetic-resonance-imaging-data.html#fieldmap-data) sub_match = re.findall('(sub-([a-zA-Z0-9]*))', session_path) sub_str = sub_match[0][0] expected_prefix = session_path.split(sub_str)[-1].split(op.sep)[-1] # dict, with fmap names as keys and the expected "IntendedFor" as values. expected_result = { # (runNo=1 goes with the long list, runNo=2 goes with None): f'{prefix}_acq-{DWI_LABEL}_dir-{d}_run-{runNo}_epi.json': intended_for for runNo, intended_for in zip([1, 2], [[ op.join(expected_prefix, 'dwi', f'{prefix}_acq-{DWI_LABEL}_run-{r}_dwi.nii.gz') for r in [1, 2] ], None]) for d in ['AP', 'PA'] } expected_result.update({ # The first "fMRI" run gets all files in the "func" folder; # the second shouldn't get any. f'{prefix}_acq-{FUNC_LABEL}_dir-{d}_run-{runNo}_epi.json': intended_for for runNo, intended_for in zip([1, 2], [[ op.join(expected_prefix, 'func', f'{prefix}_task-{FUNC_LABEL}_acq-{acq}_bold.nii.gz') for acq in ['A', 'B'] ], None]) for d in ['AP', 'PA'] }) return session_struct, expected_result, expected_fmap_groups, expected_compatible_fmaps
def create_dummy_no_shim_settings_bids_session(session_path): """ Creates a dummy BIDS session, with slim json files and empty nii.gz The fmap files are pepolar The json files don't have ShimSettings Parameters: ---------- session_path : str or os.path path to the session (or subject) level folder Returns: ------- session_struct : dict Structure of the directory that was created expected_result : dict dictionary with fmap names as keys and the expected "IntendedFor" as values. None it returns a third argument (None) to have the same signature as create_dummy_pepolar_bids_session """ session_parent, session_basename = op.split(session_path.rstrip(op.sep)) if session_basename.startswith('ses-'): prefix = op.split(session_parent)[1] + '_' + session_basename else: prefix = session_basename # 1) Simulate the file structure for a session: # Dict with the file structure for the session. # All json files will be empty. # -anat: anat_struct = { '{p}_{m}.{e}'.format(p=prefix, m=mod, e=ext): dummy_content for ext, dummy_content in zip(['nii.gz', 'json'], ['', {}]) for mod in ['T1w', 'T2w'] } # -dwi: dwi_struct = { '{p}_acq-A_run-{r}_dwi.{e}'.format(p=prefix, r=runNo, e=ext): dummy_content for ext, dummy_content in zip(['nii.gz', 'json'], ['', {}]) for runNo in [1, 2] } # -func: func_struct = { '{p}_acq-{a}_bold.{e}'.format(p=prefix, a=acq, e=ext): dummy_content for ext, dummy_content in zip(['nii.gz', 'json'], ['', {}]) for acq in ['A', 'B'] } # -fmap: fmap_struct = { '{p}_acq-{a}_dir-{d}_run-{r}_epi.{e}'.format(p=prefix, a=acq, d=d, r=r, e=ext): dummy_content for ext, dummy_content in zip(['nii.gz', 'json'], ['', {}]) for acq in ['dwi', 'fMRI'] for d in ['AP', 'PA'] for r in [1, 2] } expected_fmap_groups = { '{p}_acq-{a}_run-{r}_epi'.format(p=prefix, a=acq, r=r): [ '{p}_acq-{a}_dir-{d}_run-{r}_epi.json'.format(p=op.join( session_path, 'fmap', prefix), a=acq, d=d, r=r) for d in ['AP', 'PA'] ] for acq in ['dwi', 'fMRI'] for r in [1, 2] } # structure for the full session (init the OrderedDict as a list to preserve order): session_struct = OrderedDict([ ('fmap', fmap_struct), ('anat', anat_struct), ('dwi', dwi_struct), ('func', func_struct), ]) # add "_scans.tsv" file to the session_struct scans_file_content = generate_scans_tsv(session_struct) session_struct.update( {'{p}_scans.tsv'.format(p=prefix): scans_file_content}) create_tree(session_path, session_struct) # 2) Now, let's create a dict with the fmap groups compatible for each run # -anat: empty expected_compatible_fmaps = { '{p}_{m}.json'.format(p=op.join(session_path, 'anat', prefix), m=mod): {} for mod in ['T1w', 'T2w'] } # -dwi: each of the runs (1, 2) is compatible with both of the dwi fmaps (1, 2): expected_compatible_fmaps.update({ '{p}_acq-A_run-{r}_dwi.json'.format(p=op.join(session_path, 'dwi', prefix), r=runNo): { key: val for key, val in expected_fmap_groups.items() if key in ['{p}_acq-dwi_run-{r}_epi'.format(p=prefix, r=r) for r in [1, 2]] } for runNo in [1, 2] }) # -func: each of the acq (A, B) is compatible w/ both fmap fMRI runs (1, 2) expected_compatible_fmaps.update({ '{p}_acq-{a}_bold.json'.format(p=op.join(session_path, 'func', prefix), a=acq): { key: val for key, val in expected_fmap_groups.items() if key in ['{p}_acq-fMRI_run-{r}_epi'.format(p=prefix, r=r) for r in [1, 2]] } for acq in ['A', 'B'] }) # 3) Now, let's create a dict with what we expect for the "IntendedFor": # NOTE: The "expected_prefix" (the beginning of the path to the # "IntendedFor") should be relative to the subject level (see: # https://bids-specification.readthedocs.io/en/stable/04-modality-specific-files/01-magnetic-resonance-imaging-data.html#fieldmap-data) sub_match = re.findall('(sub-([a-zA-Z0-9]*))', session_path) sub_str = sub_match[0][0] expected_prefix = session_path.split(sub_str)[-1].split(op.sep)[-1] # dict, with fmap names as keys and the expected "IntendedFor" as values. expected_result = { # (runNo=1 goes with the long list, runNo=2 goes with None): '{p}_acq-dwi_dir-{d}_run-{r}_epi.json'.format(p=prefix, d=d, r=runNo): intended_for for runNo, intended_for in zip([1, 2], [[ op.join(expected_prefix, 'dwi', '{p}_acq-A_run-{r}_dwi.nii.gz'.format(p=prefix, r=r)) for r in [1, 2] ], None]) for d in ['AP', 'PA'] } expected_result.update({ # The first "fMRI" run gets all files in the "func" folder; # the second shouldn't get any. '{p}_acq-fMRI_dir-{d}_run-{r}_epi.json'.format(p=prefix, d=d, r=runNo): intended_for for runNo, intended_for in zip([1, 2], [[ op.join(expected_prefix, 'func', '{p}_acq-{a}_bold.nii.gz'.format( p=prefix, a=acq)) for acq in ['A', 'B'] ], None]) for d in ['AP', 'PA'] }) return session_struct, expected_result, expected_fmap_groups, expected_compatible_fmaps
def create_dummy_pepolar_bids_session(session_path): """ Creates a dummy BIDS session, with slim json files and empty nii.gz The fmap files are pepolar The json files have ShimSettings Parameters: ---------- session_path : str or os.path path to the session (or subject) level folder Returns: ------- session_struct : dict Structure of the directory that was created expected_result : dict dictionary with fmap names as keys and the expected "IntendedFor" as values. expected_fmap_groups : dict dictionary with the expected fmap groups expected_compatible_fmaps : dict dictionary with the expected fmap groups for each non-fmap run in the session """ session_parent, session_basename = op.split(session_path.rstrip(op.sep)) if session_basename.startswith('ses-'): prefix = op.split(session_parent)[1] + '_' + session_basename else: prefix = session_basename # 1) Simulate the file structure for a session: # Generate some random ShimSettings: anat_shims = [random() for i in range(SHIM_LENGTH)] dwi_shims = [random() for i in range(SHIM_LENGTH)] func_shims_A = [random() for i in range(SHIM_LENGTH)] func_shims_B = [random() for i in range(SHIM_LENGTH)] # Dict with the file structure for the session: # -anat: anat_struct = { '{p}_{m}.{e}'.format(p=prefix, m=mod, e=ext): dummy_content for ext, dummy_content in zip(['nii.gz', 'json'], ['', { 'ShimSetting': anat_shims }]) for mod in ['T1w', 'T2w'] } # -dwi: dwi_struct = { '{p}_acq-A_run-{r}_dwi.nii.gz'.format(p=prefix, r=runNo): '' for runNo in [1, 2] } dwi_struct.update({ '{p}_acq-A_run-{r}_dwi.json'.format(p=prefix, r=runNo): { 'ShimSetting': dwi_shims } for runNo in [1, 2] }) # -func: func_struct = { '{p}_acq-{a}_bold.nii.gz'.format(p=prefix, a=acq): '' for acq in ['A', 'B', 'unmatched'] } func_struct.update({ '{p}_acq-A_bold.json'.format(p=prefix): { 'ShimSetting': func_shims_A }, '{p}_acq-B_bold.json'.format(p=prefix): { 'ShimSetting': func_shims_B }, '{p}_acq-unmatched_bold.json'.format(p=prefix): { 'ShimSetting': [random() for i in range(SHIM_LENGTH)] }, }) # -fmap: # * NIfTI files: fmap_struct = { '{p}_acq-{a}_dir-{d}_run-{r}_epi.nii.gz'.format(p=prefix, a=acq, d=d, r=r): '' for acq in ['dwi', 'fMRI'] for d in ['AP', 'PA'] for r in [1, 2] } # * dwi shims: expected_fmap_groups = { '{p}_acq-dwi_run-{r}_epi'.format(p=prefix, r=r): [ '{p}_acq-dwi_dir-{d}_run-{r}_epi.json'.format(p=op.join( session_path, 'fmap', prefix), d=d, r=r) for d in ['AP', 'PA'] ] for r in [1, 2] } fmap_struct.update({ '{p}_acq-dwi_dir-{d}_run-{r}_epi.json'.format(p=prefix, d=d, r=r): { 'ShimSetting': dwi_shims } for d in ['AP', 'PA'] for r in [1, 2] }) # * func_shims (_A and _B): expected_fmap_groups.update({ '{p}_acq-fMRI_run-{r}_epi'.format(p=prefix, r=r): [ '{p}_acq-fMRI_dir-{d}_run-{r}_epi.json'.format(p=op.join( session_path, 'fmap', prefix), d=d, r=r) for d in ['AP', 'PA'] ] for r in [1, 2] }) fmap_struct.update({ '{p}_acq-fMRI_dir-{d}_run-{r}_epi.json'.format(p=prefix, d=d, r=r): { 'ShimSetting': shims } for r, shims in { '1': func_shims_A, '2': func_shims_B }.items() for d in ['AP', 'PA'] }) # structure for the full session (init the OrderedDict as a list to preserve order): session_struct = OrderedDict([ ('fmap', fmap_struct), ('anat', anat_struct), ('dwi', dwi_struct), ('func', func_struct), ]) # add "_scans.tsv" file to the session_struct scans_file_content = generate_scans_tsv(session_struct) session_struct.update( {'{p}_scans.tsv'.format(p=prefix): scans_file_content}) create_tree(session_path, session_struct) # 2) Now, let's create a dict with the fmap groups compatible for each run # -anat: empty expected_compatible_fmaps = { '{p}_{m}.json'.format(p=op.join(session_path, 'anat', prefix), m=mod): {} for mod in ['T1w', 'T2w'] } # -dwi: each of the runs (1, 2) is compatible with both of the dwi fmaps (1, 2): expected_compatible_fmaps.update({ '{p}_acq-A_run-{r}_dwi.json'.format(p=op.join(session_path, 'dwi', prefix), r=runNo): { key: val for key, val in expected_fmap_groups.items() if key in ['{p}_acq-dwi_run-{r}_epi'.format(p=prefix, r=r) for r in [1, 2]] } for runNo in [1, 2] }) # -func: acq-A is compatible w/ fmap fMRI run 1; acq-2 w/ fmap fMRI run 2 expected_compatible_fmaps.update({ '{p}_acq-{a}_bold.json'.format(p=op.join(session_path, 'func', prefix), a=acq): { key: val for key, val in expected_fmap_groups.items() if key in ['{p}_acq-fMRI_run-{r}_epi'.format(p=prefix, r=runNo)] } for runNo, acq in { '1': 'A', '2': 'B' }.items() }) # -func (cont): acq-unmatched is empty expected_compatible_fmaps.update( { '{p}_acq-unmatched_bold.json'.format(p=op.join( session_path, 'func', prefix)): {} }) # 3) Then, let's create a dict with what we expect for the "IntendedFor": sub_match = re.findall('(sub-([a-zA-Z0-9]*))', session_path) sub_str = sub_match[0][0] expected_prefix = session_path.split(sub_str)[-1].split(op.sep)[-1] # dict, with fmap names as keys and the expected "IntendedFor" as values. expected_result = { '{p}_acq-dwi_dir-{d}_run-{r}_epi.json'.format(p=prefix, d=d, r=runNo): intended_for # (runNo=1 goes with the long list, runNo=2 goes with None): for runNo, intended_for in zip([1, 2], [[ op.join(expected_prefix, 'dwi', '{p}_acq-A_run-{r}_dwi.nii.gz'.format(p=prefix, r=r)) for r in [1, 2] ], None]) for d in ['AP', 'PA'] } expected_result.update({ '{p}_acq-fMRI_dir-{d}_run-{r}_epi.json'.format(p=prefix, d=d, r=runNo): [ op.join(expected_prefix, 'func', '{p}_acq-{a}_bold.nii.gz'.format(p=prefix, a=acq)) ] # runNo=1 goes with acq='A'; runNo=2 goes with acq='B' for runNo, acq in zip([1, 2], ['A', 'B']) for d in ['AP', 'PA'] }) return session_struct, expected_result, expected_fmap_groups, expected_compatible_fmaps