Skip to content

ENH: Define Cifti2 Axes describing the rows/columns of the Cifti2 data #641

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 60 commits into from
Mar 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
87c7dc1
ENH: Define Cifti2 Axes describing the rows/columns of the Cifti2 data
MichielCottaar Jun 25, 2018
0e7566a
Clarified the test filenames
MichielCottaar Jun 25, 2018
671c196
BUG: removed failing doctest
MichielCottaar Jun 25, 2018
1dd059d
DOC: explained that Axis is an abstract class
MichielCottaar Jan 28, 2019
8660afd
RF: removed the typed array underlying all axes
MichielCottaar Mar 14, 2019
c2274c5
RF: increased consistency of methods in the Axis objects
MichielCottaar Mar 14, 2019
52aff8a
ENH: made it easier to create Label axis from constructor directly
MichielCottaar Mar 14, 2019
dad74ee
REF: made flake8 happy
MichielCottaar Mar 14, 2019
a0e8ff3
BF: fixed abstract class for python2
MichielCottaar Mar 14, 2019
420dacb
BF: allow any integer type, not just int
MichielCottaar Mar 15, 2019
29448f1
DOC: fixed many issues with the documentation
MichielCottaar Mar 15, 2019
5684268
RF: made flake8 happy again
MichielCottaar Mar 15, 2019
fbd28dc
Apply suggestions from code review
effigies Mar 19, 2019
c33e0d1
Added other reviewer suggestions
MichielCottaar Mar 19, 2019
bc2064e
RF: remove spurious ', ' from method definition
MichielCottaar Mar 19, 2019
4c0f389
Replaced asarray with asanyarray
MichielCottaar Mar 19, 2019
72c089a
reverse guard for incorrect type when concatenating parcels
MichielCottaar Mar 19, 2019
e8bcaba
Replaces type(self) with self.__class__
MichielCottaar Mar 19, 2019
ac2618b
Tests many more fail conditions and edge cases
MichielCottaar Mar 19, 2019
e00143b
MNT: Bump minimum numpy version to 1.8
effigies Mar 20, 2019
436231c
Apply suggestions from code review
effigies Mar 22, 2019
d1bc7fe
BF: only set idx_start to size - 1 for negative step
MichielCottaar Mar 22, 2019
949da0e
TEST: add tests for Axis __eq__ methods
MichielCottaar Mar 22, 2019
ac0258c
DOC: removed Series attribute list as it is already listed in the __i…
MichielCottaar Mar 22, 2019
6726b00
RF: removed separate `extend` method
MichielCottaar Mar 22, 2019
790aba4
BF: report original index
MichielCottaar Mar 22, 2019
e7302d6
RF: removed spurious '+' when concatenating literal strings
MichielCottaar Mar 22, 2019
b2c674f
Increased test coverage
MichielCottaar Mar 22, 2019
459fa88
RF: replaced last '.all()' with `array_equal`
MichielCottaar Mar 22, 2019
70588f2
Merge branch 'master' into enh/cifti2_axes
MichielCottaar Mar 22, 2019
6b55e11
RF: made flake8 happy again
MichielCottaar Mar 22, 2019
2ae25b4
Merge pull request #2 from effigies/enh/cifti2_axes
MichielCottaar Mar 22, 2019
e4bc7b0
BF: don't use np.full to create string array
MichielCottaar Mar 22, 2019
a5f88c2
RF: set surface BrainModel default structure to Other
MichielCottaar Mar 24, 2019
a31af61
RF: adjusted some type desciptions
MichielCottaar Mar 24, 2019
0e0b7f2
DOC: Added tutorial to docs
MichielCottaar Mar 24, 2019
594b22f
BUG: skip doctests in example code
MichielCottaar Mar 24, 2019
29a5287
BF: reduces line length in example code
MichielCottaar Mar 24, 2019
109fa92
RF: changes from @demianw not involving name changes
MichielCottaar Mar 26, 2019
f7c47bb
RF: rename from_mapping to from_index_mapping
MichielCottaar Mar 26, 2019
b88d516
RF: return CIFTI_MODEL_TYPE to distinguish surface and voxels
MichielCottaar Mar 26, 2019
fd8593e
RF: renamed is_surface to surface_mask and added volume_mask
MichielCottaar Mar 26, 2019
cdf57db
STY: fixed indentation
MichielCottaar Mar 26, 2019
b51d5f1
DOC: consistently use CIFTI-2 instead of CIfTI2 or CIFTI2
MichielCottaar Mar 27, 2019
532bed9
RF: appended Axis to the different axes classes
MichielCottaar Mar 27, 2019
cffb8c0
DOC: test creation of `bm_thal` and `bm_cortex`
MichielCottaar Mar 27, 2019
9b2276d
DOC: got rid of most of the :class:`Axis` in tutorial
MichielCottaar Mar 27, 2019
110334b
Update nibabel/cifti2/cifti2.py
effigies Mar 27, 2019
063047f
Apply suggestions from code review
effigies Mar 27, 2019
cefb8c6
RF: replace ~surface_mask with volume_mask
MichielCottaar Mar 27, 2019
0f0e1f7
DOC: added list of concrete classes to Axis object
MichielCottaar Mar 27, 2019
0270ad9
BF: add name to return, so that link works in html
MichielCottaar Mar 27, 2019
ed76418
RF: fix line length
MichielCottaar Mar 27, 2019
d825a3c
DOC: make format in list of axes more consistent
MichielCottaar Mar 27, 2019
1bc459e
DOCTEST: Drop doctest SKIP directives
effigies Mar 27, 2019
04a4b45
FIX: Use other.volume_mask to index other.voxel
effigies Mar 27, 2019
4aa3609
DOC: Update docstrings with a few more links and array_like
effigies Mar 27, 2019
97e16d3
Merge pull request #3 from effigies/enh/cifti2_axes
MichielCottaar Mar 27, 2019
36c162d
BF: doctest fixes for tutorial
MichielCottaar Mar 28, 2019
0927424
BF: fixed doctest for python 2.7
MichielCottaar Mar 29, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ matrix:
# Absolute minimum dependencies
- python: 2.7
env:
- DEPENDS="numpy==1.7.1"
- DEPENDS="numpy==1.8"
# Absolute minimum dependencies
- python: 2.7
env:
- DEPENDS="numpy==1.7.1"
- DEPENDS="numpy==1.8"
- CHECK_TYPE="import"
# Absolute minimum dependencies plus oldest MPL
# Check these against:
Expand All @@ -46,11 +46,11 @@ matrix:
# requirements.txt
- python: 2.7
env:
- DEPENDS="numpy==1.7.1 matplotlib==1.3.1"
- DEPENDS="numpy==1.8 matplotlib==1.3.1"
# Minimum pydicom dependency
- python: 2.7
env:
- DEPENDS="numpy==1.7.1 pydicom==0.9.9 pillow==2.6"
- DEPENDS="numpy==1.8 pydicom==0.9.9 pillow==2.6"
# pydicom master branch
- python: 3.5
env:
Expand Down
1 change: 1 addition & 0 deletions doc/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ File Formats
analyze
spm2analyze
spm99analyze
cifti2
gifti
freesurfer
minc1
Expand Down
2 changes: 1 addition & 1 deletion doc/source/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Requirements
.travis.yml

