mripy.io package

Submodules

mripy.io.freesurfer module

mripy.io.freesurfer.read_fs_annotation(fname, return_df=False)[source]
Returns:

nodes

Return type:

int array

References

https://github.com/fieldtrip/fieldtrip/blob/master/external/freesurfer/read_annotation.m

mripy.io.freesurfer.read_fs_curv(fname)[source]

Read FreeSurfer surface data binary file (big endian).

Returns:

curv – Per vertex data value (e.g., curvature, thickness, sulc, etc.).

Return type:

float array

References

https://github.com/fieldtrip/fieldtrip/blob/master/external/freesurfer/read_curv.m http://www.grahamwideman.com/gw/brain/fs/surfacefileformats.htm

mripy.io.freesurfer.read_fs_int32(fi)[source]

Read big endian 4-byte integer from opened binary file.

mripy.io.freesurfer.read_fs_patch(fname)[source]

Read FreeSurfer surface patch binary file (big endian).

Returns:

  • vtx (int array) – The stored vtx value encoding both nodes and border information.

  • verts (Nx3 float array, [x, y, z])

  • nodes (int array) – The node index of the patch vertices on the original inflated surface. The numbers are obviously non-contiguous.

  • border (bool array) – Whether the vertex is on the border of the patch.

References

https://rdrr.io/cran/freesurferformats/src/R/read_fs_patch.R http://www.grahamwideman.com/gw/brain/fs/surfacefileformats.htm (obsoleted)

mripy.io.freesurfer.read_fs_str(fi)[source]
mripy.io.freesurfer.read_fs_surf(fname)[source]

Read FreeSurfer surface mesh binary file (big endian).

Returns:

  • verts (Nx3 float array, [x, y, z])

  • faces (Nx3 int array, [v1, v2, v3])

References

https://github.com/fieldtrip/fieldtrip/blob/master/external/freesurfer/read_surf.m http://www.grahamwideman.com/gw/brain/fs/surfacefileformats.htm

mripy.io.freesurfer.read_fs_uint24(fi)[source]

Read big endian 3-byte unsigned integer from opened binary file.

mripy.io.freesurfer.write_fs_color_table(fname, color_table)[source]

Write FreeSurfer color table file (*.ctab), similar to {subject}/label/aparc.annot.a2009s.ctab, or https://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/AnatomicalROI/FreeSurferColorLUT

This file will be useful to generate a valid annot.niml.dset containing correct color table, which can then be used in *.spec to display custom anatomical labels at SUMA crosshair location. E.g., >>> FSread_annot -input lh.HCP-MMP1.annot -FSversion 2009 -FScmap lh.HCP-MMP1.ctab -FScmaprange 0 180 -dset lh.HCP-MMP1.annot.niml.dset -overwrite

mripy.io.freesurfer.write_fs_curv(fname, curv)[source]

Write FreeSurfer surface data binary file (big endian).

Parameters:
  • curv (1D array like) – Surface data, each vertex must have one and only one value.

  • version. (Only support writing in the new binary) –

mripy.io.freesurfer.write_fs_int32(fo, x)[source]

Write big endian 4-byte integer to opened binary file.

mripy.io.freesurfer.write_fs_uint24(fo, x)[source]

Write big endian 3-byte unsigned integer to opened binary file.

mripy.io.gifti module

mripy.io.gifti.read_gii_dset(fname)[source]

Read GIFTI surface data in XML format.

mripy.io.niml module

mripy.io.niml.parse_attr(attr)[source]

Split a single attribute into key and value.

Notes

NIML attributes are in the general form “attname=string”, separated by whitespace. XML allows whitespace to occur around the “=” that separates the attname from the string. NIML does not allow this whitespace; the next character after attname must be “=”, and the next character after that must be a Name character or a quote character.

We don’t need to deal with the quotes around value here, leaving it to xml.etree.TreeBuilder.

mripy.io.niml.parse_data(between, fmt)[source]

