Esempio n. 1
0
 def export(flnm, p):
     flnm = flnm + '.' + surface_format
     dt = np.int32 if np.issubdtype(p.dtype,
                                    np.dtype(int).type) else np.float32
     img = fsmgh.MGHImage(np.asarray([[p]], dtype=dt), np.eye(4))
     img.to_filename(flnm)
     return flnm
 def export(flnm, d):
     if not pimms.is_nparray(d): d = np.asarray(d.dataobj)
     flnm = flnm + '.' + volume_format
     dt = np.int32 if np.issubdtype(d.dtype, np.dtype(int).type) else np.float32
     img = fsmgh.MGHImage(np.asarray(d, dtype=dt), affmatrix)
     img.to_filename(flnm)
     return flnm
Esempio n. 3
0
def write_voldata_to_mgh_file(mgh_file_name, vol_data, affine=None, header=None):
    """
    Write volume data to a MGH format file.

    Write the volume data to a file in MGH format. The format is from FreeSurfer and stores volume images. Unless you supply a header, the header will be pretty empty. Thin wrapper around nibabels ```MGHImage``` class and the ```to_filename``` method inherited from ```FileBasedImage```. Note that if you just modified data that you loaded from a source image (e.g., you replaced some intensities), you should pass the affine and the header of the original image.

    Parameters
    ----------
    mgh_file_name: str
        Path to output file. Will be overwritten if it exists. Should have file extension mgh.

    vol_data: the data to write, usually a multi-dimensional numpy array. Shape could be (256, 256, 256) for a 3D image, or (256, 256, 256, 50) for a 4D image containing 50 time points, but this is up to you.

    affine: numpy 2D array, optional
        The affine registration matrix (4x4) relating the voxel coordinates to world coordinates in RAS+ space. See nibabel docs for details.

    header: nibabel.freesurfer.mghformat.MGHHeader, optional
        The MGH file header. If not given, an empty default header will be used.
    """
    if header is None:
        header = fsmgh.MGHHeader()
    image = fsmgh.MGHImage(vol_data, affine, header=header)
    image.to_filename(mgh_file_name)
Esempio n. 4
0
def nsd_write_fs(data, outputfile, fsdir):
    """similar to nsd_vrite_vol but for surface mgz

    Args:
        data (nd-array): the surface data
        outputfile (filename/path): where to save
        fsdir (path): we need to know where the fsdir is.

    Raises:
        ValueError: if wrong file name provided, e.g doesn't have
                    lh or rh in filename, error is raised.
    """

    # load template
    # load template
    if outputfile.find('lh.') != -1:
        hemi = 'lh'
    elif outputfile.find('rh.') != -1:
        hemi = 'rh'
    else:
        raise ValueError('wrong outpufile.')

    mgh0 = f'{fsdir}/surf/{hemi}.w-g.pct.mgh'

    if not os.path.exists(mgh0):
        mgh0 = f'{fsdir}/surf/{hemi}.orig.avg.area.mgh'

    img = fsmgh.load(mgh0)

    header = img.header
    affine = img.affine

    # Okay, make a new object now...
    vol_h = data[:, np.newaxis].astype(np.float64)
    v_img = fsmgh.MGHImage(vol_h, affine, header=header, extra={})

    v_img.to_filename(outputfile)
 def export(flnm, d):
     flnm = flnm + '.' + volume_format
     dt = np.int32 if np.issubdtype(d.dtype, np.dtype(int).type) else np.float32
     img = fsmgh.MGHImage(np.asarray(d, dtype=dt), subject.voxel_to_native_matrix)
     img.to_filename(flnm)
     return flnm
