Acquisition Data Structures
Two classes carry acquired data through ScanImage®. scanimage.interfaces.StripeData is
what the imaging system hands to the rest of the application every time a stripe of samples
is ready; scanimage.mroi.RoiData is the per-ROI image container that a StripeData
carries. Between them they are what almost every piece of user analysis code touches, so it
is worth knowing their exact shapes.
See also
hSI.hDataManager produces them, hSI.hDisplay exposes them, and Acquisition Metadata describes how their fields end up in the Tiff header.
RoiData
scanimage.mroi.RoiData holds the image data for one ROI at multiple z depths. It is a
handle class, and it is copyable (matlab.mixin.Copyable).
hRoiData = hSI.hDisplay.getRoiDataArray(); % 1 x nRois array
Image data
Property |
Description |
|---|---|
|
Cell of cell arrays, indexed |
|
Numeric array of channel numbers, giving the meaning of the first index. |
|
Numeric array of z values, giving the meaning of the second index. |
|
Logical, default true. Whether the image data is stored transposed. |
|
Handle to the |
Important
The double indexing is channel-first, z-second, and the arrays are
transposed relative to how the image is displayed. A frame for channel 1 at the first
z is hRoiData(k).imageData{1}{1}.'.
hRoiDatas = hSI.hDisplay.getRoiDataArray();
for idx = 1:numel(hRoiDatas)
hRd = hRoiDatas(idx);
fprintf('%s: %d channels x %d zs\n',hRd.hRoi.name,numel(hRd.channels),numel(hRd.zs));
chIdx = find(hRd.channels == 1); % locate channel 1
zIdx = 1;
img = hRd.imageData{chIdx}{zIdx}.'; % transpose for display orientation
imagesc(img);
end
Striping
When hSI.hScan2D.stripingEnable is set, a RoiData may hold a partial frame.
Property |
Description |
|---|---|
|
Cell array of |
|
Number of lines in the complete frame, per z. Together with |
Warning
Code that assumes a full frame will silently process partial data when striping
is on. Either check stripePosition is empty, or hook frameAcquired rather than the
RoiDataUpdated event.
Timing and provenance
Property |
Description |
|---|---|
|
Acquisition number. |
|
Frame number within the current acquisition. |
|
Frame number within the current acquisition mode. |
|
Timestamp of the last stripe acquired, in the current acquisition mode. |
|
Timestamps per z index. |
|
|
|
|
|
Buffer of frequently used parameters, so they are not recomputed per frame. |
All of these are copied from the StripeData the RoiData arrived in.
Methods
Method |
Description |
|---|---|
|
Merge another |
|
Merge in place. |
|
Exponentially average new data into this one with coefficient |
|
Maximum intensity projection over z. Assumes the same scanfield at every z. |
|
Cast the image data to another numeric type. |
|
Scale the image data. |
|
Subset by channel. |
|
Subset by z. |
|
Clear the buffers, leaving the structure, zeroed, or empty respectively. |
RoiData implements saveobj / loadobj, so it can be saved to a .mat file and
read back with its ROI geometry intact.
The imageDataUpdated event fires when imageData changes; its event data names which
zs were updated.
Note
scanimage.mroi.RoiDataSimple is a lightweight variant used by the Tiff reading
utilities - see Generate Multi-ROI Data From Tiff. It
carries the image data and ROI geometry without the live-acquisition machinery.
StripeData
scanimage.interfaces.StripeData is the unit of data flow during an acquisition. One is
produced per stripe; with striping disabled that means one per frame. It is passed to
hSI.hDataManager.stripeAcquired(stripeData) and is available to user functions hooked on
frameAcquired.
Payload
Property |
Description |
|---|---|
|
1D cell array of |
|
Raw data samples. |
|
Start position of the raw samples. |
|
Active channel numbers for the current acquisition. |
|
Whether the image data is transposed. |
|
Channels for which histogram data was computed. |
Position in the acquisition
Property |
Description |
|---|---|
|
Frame number counted from the start of the acquisition mode. |
|
Frame number within the current acquisition. |
|
Current acquisition number. |
|
Stripe number within the frame. |
|
Unprocessed stripes still in the queue. A useful backpressure signal: if this grows, your callback is too slow. |
|
Total frames acquired. |
|
Index into, and the full list of, the z series for the current acquisition. |
|
Which stack mode the acquisition is using. |
Boundary flags
These are what user-function code branches on.
Flag |
True when |
|---|---|
|
This is the first stripe of a frame. |
|
This is the last stripe of a frame. |
|
This stripe begins or ends a volume. |
|
|
|
|
|
An overvoltage was detected on any active channel during the acquisition mode. |
Timing
Property |
Description |
|---|---|
|
Time of the first pixel of the acquisition mode, as a date string. |
|
Seconds from |
|
Seconds to the acquisition start trigger of the current acquisition. |
|
Seconds to the last next-file marker. |
Spatial context
Property |
Description |
|---|---|
|
|
|
|
% where in the sample was this frame acquired?
hPt = stripeData.focalPoint.transform(hSI.hCoordinateSystems.hCSSampleRelative);
fprintf('frame %d at %.1f %.1f %.1f um\n',stripeData.frameNumberAcqMode,hPt.points);
Methods
Method |
Description |
|---|---|
|
Build the per-frame metadata string that is written into the Tiff
|
|
Merge another stripe’s ROI data into this one. |
|
Merge in place, taking the new stripe’s position fields. |
|
Apply the corresponding |
Using them from a user function
The frameAcquired event is the normal entry point. Guard on the boundary flags rather
than assuming one call per frame.
function myFrameCallback(src,evt,varargin)
hSI = src.hSI;
sd = hSI.hDataManager.lastStripeData;
if isempty(sd) || ~sd.endOfFrame
return % partial stripe; wait for the full frame
end
for idx = 1:numel(sd.roiData)
hRd = sd.roiData{idx};
chIdx = find(hRd.channels == 1);
if isempty(chIdx); continue; end
img = hRd.imageData{chIdx}{1}.';
fprintf('frame %d, roi %s, mean %.1f\n', ...
sd.frameNumberAcqMode, hRd.hRoi.name, mean(img(:)));
end
end
Warning
This callback runs on the acquisition path. Work done here delays the display
and, under load, causes dropped frames. Watch stripesRemaining; if it climbs, buffer
the data and process it on a timer instead.
See also
Recipes for complete worked examples.