Exemple #1
0
def test_get_shim_setting(tmpdir, fname, content, expected_return):
    """ Tests for get_shim_setting """
    json_name = op.join(str(tmpdir), fname)
    json_dir = op.dirname(json_name)
    if not op.exists(json_dir):
        os.makedirs(json_dir)
    save_json(json_name, content)
    assert get_shim_setting(json_name) == expected_return
Exemple #2
0
def embed_dicom_and_nifti_metadata(dcmfiles, niftifile, infofile, bids_info):
    """Embed metadata from nifti (affine etc) and dicoms into infofile (json)

    `niftifile` should exist. Its affine's orientation information is used while
    establishing new `NiftiImage` out of dicom stack and together with `bids_info`
    (if provided) is dumped into json `infofile`

    Parameters
    ----------
    dcmfiles
    niftifile
    infofile
    bids_info: dict
      Additional metadata to be embedded. `infofile` is overwritten if exists,
      so here you could pass some metadata which would overload (at the first
      level of the dict structure, no recursive fancy updates) what is obtained
      from nifti and dicoms

    """
    # imports for nipype
    import nibabel as nb
    import os.path as op
    import json
    import re
    from heudiconv.utils import save_json

    from heudiconv.external.dcmstack import ds
    stack = ds.parse_and_stack(dcmfiles, force=True).values()
    if len(stack) > 1:
        raise ValueError('Found multiple series')
    # may be odict now - iter to be safe
    stack = next(iter(stack))

    if not op.exists(niftifile):
        raise NotImplementedError(
            "%s does not exist. "
            "We are not producing new nifti files here any longer. "
            "Use dcm2niix directly or .convert.nipype_convert helper ."
            % niftifile
        )

    orig_nii = nb.load(niftifile)
    aff = orig_nii.affine
    ornt = nb.orientations.io_orientation(aff)
    axcodes = nb.orientations.ornt2axcodes(ornt)
    new_nii = stack.to_nifti(voxel_order=''.join(axcodes), embed_meta=True)
    meta_info = ds.NiftiWrapper(new_nii).meta_ext.to_json()
    meta_info = json.loads(meta_info)

    if bids_info:
        meta_info.update(bids_info)

    # write to outfile
    save_json(infofile, meta_info)
Exemple #3
0
def test_get_shim_setting(tmpdir):
    """ Tests for get_shim_setting """
    json_dir = op.join(str(tmpdir), 'foo')
    if not op.exists(json_dir):
        os.makedirs(json_dir)
    json_name = op.join(json_dir, 'sub-foo.json')
    # 1) file with no "ShimSetting", should return None
    save_json(json_name, {})
    with pytest.raises(KeyError):
        assert get_shim_setting(json_name)

    # -file with "ShimSetting" field
    save_json(json_name, {SHIM_KEY: A_SHIM})
    assert get_shim_setting(json_name) == A_SHIM
Exemple #4
0
def test_get_key_info_for_fmap_assignment(tmpdir, monkeypatch):
    """
    Test get_key_info_for_fmap_assignment
    """

    # Stuff needed to mock reading of a NIfTI file header:

    # affines (qforms/sforms) are 4x4 matrices
    MY_AFFINE = [[random() for i in range(4)] for j in range(4)]
    # dims are arrays with 8 elements with the first one indicating the number
    # of dims in the image; remaining elements are 1:
    MY_DIM = [4] + [round(256 * random()) for i in range(4)] + [1] * 3
    # We use namedtuples so that we can use the .dot notation, to mock
    # nibabel headers:
    MyHeader = namedtuple('MyHeader', 'affine dim')
    MY_HEADER = MyHeader(MY_AFFINE, MY_DIM)
    MyMockNifti = namedtuple('MyMockNifti', 'header')

    def mock_nibabel_load(file):
        """
        Pretend we run nibabel.load, but return only a header with just a few fields
        """
        return MyMockNifti(MY_HEADER)
    monkeypatch.setattr(nibabel, "load", mock_nibabel_load)

    json_name = op.join(str(tmpdir), 'foo.json')

    # 1) Call for a non-existing file should give an error:
    with pytest.raises(FileNotFoundError):
        assert get_key_info_for_fmap_assignment('foo.json')

    # 2) matching_parameters = 'Shims'
    save_json(json_name, {SHIM_KEY: A_SHIM})      # otherwise get_key_info_for_fmap_assignment will give an error
    key_info = get_key_info_for_fmap_assignment(
        json_name, matching_parameter='Shims'
    )
    assert key_info == [A_SHIM]

    # 3) matching_parameters = 'ImagingVolume'
    key_info = get_key_info_for_fmap_assignment(
        json_name, matching_parameter='ImagingVolume'
    )
    assert key_info == [MY_AFFINE, MY_DIM[1:3]]

    # 4) invalid matching_parameters:
    with pytest.raises(ValueError):
        assert get_key_info_for_fmap_assignment(
            json_name, matching_parameter='Invalid'
        )