Esempio n. 6
0
def to_mgh(obj, like=None, header=None, affine=None, extra=Ellipsis):
    '''
    to_mgh(obj) yields an MGHmage object that is as equivalent as possible to the given object obj.
      If obj is an MGHImage already and no changes are requested, then it is returned unmolested;
      otherwise, the optional arguments can be used to edit the header, affine, and exta.

    The following options are accepted:
      * like (default: None) may be provided to give a guide for the various header- and meta-data
        that is included in the image. If this is a nifti image object, its meta-data are used; if
        this is a subject, then the meta-data are deduced from the subject's voxel and native
        orientation matrices. All other specific options below override anything deduced from the
        like argument.
      * header (default: None) may be a Nifti1 or Niti2 image header to be used as the nifti header
        or to replace the header in a new image.
      * affine (default: None) may specify the affine transform to be given to the image object.
      * extra (default: Ellipsis) may specify an extra mapping for storage with the image data; the
        default value Ellipsis indicates that such a mapping should be left as is if it already
        exists in the obj or in the like option and should otherwise be empty.
    '''
    obj0 = obj
    # First go from like to explicit versions of affine and header:
    if like is not None:
        if isinstance(like, nib.analyze.AnalyzeHeader) or isinstance(obj, fsmgh.MGHHeader):
            if header is None: header = like
        elif isinstance(like, nib.analyze.SpatialImage):
            if header is None: header = like.header
            if affine is None: affine = like.affine
            if extra is Ellipsis: extra = like.extra
        elif isinstance(like, mri.Subject):
            if affine is None: affine = like.voxel_to_native_matrix
        else:
            raise ValueError('Could not interpret like argument with type %s' % type(like))
    # check to make sure that we have to change something:
    elif (isinstance(obj, fsmgh.MGHImage)):
        if ((header is None or obj.header is header) and
            (extra is Ellipsis or extra == obj.extra or (extra is None and len(obj.extra) == 0))):
            return obj
    # okay, now look at the header and affine etc.
    if header is None:
        if isinstance(obj, nib.analyze.SpatialImage):
            header = obj.header
        else:
            header = None
    if affine is None:
        if isinstance(obj, nib.analyze.SpatialImage):
            affine = obj.affine
        else:
            affine = np.eye(4)
    if extra is None: extra = {}
    # Figure out what the data is
    if isinstance(obj, nib.analyze.SpatialImage):
        obj = obj.dataobj
    else:
        obj = np.asarray(obj)
    if len(obj.shape) < 3: obj = np.asarray([[obj]])
    # make sure the dtype isn't a high-bit integer or float
    if np.issubdtype(obj.dtype, np.integer) and obj.dtype.itemsize > 4:
        obj = np.asarray(obj, dtype=np.int32)
    elif np.issubdtype(obj.dtype, np.floating) and obj.dtype.itemsize > 4:
        obj = np.asarray(obj, dtype=np.float32)
    # Okay, make a new object now...
    obj = fsmgh.MGHImage(obj, affine, header=header, extra=extra)
    # Okay, that's it!
    return obj
Esempio n. 7
0
 def _make_imm_mask(arr, val, eq=True):
     arr = (arr == val) if eq else (arr != val)
     arr.setflags(write=False)
     return fsmgh.MGHImage(arr, mgh_images['ribbon'].affine, mgh_images['ribbon'].header)
