Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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