* Python_ 2.7, or >= 3.4
* NumPy_ 1.7.1 or greater
* NumPy_ 1.8 or greater
* Six_ 1.3 or greater
* SciPy_ (optional, for full SPM-ANALYZE support)
* PyDICOM_ 0.9.9 or greater (optional, for DICOM support)
Expand Down
4 changes: 3 additions & 1 deletion nibabel/cifti2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
# copyright and license terms.
#
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""CIfTI format IO
"""CIFTI-2 format IO

.. currentmodule:: nibabel.cifti2

.. autosummary::
:toctree: ../generated

cifti2
cifti2_axes
"""

from .parse_cifti2 import Cifti2Extension
Expand All @@ -25,3 +26,4 @@
Cifti2TransformationMatrixVoxelIndicesIJKtoXYZ,
Cifti2Vertices, Cifti2Volume, CIFTI_BRAIN_STRUCTURES,
Cifti2HeaderError, CIFTI_MODEL_TYPES, load, save)
from .cifti2_axes import (Axis, BrainModelAxis, ParcelsAxis, SeriesAxis, LabelAxis, ScalarAxis)
81 changes: 58 additions & 23 deletions nibabel/cifti2/cifti2.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,15 @@
# copyright and license terms.
#
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
''' Read / write access to CIfTI2 image format
''' Read / write access to CIFTI-2 image format