Esempio n. 8
0
File: io.py Progetto: WinawerLab/sco
def export_anatomical_data(data,
                           sub,
                           anat_ids,
                           hemis,
                           name,
                           output_dir,
                           modality=None,
                           create_dir=False,
                           prefix='',
                           suffix='',
                           null=np.nan,
                           dtype=None):
    '''
    export_anatomical_data(data, sub, cortex_indices, hemis, name, output_dir) exports the
       prediction data in the given data vector or matrix, out to the given directory in a set of
       files appropriate to the modality; for surfaces, this is an lh.<name>.nii.gz and
       rh.<name>.nii.gz file; for volumes, this is just a <name>.nii.gz file.

    Parameters:
      * data must be a vector of data or a matrix of data whose rows match up to the anatomical ids
      * cortex_indices must be the voxel indices or vertex ids of the data rows
      * hemis must be a list of 1 or -1 values to indicate LH and RH respectively
      * name should be a name for the file, used as a part of the filename such as lh.<name>.nii.gz
      * output_dir must be the name of the output directory
      * freesurfer_subject: the freesurfer subject object

    Options:
      * create_dir (default: False) if True, will create the directory if it does not exist;
        otherwise raises an exception when the directory does not exist.
      * prefix (default: '') may be a string that is prepended to filenames; prepends are performed
        before other prefixes such as 'lh.<prefix><name><suffix>.nii.gz'.
      * suffix (default: '') may be a string that is appended the the filename; appends are
        performed before the file extension is appended, such as in
        'lh.<prefix><name><suffix>.nii.gz'.
      * modality (default: None) may be specified explicitly as 'surface' or 'volume', but will
        auto-detect the modality based on the cortex_indices if None is given
      * null (default: nan) specifies the null value that should be written for values not in the
        cortex_indices; if this is nan and the dtype is an integer value, then 0 is used instead
      * dtype (default: None) specifies explicitly the dtype of the exported array; if None, the
        value np.asarray(data).dtype is used
    '''
    anat_ids = np.asarray(anat_ids)
    if len(anat_ids.shape) == 2 and (anat_ids.shape[0] == 1
                                     or anat_ids.shape[1] == 1):
        anat_ids = anat_ids.flatten()
    if modality is None:
        modality = 'volume' if len(anat_ids.shape) == 2 else 'surface'
    (prefix, suffix) = _sco_init_outputs(output_dir, create_dir, prefix,
                                         suffix)
    make_fname = lambda p, ext: os.path.join(
        output_dir, p + prefix + name + suffix + '.' + ext)
    modality = modality.lower()
    data = np.asarray(data)
    data = np.asarray([data]).T if len(data.shape) == 1 else data
    if len(data) != len(anat_ids):
        raise ValueError('anatomical id (%d) and data (%d) sizesmust match' %
                         (len(anat_ids), len(data)))
    if dtype is None: dtype = data.dtype
    if np.issubdtype(dtype, np.dtype(int).type) and not np.isfinite(null):
        null = 0
    affine = sub.mgh_images['lh.ribbon'].affine
    file_names = []
    if modality == 'surface':
        for (hname, hid) in [('lh', 1), ('rh', -1)]:
            hobj = getattr(sub, hname.upper())
            hidcs = np.where(hemis == hid)[0]
            n = hobj.vertex_count
            if np.issubdtype(dtype, np.float64): dtype = np.float32
            if data.shape[1] == 1:
                vol = np.full((1, 1, n), null, dtype=dtype)
                vol[0, 0, anat_ids[hidcs]] = data[hidcs, 0]
            else:
                vol = np.full((1, 1, n, data.shape[1]), null, dtype=dtype)
                vol[0, 0, anat_ids[hidcs], :] = data[hidcs, :]
            #img = nibabel.Nifti2Image(vol, np.eye(4))
            #fnm = make_fname(hname + '.', 'nii.gz')
            img = fsmgh.MGHImage(vol, np.eye(4))
            fnm = make_fname(hname + '.', 'mgz')
            img.to_filename(fnm)
            file_names.append(fnm)
    elif modality == 'volume':
        vol = np.full(sub.mgh_images['lh.ribbon'].shape + (data.shape[1], ),
                      null,
                      dtype=dtype)
        for ((i, j, k), row) in zip(anat_ids, data):
            vol[i, j, k, :] = row
        img = nibabel.Nifti1Image(vol, affine)
        fnm = make_fname('', 'nii.gz')
        img.to_filename(fnm)
        file_names.append(fnm)
    else:
        raise ValueError('unrecognized modality: %s' % modality)
    return file_names