Parse data stream from between-tag content (can be empty). If ni_type exists, the data is converted into a numpy array.

TODO: Handle escape sequence (<, >, “, &) in text data.

mripy.io.niml.parse_data_format(attrs)[source]

Parse data stream format based on ni_form, ni_type, ni_dimen, etc. for both binary, base64, and text data.

mripy.io.niml.parse_ni_type(ni_type, flatten=None)[source]

Parse ni_type into numpy dtype.

The method exploits the flexibilty of np.dtype() in a recursive manner. Assumptions which seem to be contradicting the NIML specification:

  1. The standard type is not abbreviated, e.g., int

  2. The multiple type is indicated by “*”, e.g., 4*int

  3. The compound type is separated by “,”, e.g., 4*float,int,String

Parameters:
  • ni_type (str) –

  • flatten (bool) – Limited to create non-hierarchical structured dtype, e.g., interpreting “4*float,int,String” as “float,float,float,float,int,String”.

mripy.io.niml.parse_niml(fname)[source]

Parse NIML file into Python xml.etree.Element using incremental event-driven parsing.

References

https://afni.nimh.nih.gov/pub/dist/src/niml/NIML_base.html

mripy.io.niml.read_until(fi, end_token, batch_size=1024)[source]

Read until encountering a specific character.

Useful for event-driven parsing, especially for large binary file like NIML dset. This method is designed to work with both str and bytes.

Module contents

class mripy.io.BallMask(master, c, r)[source]

Bases: Mask

class mripy.io.CylinderMask(master, c, r)[source]

Bases: Mask

class mripy.io.Mask(master=None, kind='mask')[source]

Bases: object

ball(c, r, **kwargs)[source]
compatible(other)[source]
classmethod concat(masks)[source]
constrain(func, return_selector=False, inplace=False)[source]
Parameters:

func (callable) – selector = func(x, y, z) is used to select a subset of self.index

cylinder(c, r, **kwargs)[source]

The elongated axis is represented as nan

dump(fname, dtype=None)[source]
classmethod from_dict(d)[source]
classmethod from_expr(expr=None, **kwargs)[source]
classmethod from_files(files, combine='union', **kwargs)[source]
property ijk[source]
infer_selector(smaller)[source]
near(x, y, z, r, **kwargs)[source]

mm

pick(selector, inplace=False)[source]
slab(x1=None, x2=None, y1=None, y2=None, z1=None, z2=None, **kwargs)[source]
to_dict()[source]
to_file(fname, undump_value=False)[source]
undump(prefix, x, method='nibabel', space=None)[source]
property xyz[source]
property xyz_nifti[source]
class mripy.io.MaskDumper(mask_file)[source]

Bases: object

dump(fname)[source]
undump(prefix, x)[source]
class mripy.io.SlabMask(master, x1=None, x2=None, y1=None, y2=None, z1=None, z2=None)[source]

Bases: Mask

mripy.io.change_dim_order(in_file, out_file=None, dim_order=None, method='afni')[source]
Parameters:
  • dim_order (1D array with 8 numbers) –

    >>> np.array([  5, 300, 300, 124,   1,   2,   1,   1], dtype=np.int16) # for stats
    >>> np.array([  4, 150, 150,  62, 158,   1,   1,   1], dtype=np.int16) # for epi
    

  • method (str, 'afni' | 'nibabel') –

