Ejemplo n.º 1
0
def estimate_bold_prf(bold_file, method):
    prf_task = Task(bold_file)
    stimuli = read_prf_stimuli(prf_task)

    region_idx = 11143
    aparc = nload(str(data_aparc))

    img = nload(str(prf_task.filename))
    mri = img.get_data()

    roi = select_region(aparc, lambda x: x == region_idx)
    roi_idx = apply_affine(img.affine, array(where(roi.get_data() > 0)).T)
    roi_str = [f'{xyz[0]:.2f},{xyz[1]:.2f},{xyz[2]:.2f}' for xyz in roi_idx]

    dat = mri[roi.get_data() > 0, :]

    output = compute_prf(bold_file, dat, roi_str, stimuli, method)

    images = ['X', 'Y', 'SIGMA', 'BETA']
    for i in range(len(output)):
        nii_file = replace_extension(bold_file, 'prf' + images[i] + '.nii.gz')

        out = zeros(mri.shape[:3])
        out[roi.get_data() > 0] = output[i]
        x_img = Nifti1Image(out, img.affine)
        x_img.to_filename(str(nii_file))
Ejemplo n.º 2
0
def compute_percent(feat_path, normalize_to_mean):
    """Calculate percent change for a task.

    Parameters
    ----------

    Returns
    -------
    instance of nibabel.Nifti1Image
        percent change as image
    """
    design = read_design(feat_path)

    pe_mri = nload(str(feat_path / 'stats' / 'pe1.nii.gz'))

    pe = pe_mri.get_data()
    pe[pe == 0] = NaN
    perc = pe * 100 * design.ptp()

    if normalize_to_mean:
        """I'm not sure if this is necessary, but for sure it increases the level
        of noise"""
        mean_mri = nload(str(feat_path / 'mean_func.nii.gz'))
        mean_func = mean_mri.get_data()
        array_equal(pe_mri.affine, mean_mri.affine)
        with errstate(invalid='ignore'):
            perc /= mean_func

    mask_mri = nload(str(feat_path / 'mask.nii.gz'))
    mask = mask_mri.get_data().astype(bool)
    perc[~mask] = NaN

    return Nifti1Image(perc, pe_mri.affine)
Ejemplo n.º 3
0
def ribbon2graymatter(ribbon_files, output_dir):
    graymatter_file = output_dir / 'graymatter.nii.gz'

    ribbon_rh_file = [x for x in ribbon_files if x.endswith('rh.ribbon.mgz')][0]
    ribbon_lh_file = [x for x in ribbon_files if x.endswith('lh.ribbon.mgz')][0]

    ribbon_rh = nload(str(ribbon_rh_file))
    ribbon_lh = nload(str(ribbon_lh_file))
    graymatter = ribbon_rh.get_data() + ribbon_lh.get_data()

    nifti = Nifti1Image(graymatter, ribbon_rh.affine)
    nifti.to_filename(str(graymatter_file))

    return graymatter_file
Ejemplo n.º 4
0
def create_bold(bold_file, taskname, region_idx, timeseries):

    aparc = nload(str(data_aparc))

    brain = select_region(aparc, lambda x: x > 0)
    act = select_region(aparc, lambda x: x == region_idx)

    t = timeseries.shape[0]

    random.seed(100)
    idx = where(brain.get_data() == 1)
    r = random.randn(idx[0].shape[0], t)

    bold = ones(brain.get_data().shape + (t, ))
    bold[act.get_data() == 1, :] = timeseries
    bold[idx] += r

    nifti = Nifti1Image(bold.astype('float32'), brain.affine)
    nifti.header['pixdim'][4] = TR
    nifti.header.set_xyzt_units('mm', 'sec')
    nifti.to_filename(str(bold_file))

    d = {
        'RepetitionTime': TR,
        'TaskName': taskname,
    }

    json_bold = replace_extension(bold_file, '.json')
    with json_bold.open('w') as f:
        dump(d, f, ensure_ascii=False, indent=' ')