Exemple #5
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
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
Exemple #7
0
def test_update_json(tmpdir):
    """
    Test utils.update_json()
    """
    dummy_json_file = str(tmpdir / 'dummy.json')
    some_content = {"name": "Jason", "age": 30, "city": "New York"}
    save_json(dummy_json_file, some_content, pretty=True)

    added_content = {
        "LastName":
        "Bourne",
        "Movies": [
            "The Bourne Identity", "The Bourne Supremacy",
            "The Bourne Ultimatum", "The Bourne Legacy", "Jason Bourne"
        ]
    }
    update_json(dummy_json_file, added_content)

    # check that it was added:
    with open(dummy_json_file) as f:
        data = json.load(f)
    some_content.update(added_content)
    assert data == some_content
Exemple #8
0
def test_get_key_info_for_fmap_assignment(tmpdir,
                                          label_size=4,
                                          label_seed=LABEL_SEED):
    """
    Test get_key_info_for_fmap_assignment.
    
    label_size and label_seed are used for the "CustomAcquisitionLabel" matching
    parameter. label_size is the size of the random label while label_seed is 
    the seed for the random label creation.
    """

    nifti_file = op.join(TESTS_DATA_PATH, 'sample_nifti.nii.gz')
    # Get the expected parameters from the NIfTI header:
    MY_HEADER = nibabel.ni1.np.loadtxt(
        op.join(TESTS_DATA_PATH,
                remove_suffix(nifti_file, '.nii.gz') + '_params.txt'))
    json_name = op.join(TESTS_DATA_PATH,
                        remove_suffix(nifti_file, '.nii.gz') + '.json')

    # 1) Call for a non-existing file should give an error:
    with pytest.raises(FileNotFoundError):
        assert get_key_info_for_fmap_assignment('foo.json', 'ImagingVolume')

    # 2) matching_parameters = 'Shims'
    json_name = op.join(TESTS_DATA_PATH,
                        remove_suffix(nifti_file, '.nii.gz') + '.json')
    save_json(
        json_name,
        {SHIM_KEY: A_SHIM
         })  # otherwise get_key_info_for_fmap_assignment will give an error
    key_info = get_key_info_for_fmap_assignment(json_name,
                                                matching_parameter='Shims')
    assert key_info == [A_SHIM]

    # 3) matching_parameters = 'ImagingVolume'
    key_info = get_key_info_for_fmap_assignment(
        json_name, matching_parameter='ImagingVolume')
    np_testing.assert_almost_equal(key_info[0], MY_HEADER[:4], decimal=6)
    np_testing.assert_almost_equal(key_info[1], MY_HEADER[4][:3], decimal=6)

    # 4) matching_parameters = 'Force'
    key_info = get_key_info_for_fmap_assignment(json_name,
                                                matching_parameter='Force')
    assert key_info == [KeyInfoForForce]

    # 5) matching_parameter = 'ModalityAcquisitionLabel'
    for d in ['fmap', 'func', 'dwi', 'anat']:
        Path(op.join(str(tmpdir), d)).mkdir(parents=True, exist_ok=True)
    for (dirname, fname, expected_key_info) in [
        ('fmap', 'sub-foo_acq-fmri_epi.json', 'func'),
        ('fmap', 'sub-foo_acq-bold_epi.json', 'func'),
        ('fmap', 'sub-foo_acq-func_epi.json', 'func'),
        ('fmap', 'sub-foo_acq-diff_epi.json', 'dwi'),
        ('fmap', 'sub-foo_acq-anat_epi.json', 'anat'),
        ('fmap', 'sub-foo_acq-struct_epi.json', 'anat'),
        ('func', 'sub-foo_bold.json', 'func'),
        ('dwi', 'sub-foo_dwi.json', 'dwi'),
        ('anat', 'sub-foo_T1w.json', 'anat'),
    ]:
        json_name = op.join(str(tmpdir), dirname, fname)
        save_json(json_name, {SHIM_KEY: A_SHIM})
        assert [expected_key_info] == get_key_info_for_fmap_assignment(
            json_name, matching_parameter='ModalityAcquisitionLabel')

    # 6) matching_parameter = 'CustomAcquisitionLabel'
    A_LABEL = gen_rand_label(label_size, label_seed)
    for d in ['fmap', 'func', 'dwi', 'anat']:
        Path(op.join(str(tmpdir), d)).mkdir(parents=True, exist_ok=True)

    for (dirname, fname, expected_key_info) in [
        ('fmap', f'sub-foo_acq-{A_LABEL}_epi.json', A_LABEL),
        ('func', f'sub-foo_task-{A_LABEL}_acq-foo_bold.json', A_LABEL),
        ('dwi', f'sub-foo_acq-{A_LABEL}_dwi.json', A_LABEL),
        ('anat', f'sub-foo_acq-{A_LABEL}_T1w.json', A_LABEL),
    ]:
        json_name = op.join(str(tmpdir), dirname, fname)
        save_json(json_name, {SHIM_KEY: A_SHIM})
        assert [expected_key_info] == get_key_info_for_fmap_assignment(
            json_name, matching_parameter='CustomAcquisitionLabel')

    # Finally: invalid matching_parameters:
    assert get_key_info_for_fmap_assignment(
        json_name, matching_parameter='Invalid') == []