mripy.io.change_space(in_file, out_file=None, space=None, method='nibabel')[source]
>>> change_space('MNI152_2009_template.nii.gz', 'template.nii', space='ORIG')
>>> change_space('test+tlrc.HEAD') # -> test.nii as ORIG
mripy.io.compress(in_file, out_file=None)[source]
mripy.io.convert_dicom(dicom_dir, out_file=None, dicom_ext=None, interactive=False, extra_cmd=None)[source]
mripy.io.convert_dicoms(dicom_dirs, out_dir=None, prefix=None, out_type='.nii', dicom_ext='.IMA', **kwargs)[source]
Parameters:
  • dicom_dirs (list or str) –

    1. A list of folders containing *.IMA files

    2. It can also be a glob pattern that describes a list of folders, e.g., “raw_fmri/func??”

    3. Finally, it can be a root folder (e.g., “raw_fmri”) containing multiple sub-folders of *.IMA files, raw_fmri/anat, raw_fmri/func01, raw_fmri/func02, etc.

  • out_dir (str) –

    Output directory for converted datasets, default is current directory. The output would look like:

    out_dir/anat.nii, out_dir/func01.nii, out_dir/func02.nii, etc.
    

mripy.io.decompress(in_file, out_file=None)[source]
mripy.io.extract_physio(physio_file, dicom_file, TR=None, dummy=0, channels=['resp', 'puls'], verbose=1)[source]
mripy.io.filter_cluster(in_file, out_file, top=None, neighbor=2)[source]
neighborint

1 : face touch 2 : edge touch (default, as in afni) 3 : corner touch

mripy.io.filter_dicom_files(files, series_numbers=None, instance_numbers=None, series_pattern='.+?\\.(\\d{4})\\.(\\d{4}).+(\\d+)\\.\\d+')[source]
mripy.io.generate_afni_idcode()[source]
mripy.io.get_dim_order(in_file)[source]
mripy.io.get_ni_type(x)[source]
mripy.io.get_space(in_file)[source]
mripy.io.hms2dt(hms, date=None, timestamp=False)[source]

Convert time string in hms format to datetime object.

hms is like “102907.165000”. This format is used in dicom header.

mripy.io.match_physio_with_series(physio_infos, series_infos, channel=None, method='cover')[source]
mripy.io.mmn2dt(mmn, date=None, timestamp=False)[source]

Convert time string in mmn format to datetime object.

mmn is “msec since midnight”, like “37747165”. This format is used in physiological measurement log file.

mripy.io.parse_dicom_header(fname, fields=None)[source]

Execute afni command dicom_hdr to readout most useful info from dicom header.

Parameters:
  • fname (str) –

  • fields ({field: (matcher, extracter(match))}) – You can require additional fields in dicom header to be parsed. - field : e.g., ‘ImageTime’ - matcher : e.g. r’ID Image Time//(S+)’ - extracter : e.g., lambda match: io.hms2dt(match.group(1), date=’20170706’, timestamp=True)

mripy.io.parse_physio_file(fname, date=None)[source]

Notes

IMPLEMENTATION

  1. The first 4 (ext, puls, resp) or 5 (ecg) values are parameters (of unknown meanings).

  2. There can be multiple data lines, within which extra parameters is inclosed between 5002 and 6002, especially for ecg.

  3. The footer is inclosed between 5003 and 6003, following physiological data (and that’s why the final data value always appears to be 5003).

  4. The MDH values are timestamps derived from the clock in the scanner (so do DICOM images), while the MPCU values are timestamps derived from the clock within the PMU recording system [1]. Use MDH time to synchronize physiological and imaging time series.

  5. The trigger values (5000) are “inserted” into the data, and have to be stripped out from the time series [1]. This fact is double checked by looking at the smooth trend of the puls waveform.

  6. The sampling rate is slightly (and consistently) slower than specified in the manual and in [1].

ABOUT TIMING

The scanner clock is slightly faster than the wall clock so that 2 sec in real time is recorded as ~2.008 sec in the scanner, affacting both dicom header and physiological footer, even though the actual TR is precisely 2 s (as measured by timing the s triggers with psychtoolbox) and the actual sampling rate of physiological data is precisely 50 Hz (as estimated by dividing the total number of samples by the corrected recording duration).

References

[1] https://cfn.upenn.edu/aguirre/wiki/public:pulse-oximetry_during_fmri_scanning

