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_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.gifti module
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:
The standard type is not abbreviated, e.g., int
The multiple type is indicated by “*”, e.g., 4*int
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”.
Module contents
- class mripy.io.Mask(master=None, kind='mask')[source]
Bases:
object
- 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.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) –
A list of folders containing *.IMA files
It can also be a glob pattern that describes a list of folders, e.g., “raw_fmri/func??”
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.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.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
The first 4 (ext, puls, resp) or 5 (ecg) values are parameters (of unknown meanings).
There can be multiple data lines, within which extra parameters is inclosed between 5002 and 6002, especially for ecg.
The footer is inclosed between 5003 and 6003, following physiological data (and that’s why the final data value always appears to be 5003).
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.
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.
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_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.read_asc(fname, dtype=None)[source]
Read FreeSurfer/SUMA surface (vertices and faces) in *.asc format.
- mripy.io.read_niml_bin_nodes(fname)[source]
Read “Node Bucket” (node indices and values) from niml (binary) dataset.
- 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_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_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
- mripy.io.write_affine(fname, mat, oneline=True, sep=None)[source]
TODO: Not support multivolume affine yet
- 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.