Inheritance diagram for nipy.core.reference.coordinate_map:
This module describes two types of mappings:
inverse function.
necessarily of the same dimension, hence not always invertible.
Each of these objects is meant to encapsulate a tuple of (domain, range, function). Each of the mapping objects contain all the details about their domain CoordinateSystem, their range CoordinateSystem and the mapping between them.
They are separate classes, neither one inheriting from the other. They do, however, share some parts of an API, each having methods:
These methods are implemented by module level functions of the same name.
They also share some attributes:
AffineTransforms) and return their composition. If they are all AffineTransforms, an AffineTransform is returned. This checks to ensure that domains and ranges of the various mappings agree.
AffineTransforms) and return a new mapping that has domain and range given by the concatenation of their domains and ranges, and the mapping simply concatenates the output of each of the individual mappings. If they are all AffineTransforms, an AffineTransform is returned. If they are all AffineTransforms that are in fact linear (i.e. origin=0) then can is represented as a block matrix with the size of the blocks determined by
range. For mapping m, this is the same as product(AffineTransform.identity(‘concat’), m)
Bases: object
Class for affine transformation from domain to a range
This class has an affine attribute, which is a matrix representing the affine transformation in homogeneous coordinates. This matrix is used to evaluate the function, rather than having an explicit function (as is the case for a CoordinateMap).
Examples
>>> inp_cs = CoordinateSystem('ijk')
>>> out_cs = CoordinateSystem('xyz')
>>> cm = AffineTransform(inp_cs, out_cs, np.diag([1, 2, 3, 1]))
>>> cm
AffineTransform(
function_domain=CoordinateSystem(coord_names=('i', 'j', 'k'), name='', coord_dtype=float64),
function_range=CoordinateSystem(coord_names=('x', 'y', 'z'), name='', coord_dtype=float64),
affine=array([[ 1., 0., 0., 0.],
[ 0., 2., 0., 0.],
[ 0., 0., 3., 0.],
[ 0., 0., 0., 1.]])
)
>>> cm.affine
array([[ 1., 0., 0., 0.],
[ 0., 2., 0., 0.],
[ 0., 0., 3., 0.],
[ 0., 0., 0., 1.]])
>>> cm([1,1,1])
array([ 1., 2., 3.])
>>> icm = cm.inverse()
>>> icm([1,2,3])
array([ 1., 1., 1.])
Methods
__call__ | |
from_params | |
from_start_step | |
identity | |
inverse | |
renamed_domain(mapping, newnames[, name]) | New coordmap with the coordinates of function_domain renamed |
renamed_range(mapping, newnames) | New coordmap with the coordinates of function_range renamed |
reordered_domain(mapping[, order]) | New coordmap with the coordinates of function_domain reordered |
reordered_range(mapping[, order]) | New coordmap with the coordinates of function_range reordered |
similar_to |
Initialize AffineTransform
Parameters : | function_domain : CoordinateSystem
function_range : CoordinateSystem
affine : array-like
|
---|
Notes
The dtype of the resulting matrix is determined by finding a safe typecast for the function_domain, function_range and affine.
Create AffineTransform from innames and outnames
Parameters : | innames : sequence of str or str
outnames : seqence of str or str
params : AffineTransform, array or (array, array)
domain_name : str, optional
range_name : str, optional
|
---|---|
Returns : | aff : AffineTransform |
Notes
Precondition : | len(shape) == len(names) |
---|---|
Raises ValueError: | |
if len(shape) != len(names) |
New AffineTransform from names, start and step.
Parameters : | innames : sequence of str or str
outnames : seqence of str or str
start : sequence of float
step : sequence of float
domain_name : str, optional
range_name : str, optional
|
---|---|
Returns : | cm : CoordinateMap |
Notes
len(names) == len(start) == len(step)
Examples
>>> cm = AffineTransform.from_start_step('ijk', 'xyz', [1, 2, 3], [4, 5, 6])
>>> cm.affine
array([[ 4., 0., 0., 1.],
[ 0., 5., 0., 2.],
[ 0., 0., 6., 3.],
[ 0., 0., 0., 1.]])
Return an identity coordmap of the given shape
Parameters : | coord_names : sequence of str or str
name : str, optional
|
---|---|
Returns : | cm : CoordinateMap
|
Examples
>>> cm = AffineTransform.identity('ijk', 'somewhere')
>>> cm.affine
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.]])
>>> cm.function_domain
CoordinateSystem(coord_names=('i', 'j', 'k'), name='somewhere', coord_dtype=float64)
>>> cm.function_range
CoordinateSystem(coord_names=('i', 'j', 'k'), name='somewhere', coord_dtype=float64)
Return coordinate map with inverse affine transform or None
Parameters : | preserve_dtype : bool
|
---|---|
Returns : | aff_cm_inv : AffineTransform instance or None
|
Examples
>>> input_cs = CoordinateSystem('ijk', coord_dtype=np.int)
>>> output_cs = CoordinateSystem('xyz', coord_dtype=np.int)
>>> affine = np.array([[1,0,0,1],
... [0,1,0,1],
... [0,0,1,1],
... [0,0,0,1]])
>>> affine_transform = AffineTransform(input_cs, output_cs, affine)
>>> affine_transform([2,3,4])
array([3, 4, 5])
The inverse transform, by default, generates a floating point inverse matrix and therefore floating point output:
>>> affine_transform_inv = affine_transform.inverse()
>>> affine_transform_inv([2, 6, 12])
array([ 1., 5., 11.])
You can force it to preserve the coordinate system dtype with the preserve_dtype flag:
>>> at_inv_preserved = affine_transform.inverse(preserve_dtype=True)
>>> at_inv_preserved([2, 6, 12])
array([ 1, 5, 11])
If you preserve_dtype, and there is no inverse affine preserving the dtype, the inverse is None:
>>> affine2 = affine.copy()
>>> affine2[0, 0] = 2 # now inverse can't be integer
>>> aff_t = AffineTransform(input_cs, output_cs, affine2)
>>> aff_t.inverse(preserve_dtype=True) is None
True
New AffineTransform with function_domain renamed
Parameters : | newnames : dict
|
---|---|
Returns : | newmapping : AffineTransform
|
Examples
>>> affine_domain = CoordinateSystem('ijk')
>>> affine_range = CoordinateSystem('xyz')
>>> affine_matrix = np.identity(4)
>>> affine_mapping = AffineTransform(affine_domain, affine_range, affine_matrix)
>>> new_affine_mapping = affine_mapping.renamed_domain({'i':'phase','k':'freq','j':'slice'})
>>> new_affine_mapping.function_domain
CoordinateSystem(coord_names=('phase', 'slice', 'freq'), name='', coord_dtype=float64)
>>> new_affine_mapping = affine_mapping.renamed_domain({'i':'phase','k':'freq','l':'slice'})
Traceback (most recent call last):
...
ValueError: no domain coordinate named l
New AffineTransform with renamed function_domain
Parameters : | newnames : dict
|
---|---|
Returns : | newmapping : AffineTransform
|
Examples
>>> affine_domain = CoordinateSystem('ijk')
>>> affine_range = CoordinateSystem('xyz')
>>> affine_matrix = np.identity(4)
>>> affine_mapping = AffineTransform(affine_domain, affine_range, affine_matrix)
>>> new_affine_mapping = affine_mapping.renamed_range({'x':'u'})
>>> new_affine_mapping.function_range
CoordinateSystem(coord_names=('u', 'y', 'z'), name='', coord_dtype=float64)
>>> new_affine_mapping = affine_mapping.renamed_range({'w':'u'})
Traceback (most recent call last):
...
ValueError: no range coordinate named w
New AffineTransform with function_domain reordered
Default behaviour is to reverse the order of the coordinates.
Parameters : | order : sequence
|
---|---|
Returns : | newmapping :AffineTransform :
|
Examples
>>> input_cs = CoordinateSystem('ijk')
>>> output_cs = CoordinateSystem('xyz')
>>> cm = AffineTransform(input_cs, output_cs, np.identity(4))
>>> cm.reordered_domain('ikj').function_domain
CoordinateSystem(coord_names=('i', 'k', 'j'), name='', coord_dtype=float64)
New AffineTransform with function_range reordered
Defaults to reversing the coordinates of function_range.
Parameters : | order : sequence
|
---|---|
Returns : | newmapping : AffineTransform
|
Examples
>>> input_cs = CoordinateSystem('ijk')
>>> output_cs = CoordinateSystem('xyz')
>>> cm = AffineTransform(input_cs, output_cs, np.identity(4))
>>> cm.reordered_range('xzy').function_range
CoordinateSystem(coord_names=('x', 'z', 'y'), name='', coord_dtype=float64)
>>> cm.reordered_range([0,2,1]).function_range.coord_names
('x', 'z', 'y')
>>> newcm = cm.reordered_range('yzx')
>>> newcm.function_range.coord_names
('y', 'z', 'x')
Does other have similar coordinate systems and same mappings?
A “similar” coordinate system is one with the same coordinate names and data dtype, but ignoring the coordinate system name.
Bases: object
Class to create coordinate maps of different dimensions
Methods
__call__ | |
affine_maker | |
generic_maker | |
make_affine | |
make_cmap |
Create coordinate map maker
Parameters : | domain_maker : callable
range_maker : callable
|
---|
Examples
>>> from nipy.core.reference.coordinate_system import CoordSysMaker
>>> dmaker = CoordSysMaker('ijkl', 'generic-array')
>>> rmaker = CoordSysMaker('xyzt', 'generic-scanner')
>>> cm_maker = CoordMapMaker(dmaker, rmaker)
alias of AffineTransform
alias of CoordinateMap
Create affine coordinate map
Parameters : | affine : (M, N) array-like
append_zooms : scalar or sequence length E
append_offsets : scalar or sequence length F
|
---|---|
Returns : | affmap : AffineTransform coordinate map |
Examples
>>> from nipy.core.reference.coordinate_system import CoordSysMaker
>>> dmaker = CoordSysMaker('ijkl', 'generic-array')
>>> rmaker = CoordSysMaker('xyzt', 'generic-scanner')
>>> cm_maker = CoordMapMaker(dmaker, rmaker)
>>> cm_maker.make_affine(np.diag([2,3,4,1]))
AffineTransform(
function_domain=CoordinateSystem(coord_names=('i', 'j', 'k'), name='generic-array', coord_dtype=float64),
function_range=CoordinateSystem(coord_names=('x', 'y', 'z'), name='generic-scanner', coord_dtype=float64),
affine=array([[ 2., 0., 0., 0.],
[ 0., 3., 0., 0.],
[ 0., 0., 4., 0.],
[ 0., 0., 0., 1.]])
)
We can add extra orthogonal dimensions, by specifying the diagonal elements:
>>> cm_maker.make_affine(np.diag([2,3,4,1]), 6)
AffineTransform(
function_domain=CoordinateSystem(coord_names=('i', 'j', 'k', 'l'), name='generic-array', coord_dtype=float64),
function_range=CoordinateSystem(coord_names=('x', 'y', 'z', 't'), name='generic-scanner', coord_dtype=float64),
affine=array([[ 2., 0., 0., 0., 0.],
[ 0., 3., 0., 0., 0.],
[ 0., 0., 4., 0., 0.],
[ 0., 0., 0., 6., 0.],
[ 0., 0., 0., 0., 1.]])
)
Or the diagonal elements and the offset elements:
>>> cm_maker.make_affine(np.diag([2,3,4,1]), [6], [9])
AffineTransform(
function_domain=CoordinateSystem(coord_names=('i', 'j', 'k', 'l'), name='generic-array', coord_dtype=float64),
function_range=CoordinateSystem(coord_names=('x', 'y', 'z', 't'), name='generic-scanner', coord_dtype=float64),
affine=array([[ 2., 0., 0., 0., 0.],
[ 0., 3., 0., 0., 0.],
[ 0., 0., 4., 0., 0.],
[ 0., 0., 0., 6., 9.],
[ 0., 0., 0., 0., 1.]])
)
Coordinate map with transform function xform
Parameters : | domain_N : int
xform : callable
inv_xform : None or callable, optional
|
---|---|
Returns : | cmap : CoordinateMap |
Examples
>>> from nipy.core.reference.coordinate_system import CoordSysMaker
>>> dmaker = CoordSysMaker('ijkl', 'generic-array')
>>> rmaker = CoordSysMaker('xyzt', 'generic-scanner')
>>> cm_maker = CoordMapMaker(dmaker, rmaker)
>>> cm_maker.make_cmap(4, lambda x : x+1)
CoordinateMap(
function_domain=CoordinateSystem(coord_names=('i', 'j', 'k', 'l'), name='generic-array', coord_dtype=float64),
function_range=CoordinateSystem(coord_names=('x', 'y', 'z', 't'), name='generic-scanner', coord_dtype=float64),
function=<function <lambda> at ...>
)
Bases: object
A set of domain and range CoordinateSystems and a function between them.
For example, the function may represent the mapping of a voxel (the domain of the function) to real space (the range). The function may be an affine or non-affine transformation.
Examples
>>> function_domain = CoordinateSystem('ijk', 'voxels')
>>> function_range = CoordinateSystem('xyz', 'world')
>>> mni_orig = np.array([-90.0, -126.0, -72.0])
>>> function = lambda x: x + mni_orig
>>> inv_function = lambda x: x - mni_orig
>>> cm = CoordinateMap(function_domain, function_range, function, inv_function)
Map the first 3 voxel coordinates, along the x-axis, to mni space:
>>> x = np.array([[0,0,0], [1,0,0], [2,0,0]])
>>> cm.function(x)
array([[ -90., -126., -72.],
[ -89., -126., -72.],
[ -88., -126., -72.]])
>>> x = CoordinateSystem('x')
>>> y = CoordinateSystem('y')
>>> m = CoordinateMap(x, y, np.exp, np.log)
>>> m
CoordinateMap(
function_domain=CoordinateSystem(coord_names=('x',), name='', coord_dtype=float64),
function_range=CoordinateSystem(coord_names=('y',), name='', coord_dtype=float64),
function=<ufunc 'exp'>,
inverse_function=<ufunc 'log'>
)
>>> m.inverse()
CoordinateMap(
function_domain=CoordinateSystem(coord_names=('y',), name='', coord_dtype=float64),
function_range=CoordinateSystem(coord_names=('x',), name='', coord_dtype=float64),
function=<ufunc 'log'>,
inverse_function=<ufunc 'exp'>
)
Attributes
function_domain | |
function_range | |
function | |
inverse_function |
Methods
__call__ | |
function | |
inverse | |
inverse_function | |
renamed_domain(mapping, newnames[, name]) | New coordmap with the coordinates of function_domain renamed |
renamed_range(mapping, newnames) | New coordmap with the coordinates of function_range renamed |
reordered_domain(mapping[, order]) | New coordmap with the coordinates of function_domain reordered |
reordered_range(mapping[, order]) | New coordmap with the coordinates of function_range reordered |
similar_to |
Create a CoordinateMap given function, domain and range.
Parameters : | function_domain : CoordinateSystem
function_range : CoordinateSystem
function : callable
inverse_function : None or callable, optional
|
---|---|
Returns : | coordmap : CoordinateMap |
New CoordinateMap with the functions reversed
New CoordinateMap with function_domain renamed
Parameters : | newnames : dict
|
---|---|
Returns : | newmaping : CoordinateMap
|
Examples
>>> domain = CoordinateSystem('ijk')
>>> range = CoordinateSystem('xyz')
>>> cm = CoordinateMap(domain, range, lambda x:x+1)
>>> new_cm = cm.renamed_domain({'i':'phase','k':'freq','j':'slice'})
>>> new_cm.function_domain
CoordinateSystem(coord_names=('phase', 'slice', 'freq'), name='', coord_dtype=float64)
>>> new_cm = cm.renamed_domain({'i':'phase','k':'freq','l':'slice'})
Traceback (most recent call last):
...
ValueError: no domain coordinate named l
New CoordinateMap with function_domain renamed
Parameters : | newnames : dict
|
---|---|
Returns : | newmapping : CoordinateMap
|
Examples
>>> domain = CoordinateSystem('ijk')
>>> range = CoordinateSystem('xyz')
>>> cm = CoordinateMap(domain, range, lambda x:x+1)
>>> new_cm = cm.renamed_range({'x':'u'})
>>> new_cm.function_range
CoordinateSystem(coord_names=('u', 'y', 'z'), name='', coord_dtype=float64)
>>> new_cm = cm.renamed_range({'w':'u'})
Traceback (most recent call last):
...
ValueError: no range coordinate named w
Create a new CoordinateMap with the coordinates of function_domain reordered. Default behaviour is to reverse the order of the coordinates.
Parameters : | order : sequence
|
---|---|
Returns : | newmapping : CoordinateMap
|
Examples
>>> input_cs = CoordinateSystem('ijk')
>>> output_cs = CoordinateSystem('xyz')
>>> cm = CoordinateMap(input_cs, output_cs, lambda x:x+1)
>>> cm.reordered_domain('ikj').function_domain
CoordinateSystem(coord_names=('i', 'k', 'j'), name='', coord_dtype=float64)
Nnew CoordinateMap with function_range reordered.
Defaults to reversing the coordinates of function_range.
Parameters : | order : sequence
|
---|---|
Returns : | newmapping : CoordinateMap
|
Examples
>>> input_cs = CoordinateSystem('ijk')
>>> output_cs = CoordinateSystem('xyz')
>>> cm = CoordinateMap(input_cs, output_cs, lambda x:x+1)
>>> cm.reordered_range('xzy').function_range
CoordinateSystem(coord_names=('x', 'z', 'y'), name='', coord_dtype=float64)
>>> cm.reordered_range([0,2,1]).function_range.coord_names
('x', 'z', 'y')
>>> newcm = cm.reordered_range('yzx')
>>> newcm.function_range.coord_names
('y', 'z', 'x')
Does other have similar coordinate systems and same mappings?
A “similar” coordinate system is one with the same coordinate names and data dtype, but ignoring the coordinate system name.
Append input and output dimension to coordmap
Parameters : | cm : Affine
in_name : str
out_name : str
start : float, optional
step : float, optional
|
---|---|
Returns : | cm_plus : Affine
|
Examples
Typical use is creating a 4D coordinate map from a 3D
>>> cm3d = AffineTransform.from_params('ijk', 'xyz', np.diag([1,2,3,1]))
>>> cm4d = append_io_dim(cm3d, 'l', 't', 9, 5)
>>> cm4d.affine
array([[ 1., 0., 0., 0., 0.],
[ 0., 2., 0., 0., 0.],
[ 0., 0., 3., 0., 0.],
[ 0., 0., 0., 5., 9.],
[ 0., 0., 0., 0., 1.]])
Return mapping between input and output axes
Parameters : | coordmap : Affine
direction : {‘in2out’, ‘out2in’, ‘both’}
fix0: bool, optional :
|
---|---|
Returns : | map : dict or tuple
|
Return the composition of two or more CoordinateMaps.
Parameters : | cmaps : sequence of CoordinateMaps |
---|---|
Returns : | cmap : CoordinateMap
|
Examples
>>> cmap = AffineTransform.from_params('i', 'x', np.diag([2.,1.]))
>>> cmapi = cmap.inverse()
>>> id1 = compose(cmap,cmapi)
>>> id1.affine
array([[ 1., 0.],
[ 0., 1.]])
>>> id2 = compose(cmapi,cmap)
>>> id1.function_domain.coord_names
('x',)
>>> id2.function_domain.coord_names
('i',)
Drop dimensions axis_id from coordinate map, if orthogonal to others
If you specify an input dimension, drop that dimension and any corresponding output dimension, as long as all other outputs are orthogonal to dropped input. If you specify an output dimension, drop that dimension and any corresponding input dimension, as long as all other inputs are orthogonal to dropped output.
Parameters : | cm : class:AffineTransform
axis_id : int or str
fix0: bool, optional :
|
---|---|
Returns : | cm_redux : Affine
|
Raises : | AxisError: if `axis_id` is a str and does not match any no input or output :
AxisError: if specified `axis_id` affects more than a single input / output :
AxisError: if the named `axis_id` exists in both input and output, and they :
|
Examples
Typical use is in getting a 3D coordinate map from 4D
>>> cm4d = AffineTransform.from_params('ijkl', 'xyzt', np.diag([1,2,3,4,1]))
>>> cm3d = drop_io_dim(cm4d, 't')
>>> cm3d.affine
array([[ 1., 0., 0., 0.],
[ 0., 2., 0., 0.],
[ 0., 0., 3., 0.],
[ 0., 0., 0., 1.]])
A test to see if mapping1 is equal to mapping2 after possibly reordering the domain and range of mapping.
Parameters : | mapping1 : CoordinateMap or AffineTransform mapping2 : CoordinateMap or AffineTransform |
---|---|
Returns : | are_they_equal : bool |
Examples
>>> ijk = CoordinateSystem('ijk')
>>> xyz = CoordinateSystem('xyz')
>>> T = np.random.standard_normal((4,4))
>>> T[-1] = [0,0,0,1] # otherwise AffineTransform raises
... # an exception because
... # it's supposed to represent an
... # affine transform in homogeneous
... # coordinates
>>> A = AffineTransform(ijk, xyz, T)
>>> B = A.reordered_domain('ikj').reordered_range('xzy')
>>> C = B.renamed_domain({'i':'slice'})
>>> equivalent(A, B)
True
>>> equivalent(A, C)
False
>>> equivalent(B, C)
False
>>>
>>> D = CoordinateMap(ijk, xyz, np.exp)
>>> equivalent(D, D)
True
>>> E = D.reordered_domain('kij').reordered_range('xzy')
>>> # no non-AffineTransform will ever be
>>> # equivalent to a reordered version of itself,
>>> # because their functions don't evaluate as equal
>>> equivalent(D, E)
False
>>> equivalent(E, E)
True
>>>
>>> # This has not changed the order
>>> # of the axes, so the function is still the same
>>>
>>> F = D.reordered_range('xyz').reordered_domain('ijk')
>>> equivalent(F, D)
True
>>> id(F) == id(D)
False
Return input axis index for axis_id
axis_id can be integer, or a name of an input axis, or it can be the name of an output axis which maps to an input axis.
Parameters : | coordmap : AffineTransform axis_id : int or str
fix0: bool, optional :
|
---|---|
Returns : | inax : int
|
Raises : | AxisError: if no matching name found : AxisError : if name exists in both input and output and they do not map to
AxisError : if name present in output but no matching input |
Return input and output axis index for id axis_id in coordmap
Parameters : | cm : class:AffineTransform
axis_id : int or str
fix0: bool, optional :
|
---|---|
Returns : | in_index : None or int
out_index : None or int
|
Raises : | AxisError: if `axis_id` is a str and does not match any input or output :
AxisError: if the named `axis_id` exists in both input and output, and they :
|
Examples
>>> aff = [[0, 1, 0, 10], [1, 0, 0, 11], [0, 0, 1, 12], [0, 0, 0, 1]]
>>> cmap = AffineTransform('ijk', 'xyz', aff)
>>> io_axis_indices(cmap, 0)
(0, 1)
>>> io_axis_indices(cmap, 1)
(1, 0)
>>> io_axis_indices(cmap, -1)
(2, 2)
>>> io_axis_indices(cmap, 'j')
(1, 0)
>>> io_axis_indices(cmap, 'y')
(0, 1)
True if in_ax related only to out_ax in affine and vice versa
Parameters : | in_ax : int
out_ax : int
affine : array-like
allow_zero : bool, optional
|
---|---|
Returns : | tf : bool
|
Examples
>>> aff = np.eye(4)
>>> orth_axes(1, 1, aff)
True
>>> orth_axes(1, 2, aff)
False
“topological” product of two or more mappings
The mappings can be either AffineTransforms or CoordinateMaps.
If they are all AffineTransforms, the result is an AffineTransform, else it is a CoordinateMap.
Parameters : | cmaps : sequence of CoordinateMaps or AffineTransforms |
---|---|
Returns : | cmap : CoordinateMap |
Examples
>>> inc1 = AffineTransform.from_params('i', 'x', np.diag([2,1]))
>>> inc2 = AffineTransform.from_params('j', 'y', np.diag([3,1]))
>>> inc3 = AffineTransform.from_params('k', 'z', np.diag([4,1]))
>>> cmap = product(inc1, inc3, inc2)
>>> cmap.function_domain.coord_names
('i', 'k', 'j')
>>> cmap.function_range.coord_names
('x', 'z', 'y')
>>> cmap.affine
array([[ 2., 0., 0., 0.],
[ 0., 4., 0., 0.],
[ 0., 0., 3., 0.],
[ 0., 0., 0., 1.]])
>>> A1 = AffineTransform.from_params('ij', 'xyz', np.array([[2,3,1,0],[3,4,5,0],[7,9,3,1]]).T)
>>> A2 = AffineTransform.from_params('xyz', 'de', np.array([[8,6,7,4],[1,-1,13,3],[0,0,0,1]]))
>>> A1.affine
array([[ 2., 3., 7.],
[ 3., 4., 9.],
[ 1., 5., 3.],
[ 0., 0., 1.]])
>>> A2.affine
array([[ 8., 6., 7., 4.],
[ 1., -1., 13., 3.],
[ 0., 0., 0., 1.]])
>>> p=product(A1, A2)
>>> p.affine
array([[ 2., 3., 0., 0., 0., 7.],
[ 3., 4., 0., 0., 0., 9.],
[ 1., 5., 0., 0., 0., 3.],
[ 0., 0., 8., 6., 7., 4.],
[ 0., 0., 1., -1., 13., 3.],
[ 0., 0., 0., 0., 0., 1.]])
>>> np.allclose(p.affine[:3,:2], A1.affine[:3,:2])
True
>>> np.allclose(p.affine[:3,-1], A1.affine[:3,-1])
True
>>> np.allclose(p.affine[3:5,2:5], A2.affine[:2,:3])
True
>>> np.allclose(p.affine[3:5,-1], A2.affine[:2,-1])
True
>>>
>>> A1([3,4])
array([ 25., 34., 26.])
>>> A2([5,6,7])
array([ 129., 93.])
>>> p([3,4,5,6,7])
array([ 25., 34., 26., 129., 93.])
New coordmap with the coordinates of function_domain renamed
Parameters : | newnames: dict :
|
---|---|
Returns : | newmapping : CoordinateMap or AffineTransform
|
Examples
>>> affine_domain = CoordinateSystem('ijk')
>>> affine_range = CoordinateSystem('xyz')
>>> affine_matrix = np.identity(4)
>>> affine_mapping = AffineTransform(affine_domain, affine_range, affine_matrix)
>>> new_affine_mapping = affine_mapping.renamed_domain({'i':'phase','k':'freq','j':'slice'})
>>> new_affine_mapping.function_domain
CoordinateSystem(coord_names=('phase', 'slice', 'freq'), name='', coord_dtype=float64)
>>> new_affine_mapping = affine_mapping.renamed_domain({'i':'phase','k':'freq','l':'slice'})
Traceback (most recent call last):
...
ValueError: no domain coordinate named l
New coordmap with the coordinates of function_range renamed
Parameters : | newnames : dict
|
---|---|
Returns : | newmapping : CoordinateMap or AffineTransform
|
Examples
>>> affine_domain = CoordinateSystem('ijk')
>>> affine_range = CoordinateSystem('xyz')
>>> affine_matrix = np.identity(4)
>>> affine_mapping = AffineTransform(affine_domain, affine_range, affine_matrix)
>>> new_affine_mapping = affine_mapping.renamed_range({'x':'u'})
>>> new_affine_mapping.function_range
CoordinateSystem(coord_names=('u', 'y', 'z'), name='', coord_dtype=float64)
>>> new_affine_mapping = affine_mapping.renamed_range({'w':'u'})
Traceback (most recent call last):
...
ValueError: no range coordinate named w
New coordmap with the coordinates of function_domain reordered
Default behaviour is to reverse the order of the coordinates.
Parameters : | order: sequence :
|
---|---|
Returns : | newmapping : CoordinateMap or AffineTransform
|
Notes
If no reordering is to be performed, it returns a copy of mapping.
Examples
>>> input_cs = CoordinateSystem('ijk')
>>> output_cs = CoordinateSystem('xyz')
>>> cm = AffineTransform(input_cs, output_cs, np.identity(4))
>>> cm.reordered_domain('ikj').function_domain
CoordinateSystem(coord_names=('i', 'k', 'j'), name='', coord_dtype=float64)
New coordmap with the coordinates of function_range reordered
Defaults to reversing the coordinates of function_range.
Parameters : | order: sequence :
|
---|---|
Returns : | newmapping : CoordinateMap or AffineTransform
|
Notes
If no reordering is to be performed, it returns a copy of mapping.
Examples
>>> input_cs = CoordinateSystem('ijk')
>>> output_cs = CoordinateSystem('xyz')
>>> cm = AffineTransform(input_cs, output_cs, np.identity(4))
>>> cm.reordered_range('xzy').function_range
CoordinateSystem(coord_names=('x', 'z', 'y'), name='', coord_dtype=float64)
>>> cm.reordered_range([0,2,1]).function_range.coord_names
('x', 'z', 'y')
>>> newcm = cm.reordered_range('yzx')
>>> newcm.function_range.coord_names
('y', 'z', 'x')
Shift the origin of the domain
Parameters : | difference_vector : array
|
---|
Examples
>>> A = np.random.standard_normal((5,6))
>>> A[-1] = [0,0,0,0,0,1]
>>> affine_transform = AffineTransform(CS('ijklm', 'oldorigin'), CS('xyzt'), A)
>>> affine_transform.function_domain
CoordinateSystem(coord_names=('i', 'j', 'k', 'l', 'm'), name='oldorigin', coord_dtype=float64)
A random change of origin
>>> difference = np.random.standard_normal(5)
The same affine transforation with a different origin for its domain
>>> shifted_affine_transform = shifted_domain_origin(affine_transform, difference, 'neworigin')
>>> shifted_affine_transform.function_domain
CoordinateSystem(coord_names=('i', 'j', 'k', 'l', 'm'), name='neworigin', coord_dtype=float64)
Let’s check that things work
>>> point_in_old_basis = np.random.standard_normal(5)
This is the relation ship between coordinates in old and new origins
>>> np.allclose(shifted_affine_transform(point_in_old_basis), affine_transform(point_in_old_basis+difference))
True
>>> np.allclose(shifted_affine_transform(point_in_old_basis-difference), affine_transform(point_in_old_basis))
True
Shift the origin of the range.
Parameters : | difference_vector : array
|
---|
Examples
>>> A = np.random.standard_normal((5,6))
>>> A[-1] = [0,0,0,0,0,1]
>>> affine_transform = AffineTransform(CS('ijklm'), CS('xyzt', 'oldorigin'), A)
>>> affine_transform.function_range
CoordinateSystem(coord_names=('x', 'y', 'z', 't'), name='oldorigin', coord_dtype=float64)
Make a random shift of the origin in the range
>>> difference = np.random.standard_normal(4)
>>> shifted_affine_transform = shifted_range_origin(affine_transform, difference, 'neworigin')
>>> shifted_affine_transform.function_range
CoordinateSystem(coord_names=('x', 'y', 'z', 't'), name='neworigin', coord_dtype=float64)
>>>
Evaluate the transform and verify it does as expected
>>> point_in_domain = np.random.standard_normal(5)
Check that things work
>>> np.allclose(shifted_affine_transform(point_in_domain), affine_transform(point_in_domain) - difference)
True
>>> np.allclose(shifted_affine_transform(point_in_domain) + difference, affine_transform(point_in_domain))
True