fsleyes.displaycontext.niftiopts¶
This module defines the NiftiOpts class.
An important note on coordinate systems¶
FSLeyes displays all overlays in a single coordinate system, referred
throughout as the display coordinate system. However, Nifti
overlays can potentially be transformed into the display coordinate system
in one of several ways:
voxels
(a.k.a.
id) The image data voxel coordinates map to the display coordinates.scaled voxels
(a.k.a.
pixdim) The image data voxel coordinates are scaled by thepixdimvalues stored in the NIFTI header. The origin is fixed at the centre of voxel(0, 0, 0).radioloigcal scaled voxels
(a.k.a.
pixdim-flip) The image data voxel coordinates are scaled by thepixdimvalues stored in the NIFTI header and, if the image appears to be stored in neurological order, the X (left-right) axis is inverted. The origin is fixed at the centre of voxel(0, 0, 0)(or(X-1, 0, 0)forinverted images).
world
(a.k.a.
affine) The image data voxel coordinates are transformed by the transformation matrix stored in the NIFTI header - see theNifticlass for more details.reference
(a.k.a.
reference) The image data voxel coordinates are transformed into thepixdim-flipcoordinate system of another, reference, NIFTI image. The reference overlay is specified by theDisplayContext.displaySpaceattribute.
The NiftiOpts.transform property controls how the image data is
transformed into the display coordinate system. It allows any of the above
spaces to be specified (as id, pixdim, pixdim-flip, affine`,
or reference respectively).
Pixdim flip¶
The pixdim-flip transform is the coordinate system used internally by many
of the FSL tools. For instance, this is the coordinate system used by
FSLView, by flirt, and in the VTK sub-cortical segmentation model files
output by first.
Furthermore, the vectors in eigenvector images images output by dtifit are
oriented according to this space, so if the input data is in neurological
orientation, these vectors need to be inverted along the x axis.
What is a voxel?¶
Regardless of the space in which the Nifti is displayed , the
voxel-to-display space transformation (and in general, all of FSLeyes) assumes
that integer voxel coordinates correspond to the centre of the voxel in the
display coordinate system. In other words, a voxel at location:
[x, y, z]
is assumed to occupy the space that corresponds to:
[x-0.5 - x+0.5, y-0.5 - y+0.5, z-0.5 - z+0.5]
For example, if the NiftiOpts.transform property is set to id, the
voxel:
[2, 3, 4]
is drawn such that it occupies the space:
[1.5 - 2.5, 2.5 - 3.5, 3.5 - 4.5]
This convention is in line with the convention defined by the NIFTI
specification: it assumes that the voxel coordinates [x, y, z] correspond
to the centre of a voxel.
-
class
fsleyes.displaycontext.niftiopts.NiftiOpts(*args, **kwargs)[source]¶ Bases:
fsleyes.displaycontext.display.DisplayOptsThe
NiftiOptsclass describes how aNiftioverlay should be displayed.NiftiOptsis the base class for a number ofDisplayOptssub-classes - it contains display options which are common to all overlay types that represent a NIFTI image.-
volume= <MagicMock name='mock.Int()' id='4116300320'>¶ If the
Imagehas more than 3 dimensions, the current volume to display. The volume dimension is controlled by thevolumeDimproperty.
-
volumeDim= <MagicMock name='mock.Int()' id='4116300320'>¶ For images with more than three dimensions, this property controls the dimension that the
volumeproperty indexes into. When thevolumeDimchanges, thevolumefor the previousvolumeDimis fixed at its last value, and used for subsequent lookups.
-
transform= <MagicMock name='mock.Choice()' id='4117029600'>¶ This property defines how the overlay should be transformd into the display coordinate system. See the note on coordinate systems for important information regarding this property.
-
displayXform= <MagicMock name='mock.Array()' id='4116014608'>¶ A custom transformation matrix which is concatenated on to the voxel -> world transformation of the
Niftioverlay.This transform is intended for temporary changes to the overlay display (when
DisplayContext.displaySpace== 'world') - changes to it will not result in the :DisplayContext.boundsbeing updated.If you change the
displayXform, make sure to change it back to an identity matrix when you are done.
-
enableOverrideDataRange= <MagicMock name='mock.Boolean()' id='4117273880'>¶ By default, the
Image.dataRangeproperty is used to set display and clipping ranges. However, if this property isTrue, theoverrideDataRangeis used instead.- ..note:: The point of this property is to make it easier to display images
with a very large data range driven by outliers. On platforms which do not support floating point textures, these images are impossible to display unless they are normalised according to a smaller data range. See the
Texture3D.__determineTextureType()method for some more details.
-
overrideDataRange= <MagicMock name='mock.Bounds()' id='4116394552'>¶ Data range used in place of the
Image.dataRangeif theenableOverrideDataRangeproperty isTrue.
-
__init__(*args, **kwargs)[source]¶ Create a
NiftiOptsinstance.All arguments are passed through to the
DisplayOptsconstructor.
-
destroy()[source]¶ Calls the
DisplayOpts.destroy()method.
-
__toggleSiblingListeners(enable=True)¶ Enables/disables the
volumeDimlisteners of siblingNiftiOptsinstances. This is used by the__volumeDimChanged()method to avoid nastiness.
-
__volumeDimChanged(*a)¶ Called when the
volumeDimchanges. Saves the value ofvolumefor the lastvolumeDim, and restores the previous value ofvolumefor the newvolumeDim.
-
__overlayTransformChanged(*a)¶ Called when the
Niftioverlay sends a notification on the'transform'topic, indicating that its voxel->world transformation matrix has been updated.
-
__displaySpaceTransformChanged(*a)¶ Called when the
DisplayContext.displaySpaceis aNiftioverlay, and itsNifti.voxToWorldMatchanges. Updates the transformation matrices for this image.
-
__transformChanged(*a)¶ Called when the
transformproperty changes.Calculates the min/max values of a 3D bounding box, in the display coordinate system, which is big enough to contain the image. Sets the
DisplayOpts.boundsproperty accordingly.
-
__displaySpaceChanged(*a)¶ Called when the
DisplayContext.displaySpaceproperty changes. Re-generates transformation matrices, and re-calculates the displaybounds(via calls to__setupTransforms()and__transformChanged()).
-
__displayXformChanged(*a)¶ Called when the
displayXformproperty changes. Updates the transformation matrices andboundsaccordingly.Critically, when the
displayXformproperty changes, theDisplayContextis not notified. This is because thedisplayXformis intended for temporary changes.
-
__setupTransforms()¶ Calculates transformation matrices between all of the possible spaces in which the overlay may be displayed.
These matrices are accessible via the
getTransform()method.
-
__module__= 'fsleyes.displaycontext.niftiopts'¶
-
classmethod
getVolumeProps()[source]¶ Overrides
DisplayOpts.getVolumeProps(). Returns a list of property names which control the displayed volume/timepoint.
-
getTransform(from_, to, xform=None)[source]¶ Return a matrix which may be used to transform coordinates from
from_toto. Valid values forfrom_andtoare:idVoxel coordinates
voxelEquivalent to
id.pixdimVoxel coordinates, scaled by voxel dimensions
pixdim-flipVoxel coordinates, scaled by voxel dimensions, and with the X axis flipped if the affine matrix has a positivie determinant. If the affine matrix does not have a positive determinant, this is equivalent to
pixdim.pixflipEquivalent to
pixdim-flip.affineWorld coordinates, as defined by the NIFTI
qform/sform. SeeImage.voxToWorldMat.worldEquivalent to
affine.referencepixdim-flipcoordinates of the reference image specified by theDisplayContext.displaySpaceattribute. If thedisplaySpaceis set to'world', this is equivalent toaffine.refEquivalent to
reference.displayEquivalent to the current value of
transform.textureVoxel coordinates scaled to lie between 0.0 and 1.0, suitable for looking up voxel values when stored as an OpenGL texture.
If the
xformparameter is provided, and one offrom_ortoisdisplay, the value ofxformis used instead of the current value oftransform.
-
roundVoxels(voxels, daxes=None, roundOther=False)[source]¶ Round the given voxel coordinates to integers. This is a surprisingly complicated operation.
FSLeyes and the NIFTI standard map integer voxel coordinates to the voxel centre. For example, a voxel [3, 4, 5] fills the space:
[2.5-3.5, 3.5-4.5, 4.5-5.5].
So all we need to do is round to the nearest integer. But there are a few problems with breaking ties when rounding…
The numpy.round function breaks ties (e.g. 7.5) by rounding to the nearest even integer, which can cause funky behaviour. So instead of using numpy.round, we take floor(x+0.5), to force consistent behaviour (i.e. always rounding central values up).
The next problem is that we have to round the voxel coordaintes carefully, depending on the orientation of the voxel axis w.r.t. the display axis. We want to round in the same direction in the display coordinate system, regardless of the voxel orientation. So we need to check the orientation of the voxel axis, and round down or up accordingly.
This is to handle scenarios where we have two anatomically aligned images, but with opposing storage orders (e.g. one stored neurologically, and one stored radiologically). If we have such images, and the display location is on a voxel boundary, we want the voxel coordinates for one image to be rounded in the same anatomical direction (i.e. the same direction in the display coordinate system). Otherwise the same display location will map to mis-aligned voxels in the two images, because the voxel coordinate rounding will move in anatomically opposing directions.
This method also prevents coordinates that are close to 0 from being set to -1, and coordinates that are close to the axis size from being set to (size + 1). In other words, voxel coordinates which are on the low or high boundaries will be rounded so as to be valid voxel coordinates.
- Parameters
voxels – A
(N, 3)numpyarray containing the voxel coordinates to be rounded.daxes – Display coordinate system axes along which to round the coordinates (defaults to all axes).
roundOther – If
True, any voxel axes which are not indaxeswill still be rounded, but not with an orientation-specific rounding convention.
- Returns
The
voxels, rounded appropriately.
-
transformCoords(coords, from_, to_, vround=False, vector=False, pre=None, post=None)[source]¶ Transforms the given coordinates from
from_toto_.The
from_andto_parameters must be those accepted by thegetTransform()method.- Parameters
coords – Coordinates to transform
from – Space to transform from
to – Space to transform to
vround – If
True, andto_ in ('voxel', 'id), the transformed coordinates are rounded to the nearest integer.vector – Defaults to
False. IfTrue, the coordinates are treated as vectors.pre – Transformation to apply before the
from_-to-totransformation.post – Transformation to apply after the
from_-to-totransformation.
-
getVoxel(xyz=None, clip=True, vround=True)[source]¶ Calculates and returns the voxel coordinates corresponding to the given location (assumed to be in the display coordinate system) for the
Niftiassociated with thisNiftiOptsinstance..- Parameters
xyz – Display space location to convert to voxels. If not provided, the current
DisplayContext.locationis used.clip – If
False, and the transformed coordinates are out of the voxel coordinate bounds, the coordinates returned anyway. Defaults toTrue.vround – If
True, the returned voxel coordinates are rounded to the nearest integer. Otherwise they may be fractional.
- Returns
Noneif the location is outside of the image bounds, unlessclip=False.
-