Motors

scanimage.components.Motors, reachable as hSI.hMotors, drives the XYZ stage and owns the chain of coordinate systems that ends in sample space. Almost every method takes or returns a Points object rather than a bare numeric triple, so a position is never ambiguous about which space it is expressed in.

See also

ScanImage Coordinate System Instances for the full motor coordinate system chain, and Sample Coordinate System for the concept.


Reading position

Member

Description

hPt = hSI.hMotors.getPosition(hCS)

Current stage position as a Points object in hCS. Motors that do not publish their position automatically are queried first, so this can block on a serial round-trip.

hPt = hSI.hMotors.getPositionLastKnown(hCS)

Same, but never queries the hardware; it transforms the last known position already held in the coordinate system tree. Use it in high-rate UI paths where a stale-by-one-update value is acceptable.

hSI.hMotors.samplePosition

1 x 3 numeric position in sample-relative microns.

hSI.hMotors.axesPosition

Raw axis positions as reported by the controllers.

hSI.hMotors.position_SampleAbsolute

Target position in sample-absolute coordinates.

xyz = hSI.hMotors.queryPosition()

Explicitly query every controller. Rarely needed - motors are expected to publish through their lastKnownPosition property.

xyz = hSI.hMotors.decodeMotorPosition()

Read the controllers’ lastKnownPosition and transform it into ScanImage coordinates.

hCSs = hSI.hCoordinateSystems;

hPt = hSI.hMotors.getPosition(hCSs.hCSSampleRelative);
fprintf('sample-relative: %.2f %.2f %.2f um\n',hPt.points);

hPtRef = hSI.hMotors.getPosition(hCSs.hCSReference);

Moving

Method

Description

hSI.hMotors.move(hPt,async,axes)

Move to a Points object in any coordinate system. async defaults to false (blocking). axes is a 1 x 3 logical selecting which axes to move; the unselected ones hold their current position.

hSI.hMotors.moveSample(position,async)

Move to a 1 x 3 position in sample-relative microns. NaN in an element leaves that axis where it is.

hSI.hMotors.movePtToPosition(hPt1,hPt2)

Move the stage so that the point hPt1 ends up at hPt2. Useful for “put this feature under the objective”.

hSI.hMotors.stop()

Stop all motion.

hSI.hMotors.setPositionTargetToCurrentPosition()

Discard a pending target and adopt the current position.

hSI.hMotors.reinitMotors(failedOnly)

Re-initialize the motor controllers.

% absolute move, sample-relative microns
hSI.hMotors.moveSample([100 0 -20]);

% relative move in Z only, leaving X and Y alone
hSI.hMotors.moveSample([NaN NaN hSI.hMotors.samplePosition(3) - 5]);

% move to a point that was defined in reference space
hPt = scanimage.mroi.coordinates.Points(hSI.hCoordinateSystems.hCSReference,[2 0 0]);
hSI.hMotors.move(hPt);

Warning

move enforces maxZStep and the configured Z limits, and throws rather than clipping when a request exceeds them. Wrap scripted moves in try/catch if a refused move should not stop your script.


Move constraints

Property / method

Description

moveTimeout_s

Timeout for a blocking move. Default 10 s.

maxZStep

Largest allowed Z displacement per move, in microns. Inf disables the check.

minPositionQueryInterval_s

Minimum interval between hardware position queries.

setMinZLimit() / clearMinZLimit()

Set the lower Z bound to the current position, or clear it.

setMaxZLimit() / clearMaxZLimit()

Set the upper Z bound to the current position, or clear it.

moveInProgress

Read-only. True while a move is running.

isHomed, errorTf, motorErrorMsg

Read-only status of the underlying controllers.


Relative zero and markers

Method

Description

hSI.hMotors.setRelativeZero(newCenterPt)

Define the origin of sample-relative space. With no argument the current position becomes zero.

hSI.hMotors.clearRelativeZero()

Reset sample-relative space to coincide with sample-absolute space.

hSI.hMotors.isRelativeZeroSet

Read-only logical.

hSI.hMotors.addMarker(name)

Store the current position as a named marker. Markers live in hSI.hMotors.markers.

hSI.hMotors.deleteMarker(id) / clearMarkers()

Remove one marker or all of them.

User defined positions

hSI.hMotors.defineUserPosition('cell_01');        % store the current position
hSI.hMotors.defineUserPosition('cell_02',[10 20 0]);
hSI.hMotors.gotoUserDefinedPosition('cell_01');   % by name, or by index
hSI.hMotors.saveUserDefinedPositions();           % to a .POS file
hSI.hMotors.loadUserDefinedPositions();
hSI.hMotors.clearUserDefinedPositions();

Alignment and rotation

The stage-to-scanner alignment is built from calibration points and written into the Motor Alignment coordinate system.

Method

Description

hSI.hMotors.addCalibrationPoint(motorPosition,motion)

Add a measured pair: where the stage was, and the image motion that resulted.

hSI.hMotors.undoLastCalibrationPoint()

Drop the most recent point.

hSI.hMotors.removeCalibrationPoint(idx)

Drop one point.

hSI.hMotors.resetCalibrationPoints()

Drop all points.

hSI.hMotors.createCalibrationMatrix()

Fit the collected points and apply the result to Motor Alignment.

hSI.hMotors.resetCalibrationMatrix()

Reset Motor Alignment to identity.

hSI.hMotors.abortCalibration()

Abort a running calibration.

hSI.hMotors.isAligned

Read-only logical.

azimuth and elevation express a deliberate rotation of the stage axes - a tilted objective, or a yaw applied by the user - and write into the Motor Rotation coordinate system.

hSI.hMotors.elevation = 30;   % degrees

See also

Alignment between Stage and Scanner for the guided procedure.


Coordinate systems owned by this component

The nodes are hidden properties but publicly readable, and are documented in ScanImage Coordinate System Instances:

hCSCoordinateSystem, hCSMicron, hCSAlignment, hCSRotation, hCSAxesScaling, hCSAxesPosition, hCSAntiAlignment, hCSSampleAbsolute, hCSSampleRelative.

% the objective calibration, in optical degrees per micron
disp(hSI.hMotors.hCSMicron.toParentAffine);

An uncalibrated hCSMicron defaults to diag([1/20 1/20 1 1]): 20 microns per optical degree in XY, with Z already in microns.


Events

samplePositionChanged is a throttled, debounced notification that the sample position has settled. Listen to it instead of samplePosition PostSet unless you genuinely need every intermediate value during a move - the throttle exists so that a slow stage reporting positions continuously cannot starve the frame display callbacks.

hL = most.ErrorHandler.addCatchingListener(hSI.hMotors,'samplePositionChanged', ...
     @(varargin)fprintf('%.1f %.1f %.1f\n',hSI.hMotors.samplePosition));

suspendSamplePositionChanged() and resumeSamplePositionChanged() bracket an interactive drag so the notification cannot fire mid-drag; the resume fires one un-debounced notification so consumers reconcile.