Ejemplo n.º 5
0
def calc_fmri_at_elec(measure_nii, electrodes_file, distance, kernels,
                      graymatter, output_dir):
    """
    Calculate the (weighted) average of fMRI values at electrode locations
    """
    electrodes = Electrodes(electrodes_file)

    img = nload(str(measure_nii))
    mri = img.get_data()
    mri[mri == 0] = NaN

    labels = electrodes.electrodes.get(map_lambda=lambda x: x['name'])
    chan_xyz = array(electrodes.get_xyz())

    nd = array(list(ndindex(mri.shape)))
    ndi = from_mrifile_to_chan(img, nd)

    if graymatter:
        gm_mri = nload(str(graymatter)).get_data().astype(bool)
        mri[~gm_mri] = NaN

    lg.debug(
        f'Computing fMRI values for {measure_nii.name} at {len(labels)} electrodes and {len(kernels)} "{distance}" kernels'
    )
    fmri_vals, n_voxels = compute_kernels(kernels, chan_xyz, mri, ndi,
                                          distance)

    fmri_vals_tsv = output_dir / replace_underscore(measure_nii.name,
                                                    'compare.tsv')
    n_voxels_tsv = output_dir / replace_underscore(measure_nii.name,
                                                   'nvoxels.tsv')

    with fmri_vals_tsv.open('w') as f:
        f.write('channel\t' + '\t'.join(str(one_k)
                                        for one_k in kernels) + '\n')
        for one_label, val_at_elec in zip(labels, fmri_vals):
            f.write(one_label + '\t' +
                    '\t'.join(str(one_val) for one_val in val_at_elec) + '\n')

    with n_voxels_tsv.open('w') as f:
        f.write('channel\t' + '\t'.join(str(one_k)
                                        for one_k in kernels) + '\n')
        for one_label, val_at_elec in zip(labels, n_voxels):
            f.write(one_label + '\t' +
                    '\t'.join(str(one_val) for one_val in val_at_elec) + '\n')

    return fmri_vals_tsv, n_voxels_tsv
Ejemplo n.º 6
0
def simulate_anat(root, task_anat, t1):
    mri = nload(str(t1))
    x = mri.get_data()
    nifti = Nifti1Image(x, mri.affine)

    anat_path = task_anat.get_filename(root)
    anat_path.parent.mkdir(exist_ok=True, parents=True)
    nifti.to_filename(str(anat_path))

    return file_Core(
        anat_path)  # use the general file_Core (Task needs events.tsv)
Ejemplo n.º 7
0
    def surface_ras_shift(self):
        """Freesurfer uses two coordinate systems: one for volumes ("RAS") and
        one for surfaces ("tkReg", "tkRAS", and "Surface RAS").
        To get from surface to volume coordinates, add this numbers.
        To get from volume to surface coordinates, substract this numbers.
        """
        T1_path = self.dir / 'mri' / 'T1.mgz'
        assert T1_path.exists()

        T1 = nload(str(T1_path))

        return T1.header['Pxyz_c']
Ejemplo n.º 8
0
def plot_surf(img_dir, freesurfer_dir, info, surface):

    fs = Freesurfer(freesurfer_dir / info['subject'])
    surf = getattr(fs.read_brain(surface), info['hemi'])

    surf_img = nload(str(info['surf']))
    surf_val = surf_img.get_data()[:, 0, 0].astype('float64')

    v = Viz3()
    v.add_surf(surf, values=surf_val, limits_c=(-6, 6), colorbar=True)
    v.save(img_dir / (info['surf'].stem + '.png'))
    v.close()
Ejemplo n.º 9
0
def test_channel_sphere():
    xyz = chan.return_xyz()[0, :]
    fs = Freesurfer(fs_path)
    mask = create_sphere_around_elec(xyz,
                                     template_mri_path,
                                     distance=8,
                                     freesurfer=fs)
    assert mask.sum() == 4

    template_mri = nload(str(template_mri_path))

    xyz_volume = xyz + fs.surface_ras_shift
    mask = create_sphere_around_elec(xyz, template_mri, distance=16)
    assert mask.sum() == 35
Ejemplo n.º 10
0
    def surface_ras_shift(self):
        """Freesurfer uses two coordinate systems: one for volumes ("RAS") and
        one for surfaces ("tkReg", "tkRAS", and "Surface RAS").
        To get from surface to volume coordinates, add this numbers.
        To get from volume to surface coordinates, substract this numbers.
        """
        T1_path = self.dir / 'mri' / 'T1.mgz'
        assert T1_path.exists()

        try:
            T1 = nload(str(T1_path))
        except NameError:
            raise ImportError('nibabel needs to be installed for this function')

        return T1.header['Pxyz_c']
Ejemplo n.º 11
0
def get_vox2ras_tkr(filename):
    """This should be identical
    mri_info --vox2ras-tkr filename
    """
    img = nload(str(filename))

    Nc, Nr, Ns = img.shape[:3]
    dC, dR, dS = img.header['pixdim'][1:4]
    vox2ras_tkr = array([
        [-dC, 0, 0, Nc / 2 * dC],
        [0, 0, dS, -Ns / 2 * dS],
        [0, -dR, 0, Nr / 2 * dR],
        [0, 0, 0, 1],
    ])

    return vox2ras_tkr