def benson14_retinotopy_command(*args):
    '''
    benson14_retinotopy_command(args...) runs the benson14_retinotopy command; see 
    benson14_retinotopy_help for mor information.
    '''
    # Parse the arguments...
    (args, opts) = _benson14_parser(args)
    # help?
    if opts['help']:
        print benson14_retinotopy_help
        return 1
    # verbose?
    verbose = opts['verbose']
    def note(s):
        if verbose: print s
        return verbose
    # Add the subjects directory, if there is one
    if 'subjects_dir' in opts and opts['subjects_dir'] is not None:
        add_subject_path(opts['subjects_dir'])
    ow = not opts['no_overwrite']
    nse = opts['no_surf_export']
    nve = opts['no_vol_export']
    tr = {'polar_angle':  opts['angle_tag'],
          'eccentricity': opts['eccen_tag'],
          'visual_area':      opts['label_tag']}
    # okay, now go through the subjects...
    for subnm in args:
        note('Processing subject %s:' % subnm)
        sub = freesurfer_subject(subnm)
        note('   - Interpolating template...')
        (lhdat, rhdat) = predict_retinotopy(sub, template=opts['template'])
        # Export surfaces
        if nse:
            note('   - Skipping surface export.')
        else:
            note('   - Exporting surfaces:')
            for (t,dat) in lhdat.iteritems():
                flnm = os.path.join(sub.directory, 'surf', 'lh.' + tr[t] + '.mgz')
                if ow or not os.path.exist(flnm):
                    note('    - Exporting LH prediction file: %s' % flnm)
                    img = fsmgh.MGHImage(
                        np.asarray([[dat]], dtype=(np.int32 if t == 'visual_area' else np.float32)),
                        np.eye(4))
                    img.to_filename(flnm)
                else:
                    note('    - Not overwriting existing file: %s' % flnm)
            for (t,dat) in rhdat.iteritems():
                flnm = os.path.join(sub.directory, 'surf', 'rh.' + tr[t] + '.mgz')
                if ow or not os.path.exist(flnm):
                    note('    - Exporting RH prediction file: %s' % flnm)
                    img = fsmgh.MGHImage(
                        np.asarray([[dat]], dtype=(np.int32 if t == 'visual_area' else np.float32)),
                        np.eye(4))
                    img.to_filename(flnm)
                else:
                    note('    - Not overwriting existing file: %s' % flnm)
        # Export volumes
        if nve:
            note('   - Skipping volume export.')
        else:
            surf2rib = cortex_to_ribbon_map(sub, hemi=None)
            note('   - Exporting Volumes:')
            for t in lhdat.keys():
                flnm = os.path.join(sub.directory, 'mri', tr[t] + '.mgz')
                if ow or not os.path.exist(flnm):
                    note('    - Preparing volume file: %s' % flnm)
                    vol = cortex_to_ribbon(sub,
                                           (lhdat[t], rhdat[t]),
                                           map=surf2rib,
                                           method=('max' if t == 'visual_area' else 'weighted'),
                                           dtype=(np.int32 if t == 'visual_area' else np.float32))
                    note('    - Exporting volume file: %s' % flnm)
                    vol.to_filename(flnm)
                else:
                    note('    - Not overwriting existing file: %s' % flnm)
        note('   Subject %s finished!' % sub.id)
    return 0
            
