Acquisition Metadata

Everything ScanImage® writes into a logged file comes from a property somewhere on hSI. This page is the map between the two: what goes into the header, which API produces it, and how to read it back.

See also

Output Files for the list of file types and ScanImage® BigTiff Specification for the byte-level layout. This page covers the API side.


The three metadata blocks

A ScanImage Tiff carries metadata in three places.

Block

Produced by

Contents

Non-varying frame data

hSI.getHeaderString()

The whole model state: every gettable property of hSI and its components. Written once per file, pointed at by the Software IFD tag.

ROI group data

hSI.getRoiDataString()

The serialized ROI group. Written once per file, pointed at by the Artist IFD tag.

Per-frame data

StripeData.getFrameDescription()

The handful of values that change frame to frame. Written into each frame’s ImageDescription tag.

str = hSI.getHeaderString();     % the non-varying block, as it appears in the file
str = hSI.getRoiDataString();    % the ROI block

The per-frame fields

These come straight off the StripeData for that frame, so if you are processing live you have the same values without parsing anything.

Header field

StripeData property

Meaning

frameNumbers

frameNumberAcqMode

Frame number counted from the start of the acquisition mode.

acquisitionNumbers

acqNumber

Which acquisition within the mode.

frameNumberAcquisition

frameNumberAcq

Frame number within that acquisition.

frameTimestamps_sec

frameTimestamp

Seconds from epoch to the first pixel of the frame.

acqTriggerTimestamps_sec

acqStartTriggerTimestamp

Seconds to the acquisition start trigger. 0 when there was none.

nextFileMarkerTimestamps_sec

nextFileMarkerTimestamp

Seconds to the last next-file marker. 0 when none was recorded.

endOfAcquisition

endOfAcquisition

Last frame of the acquisition.

endOfAcquisitionMode

endOfAcquisitionMode

Last frame of the acquisition mode.

dcOverVoltage

(always written false)

Reserved.

epoch

epochAcqMode

Wall-clock time of the first pixel of the acquisition mode, as a date vector.

Note

All the ..._sec values are relative to epoch, not to each other and not to the file. To get absolute wall-clock time for a frame, add frameTimestamps_sec to datenum(epoch).


Controlling what goes into the header

Property

Effect

hSI.useJsonHeaderFormat

Write the non-varying block and the per-frame block as JSON instead of the legacy name = value format. Changes what your reader has to parse.

hSI.mdlCustomProps

Cell array of extra model properties to include, named relative to hSI - for example 'hRoiManager.scanZoomFactor'.

hSI.extCustomProps

Cell array of extra properties from outside the model.

mdlHeaderExcludeProps

Declared per class, not set at run time. Lists properties each component keeps out of the header - device handles, transient state, log file names.

hSI.useJsonHeaderFormat = true;
hSI.mdlCustomProps = {'hRoiManager.scanZoomFactor'};

The machinery underneath is most.Model’s mdlGetHeaderString and mdlGetHeaderStruct - see The most Framework. getHeaderString rewrites the scanimage.SI. prefix to SI., which is why header fields read as SI.hRoiManager....

Warning

Adding properties with expensive getters to mdlCustomProps costs time on every file. Keep the list short.


Where the values come from

The header is a flat readout of the component model, so the mapping is direct. Some frequently used fields:

Header field

Source

SI.hRoiManager.pixelsPerLine, linesPerFrame, scanZoomFactor, scanRotation

RoiManager

SI.hRoiManager.scanFrameRate, scanFramePeriod, linePeriod, scanVolumeRate

Derived timing, RoiManager

SI.hRoiManager.imagingFovDeg, imagingFovUm

Field of view corner points, RoiManager

SI.hScan2D.sampleRate, pixelBinFactor, fillFractionSpatial, bidirectional, linePhase

Scan2D: Imaging Systems and Scan2D Subclasses

SI.hScan2D.flytoTimePerScanfield, flybackTimePerFrame

Transit and flyback timing, Scan2D: Imaging Systems

SI.hChannels.channelSave, channelDisplay, channelOffset, channelInputRange

Channels and Display

SI.hStackManager.numSlices, numVolumes, framesPerSlice, zs

hSI.hStackManager

SI.hBeams.powerFractions, lengthConstants, pzAdjust

hSI.hBeams

SI.hMotors.samplePosition

Motors

SI.objectiveResolution

Derived from hSI.hMotors.hCSMicron, ScanImage Coordinate System Instances


Reading it back

ScanImage ships readers for every file type it writes. They return the header as a struct whose fields mirror the property paths above, so header.SI.hRoiManager.linePeriod in a script is the same value as hSI.hRoiManager.linePeriod was at acquisition time.

Function

Returns

[header,Aout,imgInfo,rawStream] = scanimage.util.opentif(...)

Header and image data from a Tiff. Omitting Aout reads only the header, which is fast. See Open Tiff.

ScanImageTiffReader

The fast path for whole volumes, with Python, MATLAB and Julia bindings. See ScanImage® TiffReader.

[roiData,roiGroup,header,imageData,imgInfo] = scanimage.util.getMroiDataFromTiff(...)

RoiDataSimple objects plus the ROI group, for MROI acquisitions. See Generate Multi-ROI Data From Tiff.

[frames,roiGroup,header,imageData,imgInfo] = scanimage.util.getMroiFrameSequence(...)

The same data organized as a frame sequence rather than per ROI.

[hMroi,hStim,hIntegration] = scanimage.util.readTiffRoiData(filename,header)

The three ROI groups from the Artist tag. See Read ROI Group From Appended Tiff Data.

[header,pmtData,scannerPosData,roiGroup] = scanimage.util.readLineScanDataFiles(fileName)

Arbitrary line scanning data. Accepts either the .meta.txt or the .pmt.dat name. See Reading Line Scanning Data Files.

out = scanimage.util.readPhotostimMonitorFile(filename)

Photostimulation monitor records - x, y and beam power per sample. See Read Photostim Monitor File.

scanimage.util.resaveTiff(fileName,AoutImdata,newFileName,customHdr)

Write modified image data back out carrying the original file’s metadata. Useful for producing cleaned-up motion correction reference images that ScanImage will still accept.

Two helpers convert line scan data into more convenient forms: scanimage.util.lineScan2Tiff(file) writes a Tiff, and scanimage.util.lineScan2Kymo(file) produces a kymograph. scanimage.util.lineScan2Img is an example script, not a function - open it to see how a scanner set is rebuilt from a header, and adapt it.

% header only - does not read the image data
header = scanimage.util.opentif('experiment_00001.tif');

fprintf('%d x %d px, %.2f fps, zoom %g\n', ...
    header.SI.hRoiManager.pixelsPerLine, ...
    header.SI.hRoiManager.linesPerFrame, ...
    header.SI.hRoiManager.scanFrameRate, ...
    header.SI.hRoiManager.scanZoomFactor);

See also

ScannerSet and Scanner Models for rebuilding scan geometry from a header, and Recipes for a complete batch-processing example.