Ejemplo n.º 12
0
def create_sphere_around_elec(xyz, template_mri, distance=8, freesurfer=None):
    """Create an MRI mask around an electrode location,

    Parameters
    ----------
    xyz : ndarray
        3x0 array
    template_mri : path or str (as path) or nibabel.Nifti
        (path to) MRI to be used as template
    distance : float
        distance in mm between electrode and selected voxels
    freesurfer : instance of Freesurfer
        to adjust RAS coordinates, see Notes

    Returns
    -------
    3d bool ndarray
        mask where True voxels are within selected distance to the electrode

    Notes
    -----
    Freesurfer uses two coordinate systems: one for volumes ("RAS") and one for
    surfaces ("tkReg", "tkRAS", and "Surface RAS"), so the electrodes might be
    stored in one of the two systems. If the electrodes are in surface
    coordinates (f.e. if you can plot surface and electrodes in the same space),
    then you need to convert the coordinate system. This is done by passing an
    instance of Freesurfer.
    """
    if freesurfer is None:
        shift = 0
    else:
        shift = freesurfer.surface_ras_shift

    if isinstance(template_mri, str) or isinstance(template_mri, Path):
        try:
            template_mri = nload(str(template_mri))
        except NameError:
            raise ImportError('nibabel needs to be installed for this function')

    mask = zeros(template_mri.shape, dtype='bool')
    for vox in ndindex(template_mri.shape):
        vox_ras = apply_affine(template_mri.affine, vox) - shift
        if norm(xyz - vox_ras) <= distance:
            mask[vox] = True

    return mask
Ejemplo n.º 13
0
def project_mri_to_surf(fmri_file, vert, kernel):
    img = nload(str(fmri_file))
    mri = img.get_fdata()
    mri[mri == 0] = NaN

    nd = array(list(ndindex(mri.shape)))
    ndi = from_mrifile_to_chan(img, nd)

    partial_compute_chan = partial(compute_chan,
                                   KERNEL=kernel,
                                   ndi=ndi,
                                   mri=mri,
                                   distance='gaussian')

    with Pool() as p:
        fmri_vals = p.map(partial_compute_chan, vert)
    fmri_vals = [x[0] for x in fmri_vals]

    return fmri_vals
Ejemplo n.º 14
0
def mri_nan2zero(input_nii):
    """Remove NaN values and turn them into zeros (so that Freesurfer can handle
    them)

    Parameters
    ----------
    input_nii : Path
        path to nii.gz containing NaN

    Returns
    -------
    Path
        path to temporary nii.gz containing no NaN. You can remove the file
        with .unlink()
    """
    img = nload(str(input_nii))
    dat = img.get_data()
    dat[isnan(dat)] = 0
    img = Nifti1Image(dat, img.affine)

    tmp_nii = mkstemp(suffix='.nii.gz')[1]
    img.to_filename(tmp_nii)
    return Path(tmp_nii)
Ejemplo n.º 15
0
def compute_zstat(feat_path):
    return nload(str(feat_path / 'stats' / 'zstat1.nii.gz'))
Ejemplo n.º 16
0
def timeseries_fmri(parameters):
    fmri_dir = parameters['paths']['output'] / 'workflow' / 'fmri'
    subject = parameters['plot']['subject']
    subject = 'delft'
    fmri_subj_dir = fmri_dir / f'_subject_{subject}'

    regressor_file = next(fmri_subj_dir.rglob('design.mat'))
    thresh_file = next(fmri_subj_dir.rglob('thresh_zstat1.nii.gz'))
    timeseries_file = next(fmri_subj_dir.rglob('filtered_func_data.nii.gz'))

    subj_dir = parameters['paths']['input'] / f'sub-{subject}'
    events_fmri_file = next(subj_dir.glob('ses-*/func/*_events.tsv'))
    events = read_tsv(events_fmri_file)

    thresh = nload(thresh_file).get_fdata()
    i_vox = thresh >= THRESH
    timeseries = nload(timeseries_file).get_fdata()
    fmri = timeseries[i_vox]
    t_fmri = arange(timeseries.shape[3]) * TR

    regressor = genfromtxt(regressor_file, skip_header=5)

    traces = [
        go.Scatter(
            x=t_fmri,
            y=fmri.mean(axis=0),
            line=dict(color='black', ),
        ),
        go.Scatter(
            x=t_fmri,
            y=regressor,
            yaxis='y2',
        ),
    ]

    layout = merge(
        LAYOUT,
        dict(
            height=100,
            width=450,
            showlegend=False,
            xaxis=dict(
                tick0=0,
                dtick=30,
                range=(0, 270),
            ),
            yaxis=dict(),
            yaxis2=dict(
                overlaying='y',
                side='right',
                visible=False,
            ),
            shapes=event_shapes(events),
        ),
    )

    fig = go.Figure(
        data=traces,
        layout=layout,
    )

    return fig