Coordinate System Classes

Every coordinate system in ScanImage® is an object derived from scanimage.mroi.coordinates.CoordinateSystem. A coordinate system is a node in a tree: it stores the transformation between itself and its parent, and nothing else. Transforming a point between any two coordinate systems is done by walking the tree from one node up to the common ancestor and back down to the other node, applying each node’s transformation in turn.

Because the transformations are composed at transform time, you never have to keep a “scanner to sample” matrix up to date by hand. Update the one node that changed - for example the stage alignment - and every path through that node changes with it.


The base class

scanimage.mroi.coordinates.CoordinateSystem is abstract, and is derived from scanimage.mroi.util.TreeNode.

Properties

Property

Description

name

Char array. Immutable, assigned in the constructor. Names must be unique across the whole tree - attaching a node whose subtree duplicates an existing name throws.

dimensions

Number of dimensions of the space. ScanImage’s main tree is 3-dimensional.

hParent

The parent coordinate system, or empty for a root node. Assigning hParent re-parents the node (and its subtree) at run time.

forwardable

Logical. True if points can be transformed from this coordinate system towards the parent. Maintained by the subclass.

reversible

Logical. True if points can be transformed from the parent into this coordinate system. Maintained by the subclass.

lock

Logical. When true, reset() and loading from disk are disabled for this node. Properties can still be set programmatically. ScanImage locks the nodes whose values are derived from other nodes or from live hardware readings, so that a stale value from a class data file can never drift in.

resetFcnHdl

Optional function handle @(hCS) that replaces the default reset behavior.

Methods

Method

Description

hPtsOut = hCS.transform(hPts)

Transform a Points object into hCS. This is the workhorse of the API. It resolves the path between hPts.hCoordinateSystem and hCS and applies each transformation along the way. Throws if no relationship exists, or if a node on the path is not forwardable / reversible in the required direction.

hCS.reset()

Reset this node’s transformation to identity (or to resetFcnHdl). No-op if lock is true.

s = hCS.toStruct(), hCS.fromStruct(s)

Serialize and deserialize the node. Used by the class data file. The struct carries the class name, dimensions, node name and parent name, so a mismatched struct is rejected rather than silently applied.

[parents,nodes] = hCS.getTree()

Return the full tree that this node belongs to, as a cell array of nodes plus their parents.

[path,toParent,commonAncestorIdx] = hCS.getRelationship(other)

Return the chain of nodes connecting two coordinate systems.

hCS.plotTree()

Open a figure visualizing the tree from this node.

Events

changed fires whenever the node’s transformation is modified. Listen to it if your code caches anything derived from a transformation.

hCS = hSI.hCoordinateSystems.hCSReference;
hL = most.ErrorHandler.addCatchingListener(hCS,'changed',@(varargin)disp('reference changed'));

CSLinear

scanimage.mroi.coordinates.CSLinear implements an affine transformation. This is the most common node type; the World, Reference, Focus and all Motor nodes are CSLinear.

hCS = scanimage.mroi.coordinates.CSLinear(name,dimensions,hParent);

Properties

  • toParentAffine - (dimensions+1) x (dimensions+1) homogeneous matrix mapping points from this coordinate system into the parent.

  • fromParentAffine - the matrix for the opposite direction.

Only one of the two is populated at a time. Setting one clears the other, and warns if the cleared one was not the identity. Whichever is set, the reverse direction is obtained by inverting the matrix, so forwardable and reversible are both true for any invertible matrix; a singular matrix makes the node one-way.

% a node that is offset by 10 um in z relative to its parent
T = eye(4);
T(3,4) = 10;
hCS.toParentAffine = T;

Tip

disp(hCS) on a CSLinear prints both matrices, which is the fastest way to inspect an alignment from the command window.


CSZAffineLut