mripy.io.parse_physio_files(fname, date=None, channels=None)[source]
mripy.io.parse_series_info(fname, timestamp=False, shift_time=None, series_pattern='.+?\\.(\\d{4})\\.', fields=None, parser=None)[source]

Potential bug: dicom.parse_dicom_header doesn’t support fields as kwargs

mripy.io.parse_slice_order(dicom_files)[source]
mripy.io.read_affine(fname, sep=None)[source]
Returns:

mat

Return type:

3x4 or Nx3x4

mripy.io.read_afni(fname, remove_nii=True, return_img=False)[source]
mripy.io.read_asc(fname, dtype=None)[source]

Read FreeSurfer/SUMA surface (vertices and faces) in *.asc format.

mripy.io.read_gii(fname, return_img=False)[source]
mripy.io.read_label(fname)[source]

Read FreeSurfer label

mripy.io.read_nii(fname, return_img=False)[source]
mripy.io.read_niml_bin_nodes(fname)[source]

Read “Node Bucket” (node indices and values) from niml (binary) dataset.

mripy.io.read_niml_dset(fname, tags=None, as_asc=True, return_type='list')[source]
mripy.io.read_patch_asc(fname, dtype=None, index_type='multimap')[source]

Read FreeSurfer/SUMA patch (noncontiguous vertices and faces) in *.asc format.

index_typestr
  • “raw” or “array”

  • “map” or “dict”

  • “multimap” or “func”

mripy.io.read_register_dat(fname)[source]
mripy.io.read_stim(fname)[source]
mripy.io.read_surf_data(fname)[source]
mripy.io.read_surf_info(fname)[source]
mripy.io.read_surf_mesh(fname, return_img=False, **kwargs)[source]
mripy.io.read_txt(fname, dtype=<class 'float'>, comment='#', delimiter=None, skiprows=0, nrows=None, return_comments=False)[source]

Read numerical array from text file, much faster than np.loadtxt()

mripy.io.read_vol(fname, return_img=False)[source]
mripy.io.read_warp(fname)[source]

References

[1] https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dQwarp.html

“An AFNI nonlinear warp dataset stores the displacements (in DICOM mm) from the base dataset grid to the source dataset grid. AFNI stores a 3D warp as a 3-volume dataset (NiFTI or AFNI format), with the voxel values being the displacements in mm (32-bit floats) needed to ‘reach out’ and bring (interpolate) another dataset into alignment – that is, ‘pulling it back’ to the grid defined in the warp dataset header.”

mripy.io.sort_dicom_series(folder, series_pattern='.+?\\.(\\d{4})\\.')[source]
Parameters:

folder (string) – Path to the folder containing all the *.IMA files.

Returns:

studies – [{‘0001’: [file0, file1, …], ‘0002’: [files], …}, {study1}, …]

Return type:

list of dicts

class mripy.io.unzipped(zip_file)[source]

Bases: object

mripy.io.write_1D_nodes(fname, idx, val)[source]
mripy.io.write_affine(fname, mat, oneline=True, sep=None)[source]

TODO: Not support multivolume affine yet

mripy.io.write_afni(prefix, vol, base_img=None)[source]
mripy.io.write_asc(fname, verts, faces)[source]
mripy.io.write_gii(fname, verts, faces)[source]
mripy.io.write_nii(fname, vol, base_img=None, space=None, dim=None)[source]
mripy.io.write_niml_bin_nodes(fname, idx, val)[source]

Write “Node Bucket” (node indices and values) as niml (binary) dataset.

References

[1] https://afni.nimh.nih.gov/afni/community/board/read.php?1,60396,60399#msg-60399

[2] After some trial-and-error, the following components are required:

self_idcode, COLMS_RANGE, COLMS_TYPE (tell suma how to interpret val), no whitespace between opening tag and binary data.

mripy.io.write_surf_data(fname, nodes, values)[source]
mripy.io.write_surf_mesh(fname, verts, faces, **kwargs)[source]
mripy.io.write_vol(fname, vol, base_img=None)[source]