Stitching¶
- class controllers.Stitching¶
Bases:
handleSTITCHING - Controller for the Image Stitching tool.
Assembles a mosaic from overlapping 2D/3D tile images using a grid dialog, a position file, or a MIB2 filename pattern. Registration is performed by pairwise phase correlation + global weighted least-squares optimisation (MIST/BigStitcher approach). Fusion supports in-memory (Standard dataset) and streaming OME-Zarr3 (BigData) outputs.
Available from Ribbon -> Dataset -> Stitching.
- Constructor Summary
- Stitching(mibModel, varargin)¶
STITCHING - Constructor.
- Syntax:
obj = controllers.Stitching(mibModel) obj = controllers.Stitching(mibModel, BatchOpt) obj = controllers.Stitching(mibModel, NaN)- Input Arguments:
mibModel - handle to MibModel
varargin{1} (optional) - BatchOpt struct (batch run), or NaN (return BatchOpt to mibBatchController)
- Property Summary
- BatchOpt¶
cell array of listener handles
- automaticOptions¶
K-by-3 double - per-slice mosaic corrections [z dy dx] from the inspector’s Fix Z: every output slice >= z shifts in-plane by [dy dx] (cumulative over rows). Applied by planCanvas/fusers, persisted in the project sidecar; [] = none
- canvas¶
logical - true while obj.layout comes from a loaded project sidecar rather than from BatchOpt. The widgets may then describe a completely different job (a project carries no layout source/grid before schema v3), so anything that would silently re-derive the layout from BatchOpt must stand down. Cleared by buildLayoutFromBatchOpt, i.e. by every deliberate rebuild
- edges¶
struct array - tile layout (nomOrigin, tileSize, etc.)
- inspector¶
cell array of ROIMoved listener handles for tileROIs
- inspectorListeners¶
handle to the seam-inspector child controller (controllers.StitchingInspector), [] when not open
- intensityCorrection¶
cell array of listeners on the inspector (SeamsUpdated / CloseEvent)
- layout¶
structure compatible with batch processing
- layoutFromProject¶
struct from the last global solve (rmseTotal, nPruned, disconnectedTiles). Kept on the controller - not just inside optimizePositions_Callback - so the alignment-quality chip can be re-rendered whenever the edges change (e.g. the inspector excluding a seam) without re-solving; [] until the first solve
- listener¶
handle to the view (StitchingGUI), empty in batch mode
- mibModel¶
- positions¶
struct array - measured pairwise edges (i, j, direction, measured, quality, valid)
- resolvePending¶
struct from utils.stitch.estimateIntensityCorrection - the intensity correction every tile read is made with. Estimating it costs one pass over the tiles, so it is computed LAZILY by ensureIntensityCorrection and kept here; [] means “not estimated yet”, which is not the same as BatchOpt.IntensityCorrection = ‘None’ (that estimates to a neutral struct). Dropped whenever the layout is rebuilt or the method changes
- roiListeners¶
array of images.roi.Rectangle - draggable tile handles in edit mode
- seamScoresStamp¶
logical - an inspector edit (manual fix, exclude, undo) has changed the edge set while Auto re-solve was off, so obj.positions no longer follow from obj.edges. Lives HERE rather than on the inspector because the debt outlives the window: closing the inspector used to drop the flag with it, after which the chip stopped warning and Stitch fused the stale placement. Cleared by any solve (optimizePositions_Callback); stitchBtn_Callback settles it before fusing
- solverInfo¶
N-by-1 cell of 3x3 doubles - solved per-tile affine transforms (tile-local xy -> global xy) when TransformType is not Translation; {} for the translation solve
- tforms¶
N-by-3 double - solved tile origins [y x z]
- tileROIs¶
struct - feature-detector tuning (per-detector params, RANSAC, rotation invariance, downsampling) for the Feature-based method; same shape as controllers.Alignment.defaultAutomaticOptions
- tileStack¶
struct - output canvas plan (size, tilePlacement, etc.)
- view¶
handle to MibModel
- zSliceFixes¶
[1 x N] double or [] - the order Overwrite draws the tiles in, bottom first, as set in the seam inspector. [] = the default order (see utils.stitch.tileDrawOrder). Cleared with the layout; saved in the project.
- zarrExportOptions¶
struct - what obj.edges’ seamScores were computed for (.positions, .numEdges, .correctionMethod), so the same overlaps are not re-read by the next consumer that wants them. Set by controllers.Stitching.ensureSeamScores and by a project load whose sidecar already carried a complete score set; [] = not scored (yet). Compared against live state rather than explicitly invalidated, so nothing can forget to clear it
- Method Summary
- static ViewListner_Callback2(~, evnt)¶
VIEWLISTNER_CALLBACK2 - Static model-event listener guard.
- Syntax:
controllers.Stitching.ViewListner_Callback2(obj, src, evnt)- Input Arguments:
obj - handle to the Stitching controller
evnt - event data from the model
- addCallbacks()¶
ADDCALLBACKS - Wire all GUI widget callbacks for the Stitching controller.
- Syntax:
obj.addCallbacks()
BatchOpt-linked widgets are named exactly as their BatchOpt fields (ChildView copies the component name into the Tag, which utils.updateBatchOptFromGUI_Shared uses as the field name).
- applyProjectSettings(settings, skipFields)¶
APPLYPROJECTSETTINGS - Restore tool parameters from a project sidecar into BatchOpt.
- Syntax:
appliedFields = obj.applyProjectSettings(settings) appliedFields = obj.applyProjectSettings(settings, skipFields)
Reverses the flattening done by
controllers.Stitching.collectProjectSettings(): each saved value is written back into the{1}slot of a dropdown / numericBatchOptcell, or straight into a logical / char field, guided by the SHAPE of the current default. Unknown fields, dropdown items no longer offered, and type mismatches are ignored rather than raising - a project saved by an older MIB must still load into a newer dialog.The method only touches
obj.BatchOptandobj.automaticOptions: it never rebuilds the layout or touches measurements, so the caller decides what the new settings mean for the current tiles (seecontrollers.Stitching.loadProjectBtn_Callback()).- Input Arguments:
settings - struct as returned by
utils.stitch.loadProject()(8th output); an empty struct applies nothingskipFields (optional) - [cell] field names to leave untouched. Pass
{'InputPath', 'OutputPath'}for the “settings only” load, where the parameters are reused on a DIFFERENT set of tiles.
- Output Arguments:
appliedFields - [cell] names of the fields actually written
Example - reuse a project’s parameters on the tiles selected right now:
[~, ~, ~, ~, ~, ~, ~, settings] = utils.stitch.loadProject(projectPath); obj.applyProjectSettings(settings, {'InputPath', 'OutputPath'}); obj.buildLayoutFromBatchOpt();
- askImportMode(inputPath)¶
ASKIMPORTMODE - Ask how much of an acquisition’s own stitch to reuse.
- Syntax:
accepted = obj.askImportMode(inputPath)
Called from
controllers.Stitching.selectInputBtn_Callback()when the Position file source is pointed at a file that can carry a finished stitch - a Fibics Atlas.ve-mifor a SerialEM.mdoc- rather than a position text file.Both formats record the same three stages of the same job: a nominal placement, the pairwise seam measurements taken from it, and the final solved positions. Only where they are written differs - Atlas puts each stage in its own sidecar file, SerialEM keeps all three in the one
.mdoc. The choice offered is therefore identical, and only the WORDING is vendor-specific.Both later stages are worth having: MIB can solve from the recorded measurements without re-registering a pixel, or take the finished placement and go straight to fusing. Neither is worth having blindly, though - under difficult imaging conditions the stage positions a vendor works from can be wrong enough that its stitch is bad while the tiles themselves are perfectly stitchable. So the choice is the user’s, and Nominal grid only (register everything from scratch) is always offered.
The answer is written into
BatchOpt.LayoutImport, whichcontrollers.Stitching.buildLayoutFromBatchOpt()reads when it builds the layout. Nothing is asked when the file carries no stitch (there is nothing to choose) or when the tool has no window (batch runs take the BatchOpt value as given).- Input Arguments:
inputPath - [char] full path to the
.ve-mif/.mdocabout to be opened
- Output Arguments:
accepted - [logical]
falseonly when the user cancelled the dialog; the caller should then abandon the whole selection
See also utils.stitch.findAtlasSidecars, utils.stitch.findMdocSidecar, utils.stitch.buildLayoutAtlas, utils.stitch.buildLayoutMdoc
- buildFeatureOptions()¶
BUILDFEATUREOPTIONS - Assemble the options struct for utils.stitch.featureShift from the current detector selection and automaticOptions (used when RegistrationMethod = Feature-based).
rotationInvarianceis DERIVED fromBatchOpt.AllowRotationrather than stored: it is MATLAB’sextractFeaturesUprightflag, so upright descriptors (true) cannot match rotated content at all and would silently veto a rotating solve. The two are therefore one user decision - “are the tiles rotated?” - and the single Allow rotation checkbox owns it. Deriving it here, the one place every consumer (measure, stitch,previewFeatureMatch()) goes through, means the two cannot drift and no stale value can survive a project load.- Syntax:
featureOptions = obj.buildFeatureOptions()
- buildLayoutFromBatchOpt()¶
BUILDLAYOUTFROMBATCHOPT - Build the tile layout from current BatchOpt settings (headless).
- Syntax:
obj.buildLayoutFromBatchOpt()
Builds
obj.layoutfromBatchOpt.LayoutSourceandBatchOpt.InputPathwithout opening any dialogs, so it works both in batch mode and from the GUI after the input path was chosen. Errors when the path is missing or contains no tiles. Downstream state (edges,positions,canvas) is reset.The Position file source covers three file kinds, told apart by extension: MIB’s own
filename X Y [Z]text file, a Fibics Atlas mosaic (MosaicInfo_*.ve-mif), and a SerialEM montage (*.mdoc, or the.mrcit describes). All three answer the same question - where does each tile go - so they share one layout source rather than three dropdown entries.The two vendor formats can bring more than a layout: alongside the acquisition record they may carry the vendor’s own finished stitch, and
BatchOpt.LayoutImportdecides how much of it to take (nothing / the seam measurements / the measurements and the solved placement). Importing here rather than in the GUI callback keeps batch runs and the dialog on one path.
- closeWindow()¶
CLOSEWINDOW - Close the Stitching GUI and clean up listeners.
- Syntax:
obj.closeWindow()
- collectProjectSettings()¶
COLLECTPROJECTSETTINGS - Flatten the tool’s own parameters for the project sidecar.
- Syntax:
settings = obj.collectProjectSettings()
Produces the
settingsblock written byutils.stitch.saveProject()(schema v3): one plain value per persistedBatchOptfield - dropdown and numeric-limit cells are reduced to their{1}entry, since the item lists and spinner limits belong to the controller, not to the saved project - plus the nestedFeatureOptions(the feature-detector tuning behind the Settings… dialog).controllers.Stitching.applyProjectSettings()reverses the flattening on load.Deliberately NOT persisted:
showWaitbarand themibBatch*fields (batch plumbing, not user settings) andid(the active dataset).- Output Arguments:
settings - struct with one field per persisted setting
Example - save the current dialog state with the project:
utils.stitch.saveProject(projectPath, obj.layout, obj.edges, obj.positions, ... struct(), outputInfo, obj.tforms, obj.zSliceFixes, obj.collectProjectSettings());
- configureFeaturesBtn_Callback()¶
CONFIGUREFEATURESBTN_CALLBACK - Open the feature-detector settings dialog.
- Syntax:
obj.configureFeaturesBtn_Callback()
Pops the shared
utils.align.detectorSettingsDlg()(also used bycontrollers.Alignment) to edit the currently selectedFeatureDetectorTypeparameters, the upright-descriptor flag (automaticOptions.rotationInvariance, which holds MATLAB’sUprightvalue - seeutils.align.detectorSettingsDlg()), the detection downsampling factor, and the RANSAC (estgeotform2d) settings. The edited values are stored inobj.automaticOptionsand applied on the next Measure overlaps / Stitch run of the Feature-based method. When the dialog is accepted and a layout is loaded,previewFeatureMatch()renders the resulting keypoint matches on a representative tile pair so the effect of the change is visible immediately (as in the Alignment feature preview).
- currentSeamScoreStamp()¶
CURRENTSEAMSCORESTAMP - What a seam-score pass over the current state would be valid for.
- Syntax:
stamp = obj.currentSeamScoreStamp()
One builder shared by everything that records the stamp, so the fields compared in
controllers.Stitching.seamScoresAreCurrent()and the fields written after scoring cannot drift apart.- Output Arguments:
stamp - [struct]
.positions,.numEdges,.correctionMethod
- defaultFeatureOptions(~)¶
DEFAULTFEATUREOPTIONS - Default feature-detector tuning for the Feature-based registration method. Same shape as controllers.Alignment.defaultAutomaticOptions, tuned for stitching: full-resolution detection (factor 1) and a lower SURF threshold (more blobs in thin overlaps).
- Syntax:
options = obj.defaultFeatureOptions()
- ensureIntensityCorrection()¶
ENSURETILECORRECTION - The intensity correction every tile read is made with.
- Syntax:
correction = obj.ensureIntensityCorrection()
Returns the correction implied by
BatchOpt.IntensityCorrection, estimating it on first use and caching it inobj.intensityCorrection. Every stage that builds a tile reader - overlap estimation, measurement, seam scoring, the seam inspector and both fusers - passes the result through asoptions.correction, which is what makes them all see the SAME pixels. A stage that skipped it would measure or score one set of intensities and fuse another.Why it is lazy. Estimating reads every tile once, which is worth avoiding until something actually needs pixels: opening a dialog, picking an input or flipping the dropdown must stay instant. The cache is dropped by
controllers.Stitching.buildLayoutFromBatchOpt()(new tiles) and bycontrollers.Stitching.updateBatchOptFromGUI()(new method), so it can never describe a job other than the current one.'None'still produces a struct (neutral gains, no field) rather than[]. Distinguishing “estimated, and the answer is no correction” from “not estimated yet” is what stops the estimate being retried on every stage of a run.``’Re-exposure damage’`` also depends on the PLACEMENT, which none of the other methods do closely enough to matter: it corrects a sharp-edged patch where an earlier tile’s footprint fell, so its footprints are only as right as the positions they were placed with. Two consequences:
Before the first solve it is neutral. Nominal positions can be off by many pixels (117 px vertically on the reference pair), and a correction placed there would paint a sharp false edge into the pixels the registration then measures. Measure overlaps and overlap estimation therefore run on uncorrected pixels - phase correlation is insensitive to a flat offset band anyway - and the damage is estimated as soon as solved positions exist, i.e. before the seams are scored and before anything is fused.
A changed placement re-places it. The cached correction records the positions it was placed with; when they no longer match
obj.positionsit is re-estimated with the old one passed asprevious, which for a move of a few pixels (a re-solve, an inspector fix) only re-places the footprints and reads no pixel.
- Output Arguments:
correction - struct per
utils.stitch.estimateIntensityCorrection();[]only when there is no layout to estimate from.
See also utils.stitch.estimateIntensityCorrection, utils.stitch.makeTileReader
- ensureSeamScores(options)¶
ENSURESEAMSCORES - Seam scores for the CURRENT placement, computed at most once.
- Syntax:
cancelled = obj.ensureSeamScores() cancelled = obj.ensureSeamScores(options)
Fills
obj.edges(k).seamScore/.dzHintwithutils.stitch.scoreSeams(), and returns immediately when they already describe the current state. Same lazy-cache shape ascontrollers.Stitching.ensureIntensityCorrection(), and for the same reason: scoring re-reads every overlap from disk, which on a large mosaic is the slowest thing the tool does short of fusing.What it stops. Two stages score the seams as part of their own job -
optimizePositions_Callback()after a solve andbuildLayoutFromBatchOpt()after importing a vendor placement - and the seam inspector scores them again on the way in (controllers.StitchingInspector.scoreAndRank()). Importing an Atlas or SerialEM stitch and then pressing Inspect and fix… therefore read every overlap twice, as did every inspector re-solve (controllers.StitchingInspector.resolveBtn_Callback()callsoptimizePositions_Callbackand thenscoreAndRank). The ranking itself is free to recompute -utils.stitch.rankSeams()touches no pixels.What counts as “still current” (
obj.seamScoresStamp):the solved
positionsare unchanged - the scores ARE a function of the placement, since the strips are cut at the solved origins;the edge count is unchanged - a re-measure produces a different set;
BatchOpt.IntensityCorrectionis unchanged - the scores are correlations of CORRECTED pixels, so changing the method changes them;and every edge actually carries a score, so a partially-scored set (a cancelled pass, or a project saved before scoring existed) is redone.
Deliberately NOT invalidated by an edge edit that leaves the positions alone: excluding a seam, or a manual fix awaiting its re-solve, cannot change any seam’s pixels. The re-solve that follows moves the positions, and that is what triggers the rescore.
- Input Arguments:
options (optional) - struct with fields:
.parentFigure- [handle] progress-dialog parent (default:guiFigure(); the inspector passes its own window).readerFcn- [function_handle] reuse an existing tile reader (optional)
- Output Arguments:
cancelled - [logical]
truewhen the user cancelled the Scoring seams… dialog; the scores are then cleared, the stamp is NOT set, and the next request scores again.falsewhen scoring ran or was skipped.
See also utils.stitch.scoreSeams, utils.stitch.rankSeams, controllers.Stitching.ensureIntensityCorrection
- guiFigure()¶
GUIFIGURE - Handle of the tool window, or
[]without a view.- Syntax:
figureHandle = obj.guiFigure()
Every dialog parent and progress-bar anchor goes through this so the workflow methods run unchanged whether the tool has a window (GUI), was launched from a batch protocol, or is driven headlessly by the test suite.
utils.dlgs.*and theutils.stitchprogress helpers all accept[]as “no parent”.- Output Arguments:
figureHandle - [handle] the
StitchingGUIfigure, or[]when the controller has no (valid) view
- helpBtn_Callback()¶
HELPBTN_CALLBACK - Open the online help page for the Stitching tool.
- Syntax:
obj.helpBtn_Callback()
- static imageFileFormat(label)¶
IMAGEFILEFORMAT - Look one
imageFileFormats()row up by label.- Syntax:
entry = controllers.Stitching.imageFileFormat(label)- Input Arguments:
label - [char] a
BatchOpt.OutputFormatvalue
- Output Arguments:
entry - [struct] the matching row; the FIRST row when the label is unknown, so a project or batch protocol written by a newer MIB still exports rather than erroring
- static imageFileFormats()¶
IMAGEFILEFORMATS - The image file formats
OutputMode = Image filesoffers.- Syntax:
formats = controllers.Stitching.imageFileFormats()
One table shared by the file picker (
controllers.Stitching.selectOutputPath_Callback()), theBatchOpt.OutputFormatitem list and the fuse (controllers.Stitching.stitchBtn_Callback()), so a label offered in the dialog cannot name a saver the fuse does not call.labelis what the user picks and whatBatchOpt.OutputFormatrecords;saverFormat+policyare whatutils.stitch.fuseToFiles()passes on toio.SaverFactory. The two are not the same string because a TIF format name says nothing about 2-D versus 3-D - MIB’s own Save-as asks that separately, throughSaving3DPolicy- and this dialog raises no follow-up questions, so the choice has to be in the label.- Output Arguments:
formats - [1xN struct] with fields
.label,.extension,.saverFormat,.policy
- inspectSeams_Callback()¶
INSPECTSEAMS_CALLBACK - Open (or focus) the seam inspector.
- Syntax:
obj.inspectSeams_Callback()
Launches
controllers.StitchingInspectoron the current edges/positions for worst-first manual QC (seedevelopment/stitching/plan_inspector.md). The inspector mutates this controller’s edge/position state in place; itsSeamsUpdatedevent refreshes this window’s widgets so both stay in sync.
- loadProjectBtn_Callback()¶
LOADPROJECTBTN_CALLBACK - Load a stitching project from a JSON sidecar file.
- Syntax:
obj.loadProjectBtn_Callback()
A project file carries two independent things: the STATE of one particular stitch (tiles, seam measurements, solved positions) and the SETTINGS it was produced with (layout source, grid, overlap, registration, output - schema v3 and newer). Both are useful on their own, so the user is asked which to take:
Restore everything -
obj.layout/obj.edges/obj.positions/obj.tforms/obj.zSliceFixescome back from the file and every widget is reset to the saved settings, reproducing the dialog as it was.Settings only - the saved parameters are applied to the tiles selected HERE (
InputPath/OutputPatihare kept), the layout is rebuilt from them, and the file’s tiles/measurements/positions are ignored. This is the “stitch a new acquisition exactly like the previous one” case.
Files written before the settings block existed have nothing to choose from, so they load their state directly without a dialog.
- measureOverlaps_Callback()¶
MEASUREOVERLAPS_CALLBACK - Measure pairwise shifts for all neighbour tile pairs.
- Syntax:
obj.measureOverlaps_Callback()
Calls
utils.stitch.findNeighborPairsto identify all overlapping tile pairs, then callsutils.stitch.measureAllPairsto compute phase- correlation shifts and quality scores for each pair. Results are cached inobj.edges, the status label is updated and the layout preview is redrawn (previewLayoutBtn_Callback()).The progress dialog shown during measurement is cancelable: pressing Cancel leaves
obj.edgesand the status line untouched, as if this call had never been made.
- onInspectorClosed()¶
ONINSPECTORCLOSED - Release the seam-inspector handle and its listeners.
- Syntax:
obj.onInspectorClosed()
- optimizePositions_Callback()¶
OPTIMIZEPOSITIONS_CALLBACK - Run global least-squares solve and plan the output canvas.
- Syntax:
obj.optimizePositions_Callback()
Calls
utils.stitch.solveGlobalLeastSquaresto determine optimal tile positions from the measured edge set, then callsutils.stitch.planCanvasto compute the output canvas size and integer tile placements. Results are cached inobj.positionsandobj.canvas.RMSE and residual statistics are displayed in the status label.
- previewFeatureMatch()¶
PREVIEWFEATUREMATCH - Visualise feature matches on a representative tile pair.
- Syntax:
obj.previewFeatureMatch()
Feature-based tuning aid, mirroring
controllers.Alignment.previewFeaturesBtn_Callback(). Picks the first overlapping tile pair from the currentobj.layout, reads both FULL tiles (feature matching uses whole tiles, not the thin nominal overlap strip), detects + matches keypoints with the selectedFeatureDetectorTypeand the parameters inobj.automaticOptions, robust-fits a translation (estgeotform2dRANSAC), and renders the two tiles stitched at the recovered offset (imfusefalse-colour: tile i green, tile j magenta, grey where they agree) with the inlier keypoints marked on top. A clean seam and tightly overlapping green/magenta keypoints mean a good registration; the recovered shift and inlier ratio are shown in the title, so the effect of a settings change is visible immediately - the feedback loop the Alignment preview provides.A
downsampleFactorabove 1 affects DETECTION ONLY: keypoints are found on resized copies and their locations scaled back, while the composite is always BUILT from the full-resolution tiles (the title notes the detection scale). For real-world tile sizes that composite can exceed a GPU’s max texture side (commonly ~16384 px) - MATLAB then creates the image object without error, but the driver silently fails to rasterize it while the point/tie-line overlay still renders, i.e. only markers show, no image. To avoid this, the composite is downsized for DISPLAY ONLY past a safe cap (title notes the display scale too); detection/matching/the fitted shift are unaffected.No stitching is applied. Requires a layout with at least one overlapping pair (select input tiles first); shows an informational dialog otherwise.
Shows a Cancelable progress dialog spanning tile reading, feature detection/matching, transform fitting, AND composite building + the display-downsize step above - reading/warping/fusing full-resolution tiles off disk can take a noticeable time for large files, and without it the app would look frozen. Cancel is polled between stages (read A, read B, detect, match, fit, build composite, resize for display); since each stage itself is one blocking call, a click takes effect at the next stage boundary, not mid-call. Cancelling closes the dialog and returns without opening the preview figure.
- previewLayoutBtn_Callback()¶
PREVIEWLAYOUTBTN_CALLBACK - Draw nominal tile positions on the preview axes.
- Syntax:
obj.previewLayoutBtn_Callback()
Renders a top-down view of tile nominal positions on the
previewAxeswidget, colour-coded and labelled with the tile index. The axes are scaled to the full canvas extent.- Two modes, selected by the
editLayoutCheckboxstate: display (default) - static
patchrectangles (fast, read-only). Drawn at the SOLVED positions whenever a solve exists (kept current byoptimizePositions_Callbackand hence by every inspector re-solve); nominal positions otherwise - the title states which.edit - one draggable
images.roi.Rectangleper tile (translate-only, fixed size); dragging a tile writes its new position intolayout(i).nomOriginand invalidates the measured edges / solved positions so the next Measure/Optimize run uses the corrected layout. This is the interactive rough-placement workflow (Phase 3).
For multi-layer (3D) layouts only the FIRST Z-layer is drawn/edited: every layer shares the same XY grid, so drawing them all would stack rectangles.
- static projectSettingFields()¶
PROJECTSETTINGFIELDS - BatchOpt fields persisted in the project sidecar.
- Syntax:
fieldNames = controllers.Stitching.projectSettingFields()
The single list shared by
controllers.Stitching.collectProjectSettings()(save) andcontrollers.Stitching.applyProjectSettings()(load), so the two can never drift apart. ExcludesshowWaitbar/mibBatch*/id- batch plumbing rather than user settings.- Output Arguments:
fieldNames - [cell] BatchOpt field names, in dialog order
- refreshInputPathWidget()¶
REFRESHINPUTPATHWIDGET - Show BatchOpt.InputPath in the InputPath widget, handling either a uieditfield (single newline-joined string) or a uilistbox (one item per path - better for multi-folder input). BatchOpt.InputPath stays the newline-joined string in both cases, so batch mode is unaffected.
- Syntax:
obj.refreshInputPathWidget()
- refreshQualityChip()¶
REFRESHQUALITYCHIP - Render the alignment-quality chip from the cached state.
- Syntax:
obj.refreshQualityChip()
Colour-coded alignment quality (
rmseLabel), translating the raw solver RMSE - in pixels, the mean disagreement between the pairwise measurements at the solved positions - into a plain-language rating on a green→red scale that a non-specialist can read at a glance, DOWNGRADED whenever the pixel seam check disagrees with the residual. The exact numbers stay in the text and the tooltip for those who want them.Reads
obj.solverInfo(cached bycontrollers.Stitching.optimizePositions_Callback(), restored bycontrollers.Stitching.loadProjectBtn_Callback()) and the seam scores currently onobj.edges. Nothing here re-reads pixels or re-solves, so it is cheap enough to run fromupdateWidgets- which is what keeps the chip honest when the seam inspector excludes or re-includes an edge: the worst score is a minimum over the VALID edges, so that set changing changes the verdict even though no position moved.While a global re-solve is owed (
obj.resolvePending- a fix made with Auto re-solve off), the cached RMSE no longer describes the current edge set, so the chip says so instead of quoting a stale number. The flag lives on the CONTROLLER, not on the inspector, so the warning survives the inspector being closed - which is exactly when a stale rating would otherwise go unmentioned.
- static renameLegacyFields(settings)¶
RENAMELEGACYFIELDS - Map retired BatchOpt field names onto current ones.
- Syntax:
settings = controllers.Stitching.renameLegacyFields(settings)
Applied to anything arriving from OUTSIDE this class - a batch protocol or a project sidecar - before it is merged into
BatchOpt, so both entry points age the same way.AtlasImportbecameLayoutImportwhen SerialEM montages joined Fibics Atlas in offering their own stitch for import: the three modes were never Atlas-specific, and the old name made a SerialEM protocol read as an Atlas one. The values were renamed with it ('Atlas seams…'→'Vendor seams…').A file carrying BOTH names keeps the current one - an old key alongside a new one means the writer knew about the new name.
- Input Arguments:
settings - [struct] BatchOpt-shaped struct, possibly using retired field names
- Output Arguments:
settings - [struct] same struct with retired names replaced
- reportError(errorInfo, dlgTitle)¶
REPORTERROR - Surface a caught error from a workflow step.
- Syntax:
obj.reportError(errorInfo, dlgTitle)
With a window: an error dialog, and the caller returns. Without one the error is rethrown, so a batch protocol or a test sees the failure instead of a silently skipped step.
- Input Arguments:
errorInfo - [MException] the caught error
dlgTitle - [char] dialog title
- returnBatchOpt(BatchOptOut)¶
RETURNBATCHOPT - Send BatchOpt to mibBatchController.
- Syntax:
obj.returnBatchOpt() obj.returnBatchOpt(BatchOptOut)- Input Arguments:
BatchOptOut (optional) - [struct] BatchOpt to send; defaults to
obj.BatchOpt
- runOverlapEstimation()¶
RUNOVERLAPESTIMATION - Estimate the true grid overlap and rebuild the nominal layout.
- Syntax:
cancelled = obj.runOverlapEstimation()
Grid-style layout sources only (Grid, Filename pattern - both carry
.gridRC). Callsutils.stitch.estimateOverlap()(full-tile phase correlation with peak verification, median over the grid), writes the recovered percentages intoBatchOpt.OverlapX/OverlapYand rebuilds the layout so the subsequent tight measurement pass starts from honest nominal positions. Directions that could not be estimated keep the user’s value.Does nothing for a layout restored from a project file: the rebuild would re-derive it from
BatchOpt, which still describes whatever job was set up before the load (a project carries no layout source or grid before schema v3), silently replacing the project’s tiles. Its nominal origins come from the file and need no overlap guess.Shows a Cancelable progress dialog while the sampled tile pairs are read and registered - reading full-resolution tiles can take a noticeable time for large files. Returns
cancelled = true(and leaves BatchOpt untouched) if the user cancels before the estimate finished; callers must check this and stop rather than continue to Measure overlaps with an un-estimated guess.- Output Arguments:
cancelled - [logical]
truewhen the user cancelled the estimate.
- saveProjectBtn_Callback()¶
SAVEPROJECTBTN_CALLBACK - Save the current stitching project to a JSON file.
- Syntax:
obj.saveProjectBtn_Callback()
- seamScoresAreCurrent()¶
SEAMSCORESARECURRENT - True when obj.edges’ seam scores still describe the current placement, edge set and intensity correction.
- Syntax:
tf = obj.seamScoresAreCurrent()
The stamp is COMPARED against live state rather than cleared by whoever changes that state: a rescore that should have happened and did not is a mosaic rated on the wrong pixels, and there is no single place every position change goes through. Every edge must also actually carry a score - a cancelled pass or a pre-scoring project leaves some empty, and a partial set is not a set.
- selectInputBtn_Callback()¶
SELECTINPUTBTN_CALLBACK - Open a file/folder picker and build the tile layout.
- Syntax:
obj.selectInputBtn_Callback()
Behaviour depends on
BatchOpt.LayoutSourceandBatchOpt.SubfolderMode(SubfolderMode = each tile is a FOLDER Z-stack rather than a single file):Bio-Formats metadata - multi-select file picker; one multi-series file (series = tiles) or several single-tile files carrying stage coordinates.
Position file - file picker for any kind of file that states where the tiles go: MIB’s position text file (whose filename column may point at images or, with SubfolderMode, at folders), a Fibics Atlas mosaic (
MosaicInfo_*.ve-mif), or a SerialEM montage (*.mdoc). Each format offers only the ONE file that states where the tiles go: Atlas’s.ve-tie/.ve-updatesare detected from the.ve-mif, and a SerialEM.mrcis reached from its.mdoc- a bare stack has no placement in it and is refused with an explanation. When the acquisition already stitched the mosaic the user is asked how much of that stitch to reuse before the layout is built.Grid / Filename pattern, SubfolderMode OFF - multi-select file picker; the selected image files are the tiles (stored newline-joined in InputPath; the layout builder natural-sorts them, so selection order does not matter). A plain folder path typed/pasted into InputPath still works - its image files become the tiles (batch back-compat).
Grid / Filename pattern, SubfolderMode ON - multi-select the tile folders (each a Z-stack); stored newline-joined in InputPath.
After building the layout,
obj.layoutis populated andupdateWidgetsis called to refresh the status display.
- selectOutputPath_Callback()¶
SELECTOUTPUTPATH_CALLBACK - Open a file picker to choose the output path.
- Syntax:
obj.selectOutputPath_Callback()- What is offered depends on
BatchOpt.OutputMode: OME-Zarr3 (BigData) - a single
.zarr3store.Image files - the formats from
controllers.Stitching.imageFileFormats(), whose picked filter is recorded inBatchOpt.OutputFormat. This dialog is the ONLY place the image format is chosen, which is why it also has to survive the cancel path unchanged.
In memorynever reaches here - the button is disabled for it.
- stitchBtn_Callback(batchModeSwitch)¶
STITCHBTN_CALLBACK - Fuse all tiles into the output dataset.
- Syntax:
obj.stitchBtn_Callback() obj.stitchBtn_Callback(batchModeSwitch)- Input Arguments:
batchModeSwitch (optional) - [logical]
truewhen called headlessly (suppresses interactive dialogs); defaultfalse
- Fusion path depends on
BatchOpt.OutputMode: In memory - calls
utils.stitch.fuseInMemorythen creates a newcore.MibDatasetand notifies'NewDataset'.OME-Zarr3 (BigData) - asks for the pyramid/chunk/compression settings (
io.savers.Zarr3Saver.optionsDialog, the same dialog as the standard “Export to Zarr3” action), callsutils.stitch.fuseStreamingto write chunk-wise to an OME-Zarr file, then reopens it viaio.loaders.Zarr3VirtualSetupLoaderand notifies'NewDataset'.Image files - calls
utils.stitch.fuseToFilesto write the mosaic as ordinary TIF/PNG/Amira files in the formatBatchOpt.OutputFormatnames. The result is NOT opened: a 2-D sequence is potentially hundreds of files, and re-reading what was just fused would cost as much as the stitch.
The project JSON sidecar is saved if
BatchOpt.SaveProjectis true.This is the ONLY fuse entry point - the seam inspector has no button of its own, so a fix made there is baked in by pressing Stitch here (both windows stay usable side by side). When the inspector still owes a global re-solve (auto-re-solve off, or a deferred nudge), that re-solve runs FIRST: the guard lives on the operation, not on one button, so the mosaic can never be fused from stale positions.
- stitchedFilename()¶
STITCHEDFILENAME - Name for the dataset a stitch produces.
- Syntax:
filename = obj.stitchedFilename()
<source>_stitch.tif, next to whatever the mosaic was built from: the position file for a Position-file layout, otherwise the first tile. A stitched mosaic has no file of its own until it is saved, and a dataset with no filename makesSave asopen on MATLAB’s working folder - somewhere unrelated to the data. Pointing it at the source folder puts the suggested name where the tiles are, which is where the result belongs.The extension is always
.tifregardless of what the tiles were: it names a single assembled 2-D/3-D image, which is not the same kind of thing as an MRC montage container or a.ve-mifmosaic record, and offering to save a mosaic back as its vendor’s acquisition format would be wrong.- Output Arguments:
filename - [char] full path, e.g. a montage picked as
C:\data\Cell1.mrc.mdocbecomesC:\data\Cell1_stitch.tif.
See also controllers.Stitching.stitchBtn_Callback
- updateBatchOptFromGUI(hObject)¶
UPDATEBATCHOPTFROMGUI - Sync obj.BatchOpt from a changed widget.
- Syntax:
obj.updateBatchOptFromGUI(hObject)- Input Arguments:
hObject - handle to the AppDesigner widget that changed
- updateInfoLabel()¶
UPDATEINFOLABEL - Set the info label to a short description of what the current
LayoutSourcedoes, so the user knows what input to provide. Guarded byisfield- no-op until theinfoLabelwidget exists in the mlapp.- Syntax:
obj.updateInfoLabel()
- updateWidgets()¶
UPDATEWIDGETS - Refresh all GUI widgets from current BatchOpt state.
- Syntax:
obj.updateWidgets()
No-op without a view (batch protocols and headless runs hold the same state in
BatchOpt- there is simply nothing to render it into).