Format of the NIFTI2 container format described here:

http://www.nitrc.org/forum/message.php?msg_id=3738

Definition of the CIFTI2 header format and file extensions attached to this
email:
Definition of the CIFTI-2 header format and file extensions can be found at:

http://www.nitrc.org/forum/forum.php?thread_id=4380&forum_id=1955

Filename is ``CIFTI-2_Main_FINAL_1March2014.pdf``.
http://www.nitrc.org/projects/cifti
'''
from __future__ import division, print_function, absolute_import
import re
Expand All @@ -42,7 +39,7 @@ def _float_01(val):


class Cifti2HeaderError(Exception):
""" Error in CIFTI2 header
""" Error in CIFTI-2 header
"""


Expand Down Expand Up @@ -178,7 +175,7 @@ def _to_xml_element(self):


class Cifti2LabelTable(xml.XmlSerializable, MutableMapping):
""" CIFTI2 label table: a sequence of ``Cifti2Label``s
""" CIFTI-2 label table: a sequence of ``Cifti2Label``s

* Description - Used by NamedMap when IndicesMapToDataType is
"CIFTI_INDEX_TYPE_LABELS" in order to associate names and display colors
Expand Down Expand Up @@ -236,7 +233,7 @@ def _to_xml_element(self):


class Cifti2Label(xml.XmlSerializable):
""" CIFTI2 label: association of integer key with a name and RGBA values
""" CIFTI-2 label: association of integer key with a name and RGBA values

For all color components, value is floating point with range 0.0 to 1.0.

Expand Down Expand Up @@ -314,7 +311,7 @@ def _to_xml_element(self):


class Cifti2NamedMap(xml.XmlSerializable):
"""CIFTI2 named map: association of name and optional data with a map index
"""CIFTI-2 named map: association of name and optional data with a map index

Associates a name, optional metadata, and possibly a LabelTable with an
index in a map.
Expand Down Expand Up @@ -432,7 +429,7 @@ def _to_xml_element(self):


class Cifti2VoxelIndicesIJK(xml.XmlSerializable, MutableSequence):
"""CIFTI2 VoxelIndicesIJK: Set of voxel indices contained in a structure
"""CIFTI-2 VoxelIndicesIJK: Set of voxel indices contained in a structure

* Description - Identifies the voxels that model a brain structure, or
participate in a parcel. Note that when this is a child of BrainModel,
Expand Down Expand Up @@ -514,7 +511,7 @@ def _to_xml_element(self):


class Cifti2Vertices(xml.XmlSerializable, MutableSequence):
"""CIFTI2 vertices - association of brain structure and a list of vertices
"""CIFTI-2 vertices - association of brain structure and a list of vertices

* Description - Contains a BrainStructure type and a list of vertex indices
within a Parcel.
Expand Down Expand Up @@ -580,7 +577,7 @@ def _to_xml_element(self):


class Cifti2Parcel(xml.XmlSerializable):
"""CIFTI2 parcel: association of a name with vertices and/or voxels
"""CIFTI-2 parcel: association of a name with vertices and/or voxels

* Description - Associates a name, plus vertices and/or voxels, with an
index.
Expand Down Expand Up @@ -695,7 +692,7 @@ def _to_xml_element(self):


class Cifti2Volume(xml.XmlSerializable):
"""CIFTI2 volume: information about a volume for mappings that use voxels
"""CIFTI-2 volume: information about a volume for mappings that use voxels

* Description - Provides information about the volume for any mappings that
use voxels.
Expand Down Expand Up @@ -738,7 +735,7 @@ def _to_xml_element(self):


class Cifti2VertexIndices(xml.XmlSerializable, MutableSequence):
"""CIFTI2 vertex indices: vertex indices for an associated brain model
"""CIFTI-2 vertex indices: vertex indices for an associated brain model

The vertex indices (which are independent for each surface, and
zero-based) that are used in this brain model[.] The parent
Expand Down Expand Up @@ -1081,7 +1078,7 @@ def _to_xml_element(self):


class Cifti2Matrix(xml.XmlSerializable, MutableSequence):
""" CIFTI2 Matrix object
""" CIFTI-2 Matrix object

This is a list-like container where the elements are instances of
:class:`Cifti2MatrixIndicesMap`.
Expand Down Expand Up @@ -1213,7 +1210,7 @@ def _to_xml_element(self):


class Cifti2Header(FileBasedHeader, xml.XmlSerializable):
''' Class for CIFTI2 header extension '''
''' Class for CIFTI-2 header extension '''

def __init__(self, matrix=None, version="2.0"):
FileBasedHeader.__init__(self)
Expand Down Expand Up @@ -1268,9 +1265,43 @@ def get_index_map(self, index):
'''
return self.matrix.get_index_map(index)