scanimage.mroi.coordinates.CSZAffineLut implements a z-dependent 2D affine transformation: a lookup table of 3x3 affines, one per z plane, interpolated in z. This is how ScanImage represents an imaging system whose lateral alignment to reference space changes with depth (see flexible 3D characterization). It is restricted to 3 dimensions.

Properties

  • toParentLutEntries, fromParentLutEntries - arrays of scanimage.mroi.coordinates.cszaffinelut.LUTEntry. As with CSLinear, setting one clears the other.

Each LUTEntry holds

  • zfrom - the z value in this coordinate system,

  • zto - the corresponding z value in the parent,

  • affine2D - the 3x3 affine applied to XY at that z.

Useful methods on the entry array

Method

Description

T = entries.makeZAffines(z,reverse)

Interpolate the LUT and return the 3x3 XY affine(s) at the requested z value(s). z may be a vector, in which case T is 3 x 3 x numel(z). With a single entry the LUT degenerates to that entry’s affine; with no entries it returns identity.

entries.interpolate(pts), entries.interpolateReverse(pts)

Apply the LUT to an N x 3 array of points in the forward or reverse direction.

entries.sort(), entries.validate()

Order and sanity check the table. validate runs automatically in the property setter.

% the scanner-to-reference affine of the resonant scanner, evaluated at z = 20 um
zRef = 20;
T = hSI.hResScan.hCSZAffineLut.toParentLutEntries.makeZAffines(zRef);

% build a two-plane LUT by hand
e(1) = scanimage.mroi.coordinates.cszaffinelut.LUTEntry(0  ,0  ,eye(3));
e(2) = scanimage.mroi.coordinates.cszaffinelut.LUTEntry(100,100,[1.02 0 0.3; 0 1.02 -0.1; 0 0 1]);
hSI.hLinScan.hCSZAffineLut.fromParentLutEntries = e;

Attention

The alignment tools that populate these lookup tables are only available in Premium ScanImage®.


CSLut

scanimage.mroi.coordinates.CSLut transforms each dimension through an interpolant.

Properties

  • toParentInterpolant, fromParentInterpolant - 1 x dimensions cell arrays. Cell k holds the interpolant (typically a griddedInterpolant or a scatteredInterpolant) that produces dimension k of the output. An empty cell means that dimension passes through unchanged.

An interpolant with a single grid vector is evaluated on that dimension alone; a multi-dimensional interpolant is evaluated on the full point. This lets a single node express “z depends on x, y and z, while x and y are unchanged”, which is exactly how SLM field curvature correction and SLM diffraction efficiency are modeled.

% corrected z as a function of (x,y,z); x and y left alone
hCS.fromParentInterpolant = {[], [], hInterpolantZ};

CSFunction

scanimage.mroi.coordinates.CSFunction transforms points through arbitrary function handles.

Properties

  • toParentFunction, fromParentFunction - function handles of the form ptsOut = f(ptsIn) operating on N x dimensions arrays. An empty handle leaves points untouched.

Warning

Function handles cannot be meaningfully restored from a class data file. A CSFunction node checks on load whether the stored function matches, but it does not recreate it - whatever code created the node has to set the handles again.


CSDimConversion

scanimage.mroi.coordinates.CSDimConversion bridges spaces with different dimensionality, for example connecting a 2D pixel space to the 3D main tree.

hCS = scanimage.mroi.coordinates.CSDimConversion(name,dimensions,hParent, ...
                                                 parentDimensions,dimensionSelection);

dimensionSelection states which dimensions map onto which; when omitted it defaults to 1:min(dimensions,parentDimensions). Going towards the lower-dimensional side drops the unselected dimensions; going the other way fills them with zeros.


Choosing a node type

Class

Use when

CSLinear

The relationship is a fixed affine: translation, rotation, scaling, shear.

CSZAffineLut

The lateral relationship changes with depth and was measured plane by plane.

CSLut

The relationship is measured and non-affine, and is best represented by interpolants.

CSFunction

The relationship is known analytically but is not affine.

CSDimConversion

The two spaces do not have the same number of dimensions.