def register_retinotopy_command(args):
    '''
    register_retinotopy_command(args) can be given a list of arguments, such as sys.argv[1:]; these
    arguments may include any options and must include at least one subject id. All subjects whose
    ids are given are registered to a retinotopy model, and the resulting registration, as well as
    the predictions made by the model in the registration, are exported.
    '''
    # Parse the arguments
    (args, opts) = _retinotopy_parser(args)
    # First, help?
    if opts['help']:
        print register_retinotopy_help
        return 1
    # and if we are verbose, lets setup a note function
    verbose = opts['verbose']

    def note(s):
        if verbose: print s
        return verbose

    # Add the subjects directory, if there is one
    if 'subjects_dir' in opts and opts['subjects_dir'] is not None:
        add_subject_path(opts['subjects_dir'])
    # Parse the simple numbers
    for o in [
            'weight_cutoff', 'edge_strength', 'angle_strength',
            'func_strength', 'max_step_size', 'max_out_eccen'
    ]:
        opts[o] = float(opts[o])
    opts['max_steps'] = int(opts['max_steps'])
    # These are for now not supported: #TODO
    if opts['angle_math'] or opts['angle_radians'] or opts['eccen_radians']:
        print 'Mathematical angles and angles not in degrees are not yet supported.'
        return 1
    # The remainder of the args can wait for now; walk through the subjects:
    tag_key = {
        'eccen': 'eccentricity',
        'angle': 'polar_angle',
        'label': 'visual_area'
    }
    for subnm in args:
        sub = freesurfer_subject(subnm)
        note('Processing subject: %s' % sub.id)
        # we need to register this subject...
        res = {}
        ow = not opts['no_overwrite']
        for h in ['LH', 'RH']:
            note('   Processing hemisphere: %s' % h)
            hemi = sub.__getattr__(h)
            # See if we are loading custom values...
            (ang, ecc, wgt) = (None, None, None)
            suffix = '_' + h.lower() + '_file'
            if opts['angle' + suffix] is not None:
                ang = _guess_surf_file(opts['angle' + suffix])
            if opts['eccen' + suffix] is not None:
                ecc = _guess_surf_file(opts['eccen' + suffix])
            if opts['weight' + suffix] is not None:
                wgt = _guess_surf_file(opts['weight' + suffix])
            # Do the registration
            note('    - Running Registration...')
            res[h] = register_retinotopy(
                hemi,
                retinotopy_model(),
                polar_angle=ang,
                eccentricity=ecc,
                weight=wgt,
                weight_cutoff=opts['weight_cutoff'],
                partial_voluming_correction=opts['part_vol_correct'],
                edge_scale=opts['edge_strength'],
                angle_scale=opts['angle_strength'],
                functional_scale=opts['func_strength'],
                prior=opts['prior'],
                max_predicted_eccen=opts['max_out_eccen'],
                max_steps=opts['max_steps'],
                max_step_size=opts['max_step_size'])
            # Perform the hemi-specific outputs now:
            if not opts['no_reg_export']:
                regnm = '.'.join(
                    [h.lower(), opts['registration_name'], 'sphere', 'reg'])
                flnm = (os.path.join(sub.directory, 'surf', regnm)
                        if h == 'LH' else os.path.join(sub.directory, 'xhemi',
                                                       'surf', regnm))
                if ow or not os.path.exist(flnm):
                    note('    - Exporting registration file: %s' % flnm)
                    fsio.write_geometry(
                        flnm, res[h].coordinates.T, res[h].faces.T,
                        'Created by neuropythy (github.com/noahbenson/neuropythy)'
                    )
                else:
                    note('    - Skipping registration file: %s (file exists)' %
                         flnm)
            if not opts['no_surf_export']:
                for dim in ['angle', 'eccen', 'label']:
                    flnm = os.path.join(
                        sub.directory, 'surf',
                        '.'.join([h.lower(), opts[dim + '_tag'], 'mgz']))
                    if ow or not os.path.exist(flnm):
                        note('    - Exporting prediction file: %s' % flnm)
                        img = fsmgh.MGHImage(
                            np.asarray([[res[h].prop(tag_key[dim])]],
                                       dtype=(np.int32 if dim == 'label' else
                                              np.float32)), np.eye(4))
                        img.to_filename(flnm)
                    else:
                        note('    - Skipping prediction file: %s (file exists)'
                             % flnm)
        # Do the volume exports here
        if not opts['no_vol_export']:
            note('   Processing volume data...')
            note('    - Calculating cortex-to-ribbon mapping...')
            surf2rib = cortex_to_ribbon_map(sub, hemi=None)
            for dim in ['angle', 'eccen', 'label']:
                flnm = os.path.join(sub.directory, 'mri',
                                    opts[dim + '_tag'] + '.mgz')
                if ow or not os.path.exist(flnm):
                    note('    - Generating volume file: %s' % flnm)
                    vol = cortex_to_ribbon(
                        sub, (res['LH'].prop(tag_key[dim]), res['RH'].prop(
                            tag_key[dim])),
                        map=surf2rib,
                        method=('max' if dim == 'label' else 'weighted'),
                        dtype=(np.int32 if dim == 'label' else np.float32))
                    note('    - Exporting volume file: %s' % flnm)
                    vol.to_filename(flnm)
                else:
                    note('    - Skipping volume file: %s (file exists)' % flnm)
        # That is it for this subject!
        note('   Subject %s finished!' % sub.id)
    # And if we made it here, all was successful.
    return 0