def get_axis(self, index):
'''
Generates the Cifti2 axis for a given dimension

Parameters
----------
index : int
Dimension for which we want to obtain the mapping.

Returns
-------
axis : :class:`.cifti2_axes.Axis`
'''
from . import cifti2_axes
return cifti2_axes.from_index_mapping(self.matrix.get_index_map(index))

@classmethod
def from_axes(cls, axes):
'''
Creates a new Cifti2 header based on the Cifti2 axes

Parameters
----------
axes : tuple of :class`.cifti2_axes.Axis`
sequence of Cifti2 axes describing each row/column of the matrix to be stored

Returns
-------
header : Cifti2Header
new header describing the rows/columns in a format consistent with Cifti2
'''
from . import cifti2_axes
return cifti2_axes.to_header(axes)


class Cifti2Image(DataobjImage):
""" Class for single file CIFTI2 format image
""" Class for single file CIFTI-2 format image
"""
header_class = Cifti2Header
valid_exts = Nifti2Image.valid_exts
Expand All @@ -1297,15 +1328,19 @@ def __init__(self,
Object containing image data. It should be some object that
returns an array from ``np.asanyarray``. It should have a
``shape`` attribute or property.
header : Cifti2Header instance
Header with data for / from XML part of CIFTI2 format.
header : Cifti2Header instance or sequence of :class:`cifti2_axes.Axis`
Header with data for / from XML part of CIFTI-2 format.
Alternatively a sequence of cifti2_axes.Axis objects can be provided
describing each dimension of the array.
nifti_header : None or mapping or NIfTI2 header instance, optional
Metadata for NIfTI2 component of this format.
extra : None or mapping
Extra metadata not captured by `header` or `nifti_header`.
file_map : mapping, optional
Mapping giving file information for this image format.
'''
if not isinstance(header, Cifti2Header) and header:
header = Cifti2Header.from_axes(header)
super(Cifti2Image, self).__init__(dataobj, header=header,
extra=extra, file_map=file_map)
self._nifti_header = Nifti2Header.from_header(nifti_header)
Expand All @@ -1321,7 +1356,7 @@ def nifti_header(self):

@classmethod
def from_file_map(klass, file_map):
""" Load a CIFTI2 image from a file_map
""" Load a CIFTI-2 image from a file_map

Parameters
----------
Expand All @@ -1341,7 +1376,7 @@ def from_file_map(klass, file_map):
cifti_header = item.get_content()
break
else:
raise ValueError('NIfTI2 header does not contain a CIFTI2 '
raise ValueError('NIfTI2 header does not contain a CIFTI-2 '
'extension')

# Construct cifti image.
Expand Down Expand Up @@ -1400,7 +1435,7 @@ def to_file_map(self, file_map=None):
img.to_file_map(file_map or self.file_map)

def update_headers(self):
''' Harmonize CIFTI2 and NIfTI headers with image data
''' Harmonize CIFTI-2 and NIfTI headers with image data

>>> import numpy as np
>>> data = np.zeros((2,3,4))
Expand Down
Loading