Standalone utility functions

utils.addText2Img(img, textArray, positionList, options)

ADDTEXT2IMG - Add text labels to a 2D image using Computer Vision Toolbox functions.

Syntax:

img = addText2Img(img, textArray, positionList, options)

Requires insertText and insertMarker from the Computer Vision Toolbox. Falls back to a legacy implementation when those are unavailable.

Input Arguments:
  • img - [numeric] 2D image to annotate

  • textArray - [cell] labels to render, e.g. {'label1'; 'label2'}

  • positionList - [numeric] label positions [pointNo; x, y]

  • options (optional) - struct with rendering settings:

    • .color - [numeric] text colour as an RGB vector or scalar grey value (default: 0.5)

    • .fontSize - [numeric] font size index 1-7, mapping to pt 8-20 of Ubuntu Mono (default: 2)

    • .markerText - [char] marker+text visibility: 'Label + Value' (default), 'Label' (only label, no value), or 'Value' (only value, no label)

    • .markerShow - [logical] true - (default) show marker; false - do not show marker

    • .AnchorPoint - [char] text-box reference point: 'LeftTop' (default), 'LeftCenter', 'LeftBottom', 'CenterTop', 'Center', 'CenterBottom', 'RightTop', 'RightCenter', 'RightBottom'

Output Arguments:
  • img - [numeric] annotated 2D image

Note

To print special characters, generate them with char(dec_index). For example, replace \mu with the proper symbol:

textArray = strrep(textArray, '\mu', char(956));

See https://unicode-table.com/en/ for character codes.

Usage:

Example 1 - add two coloured labels at specified positions

textArray{1} = 'label1';
textArray{2} = 'label2';
positionList(1,:) = [50, 75];
positionList(2,:) = [150, 175];
options.color = [1 0 0];
options.fontSize = 3;
selection(:,:,5) = utils.addText2Img(selection(:,:,5), textArray, positionList, options);
utils.applyThemeColors(hFig)

APPLYTHEMECOLORS - adapt the standard dialog button colors to the figure theme.

Syntax:
utils.applyThemeColors(hFig)

Most MIB dialogs paint their main action button green and their Close/Cancel button orange in App Designer, with the font color on auto. Under the dark theme the auto font turns near-white and becomes unreadable on these light colors.

The function finds every uibutton and uistatebutton of hFig whose background is one of the standard dialog colors of either theme (dialogAction, dialogClose, dialogSecondary or dialogStop of utils.themeColors) and repaints it with that color of the theme the figure currently uses. The same is done for the background of every uitab and uipanel painted tabHighlight, of every uidropdown, uieditfield, numeric uieditfield and uispinner painted fieldError, fieldYellow or fieldBlue, and for the color-coded parts of a window: uitab, uipanel, uigridlayout, uilabel and buttons painted one of the panel... tints (panelYellow, panelBlue, panelGreen, panelRed, panelMint, panelSky), buttons and input fields painted one of the widget... tints. Grid layouts are included because a grid that fills a tab hides the tab’s own background, so the grid carries the visible color. A button whose background was set explicitly to the theme default (background of either theme, typically copied from another widget with btn.BackgroundColor = panel.BackgroundColor) is switched back to BackgroundColorMode = 'auto', because the copied value no longer follows the theme. Finally, the title of every uitab whose ForegroundColor was set explicitly to the text color of either theme (App Designer writes the light default [0.129 0.129 0.129] when the title color is touched, which is invisible in the dark theme). Matching both themes makes the call idempotent and reversible, so it is also the handler for a theme switch. Widgets with any other background are left untouched; the match uses a tolerance of 1e-3 because App Designer stores the colors rounded to 4 decimals.

Explicitly assigned colors are not remapped by MATLAB on a theme switch, so the function installs itself as hFig.ThemeChangedFcn, unless the figure already has a different handler (which is then left in place and has to call this function itself). On releases without the figure Theme property (before R2025a) the buttons already carry the light colors and nothing is changed.

Input Arguments:
  • hFig - [matlab.ui.Figure] handle of the dialog figure, e.g. obj.view.gui

Usage:
obj.view = core.ChildView(obj, 'views.StitchingGUI');
utils.applyThemeColors(obj.view.gui);

See also

utils.themeColors

utils.attachFileDnD(webwin, parentFigure, callback)

ATTACHFILEDND - Attach OS-level file drag-and-drop to a MATLAB webwindow.

Syntax:

bridgeButton = attachFileDnD(webwin, parentFigure, callback)

Wraps MATLAB’s native FileDragDropCallback in a JS bridge so that:

  • file opening is deferred until the actual DOM drop (mouse release), not the native drag-enter event

  • Chromium’s default navigate / Save-As / red-no-parking-cursor behaviours are all suppressed

  • browser-renderable file types (JPEG, PNG, …) cannot trigger Chromium’s native JPEG decoder, which has a heap-corruption bug in some MATLAB releases when a dropped file is decoded concurrently with MATLAB’s own imread; webwin.allowNavigation(false/true) brackets each drag operation to block the CEF-level navigation before it starts

Input Arguments:
  • webwin - handle to matlab.internal.webwindow (AppContainer) or matlab.internal.cef.webwindow (standalone mlapp) hosting the app

  • parentFigure - a uifigure rendered inside webwin’s Chromium document (the hidden bridge uibutton becomes its child)

  • callback - function handle invoked on drop as callback(params) where params = {webwin, filenames} - the same shape the native FileDragDropCallback produces. Wrap method calls in an explicit anonymous function, e.g. @(params) obj.myController.dragNdrop_Callback(params)

Output Arguments:
  • bridgeButton - handle to the hidden uibutton; deleting it detaches the MATLAB side of the bridge (the JS handlers remain until the webwindow is reloaded, but they become no-ops)

Usage:

Example 1 - attach drag-and-drop to the selection panel

obj.controller.dndBridgeButton = utils.attachFileDnD( ...
    obj.controller.mibWebWindow, ...
    obj.handles.panels.selectionPanel.Figure, ...
    @(params) obj.controller.dragNdrop_Callback(params));

See development/guides/drag-and-drop.md for a full explanation of the pattern.

utils.calcCurveLength(slice, pixSize, CC)

CALCCURVELENGTH - Calculate length of the curve objects in a 2D slice.

Syntax:

STATS = calcCurveLength(slice)
STATS = calcCurveLength(slice, pixSize)
STATS = calcCurveLength(slice, pixSize, CC)

Both closed and non-closed curves can be measured. The curves are expected to be 1 pixel wide, i.e. the objects should be thinned (bwmorph(img, 'thin', Inf)) before the call; a non-closed curve with more than two end points is rejected.

Each object is traced with bwtraceboundary from one of its end points, the resulting point list is smoothed with a 3-point window (utils.align.windv) and the length is taken as the sum of distances between the consecutive points.

Input Arguments:
  • slice - one of:

    • [numeric|logical] 2D slice [1:height, 1:width] with the drawn curves

    • [struct] connected components structure returned by bwconncomp; in this case it is used instead of CC

  • pixSize (optional) - struct with physical pixel sizes; required fields .x and .y. When omitted or not a struct, the length is returned in pixels and placed into the CurveLengthInPixels field instead of CurveLengthInUnits.

  • CC (optional) - [struct] connected components structure returned by bwconncomp. When omitted it is calculated from slice using 8-connectivity.

Output Arguments:
  • STATS - [1 x NumObjects] struct array with fields:

    • .Centroid - object centroid, [x, y]

    • .PixelIdxList - linear indices of the object pixels

    • .CurveLengthInUnits - curve length in physical units; present when pixSize was provided

    • .CurveLengthInPixels - curve length in pixels; present when pixSize was omitted

    NaN is returned when one of the objects has more than two end points.

Usage:

Example 1 - length of the curves in pixels

STATS = utils.calcCurveLength(bwmorph(slice, 'thin', Inf));

Example 2 - length of the curves in physical units

pixSize = obj.mibModel.I{obj.mibModel.Id}.pixSize;
STATS = utils.calcCurveLength(slice, pixSize);

See also

utils.align.windv

utils.calculatePixSizes(resolution, unitFrom, unitTo)

CALCULATEPIXSIZES - Recalculate pixel size (width, height) of the dataset to new units.

Syntax:

pixSize = calculatePixSizes(resolution, unitFrom, unitTo)
Input Arguments:
  • resolution - [numeric] current resolution of the dataset [XResolution, YResolution]

  • unitFrom - [char] source units: 'Inch', 'Centimeter', 'Meter'

  • unitTo - [char] desired units: 'm', 'cm', 'mm', 'um', 'nm'

Output Arguments:
  • pixSize - struct with updated pixel sizes:

    • .x - physical width of the pixel

    • .y - physical height of the pixel

Usage:

Example 1 - convert 72 dpi resolution to micrometres

pixSize = utils.calculatePixSizes([72, 72], 'Inch', 'um');
utils.calculateResolution(pixSize)

CALCULATERESOLUTION - Calculate image resolution in Pixels/Inch for saving TIFF files.

Syntax:

resolution = calculateResolution(pixSize)
Input Arguments:
  • pixSize - struct with physical voxel dimensions:

    • .x - physical width of the pixel

    • .y - physical height of the pixel

    • .units - physical unit string: 'm', 'cm', 'mm', 'um', 'nm'

Output Arguments:
  • resolution - [numeric] [XResolution, YResolution] in Pixels/Inch

Usage:

Example 1 - compute resolution for TIFF saving

pixSize.x = 0.065; pixSize.y = 0.065; pixSize.units = 'um';
resolution = utils.calculateResolution(pixSize);
utils.childWindowKeyPressFcn(controller, hWidget, hData)

CHILDWINDOWKEYPRESSFCN - Shared keyboard shortcut handler for child dialog controllers.

Syntax:

childWindowKeyPressFcn(controller, hWidget, hData)

Provides a safe subset of MIB keyboard shortcuts that work correctly in child dialog windows (Quantification, Annotations, etc.) without requiring a handle to MibController. Reads the user’s KeyShortcuts preferences so custom bindings are respected.

Currently supported actions:
  • Undo/Redo last action - calls mibModel.undo() + fires ShowImage

Additionally handles Escape independently of KeyShortcuts:
  • Escape - calls controller.closeWindow() if the method exists

Input Arguments:
  • controller - handle to the child controller; must have a .mibModel property

  • hWidget - the UIFigure that fired the event (passed by WindowKeyPressFcn)

  • hData - KeyData event object with .Key and .Modifier fields

Usage:

Example 1 - wire in a child controller’s addCallbacks

obj.view.gui.WindowKeyPressFcn = @(h,d) utils.childWindowKeyPressFcn(obj, h, d);
utils.concatenateDictionaries(primaryDict, secondaryDict)

CONCATENATEDICTIONARIES - Update keys of primaryDict using the keys of secondaryDict.

Syntax:

primaryDict = concatenateDictionaries(primaryDict, secondaryDict)
Input Arguments:
  • primaryDict - primary dictionary that should be updated

  • secondaryDict - secondary dictionary that should be concatenated into the primary dictionary

Output Arguments:
  • primaryDict - updated primary dictionary

Usage:

Example 1 - update preferences dictionary from a saved session

obj.mibModel.preferences = utils.concatenateDictionaries(obj.mibModel.preferences, mib_pars.preferences);
utils.concatenateStructures(primaryStruct, secondaryStruct, knownFieldsOnly)

CONCATENATESTRUCTURES - Update fields of primaryStruct using the fields of secondaryStruct.

Syntax:

primaryStruct = concatenateStructures(primaryStruct, secondaryStruct)
primaryStruct = concatenateStructures(primaryStruct, secondaryStruct, knownFieldsOnly)
Input Arguments:
  • primaryStruct - primary structure that should be updated

  • secondaryStruct - secondary structure that should be concatenated into the primary structure

  • knownFieldsOnly - [optional, default false] logical; when false a field of secondaryStruct that primaryStruct does not have is added to the result. When true such a field is dropped instead, at every nesting level, so the result keeps exactly the shape of primaryStruct and only its values are updated. Used when restoring preferences saved by a newer MIB into an older one: the older version must not inherit settings whose meaning it does not implement, see models.MibModel.initializePreferences()

Output Arguments:
  • primaryStruct - updated primary structure

Usage:

Example 1 - update preferences structure from a saved session

obj.mibModel.preferences = utils.concatenateStructures(obj.mibModel.preferences, mib_pars.preferences);

Example 2 - take only the settings this version knows about

obj.preferences = utils.concatenateStructures(obj.preferences, mib_pars.preferences, true);
utils.connectPoints(img, pnts, options)

CONNECTPOINTS - Generate a bitmap image with lines that connect a sequence of points.

Syntax:

img = connectPoints(img, pnts)
img = connectPoints(img, pnts, options)
Input Arguments:
  • img - [uint8] image where the lines should be drawn

  • pnts - [numeric] matrix with point coordinates [pointNo, [x, y]]

  • options (optional) - struct with extra parameters:

    • .close - [logical] when 1 the shape will be closed (default: 0)

    • .fill - [logical] when 1 fill the enclosed shape (default: 0)

Output Arguments:
  • img - [uint8] bitmap image with drawn lines

Usage:

Example 1 - draw open polyline

img = utils.connectPoints(img, pnts);

Example 2 - draw closed filled polygon

opts.close = 1;
opts.fill  = 1;
img = utils.connectPoints(img, pnts, opts);
utils.ensureJavaLibraries(libList, mibPath, externalDirs)

ENSUREJAVALIBRARIES - Initialize external Java libraries on their first use.

Syntax:
utils.ensureJavaLibraries(libList)
utils.ensureJavaLibraries(libList, mibPath, externalDirs)

Adds the requested Java libraries to the dynamic Java class path. Each library is initialized only once per MATLAB session (kept in a persistent registry), so the function is cheap to call from any code path that is about to use a Java-dependent feature. Keeping the javaaddpath calls out of the MIB startup makes the startup faster and avoids the global variable clearing side effect of javaaddpath until a library is actually needed.

When MATLAB runs without a Java runtime (utils.JavaSetup.isAvailable is false, the default from MATLAB R2026b, which no longer bundles Java; also when the jenv setting points to an uninstalled Java), only the non-Java 'bm3d' entry is processed and 'imageselection' is skipped silently (it is requested at startup, and imclipboard falls back to the .NET clipboard on Windows). Any other requested library throws MIB:javaNotFound with a message that names the feature (Bio-Formats, Fiji, …) and points to Preferences -> External directories -> Java (utils.JavaSetup), which works both in MATLAB and in the compiled standalone, followed by a restart. Callers that catch errors should show err.message rather than a generic text, so the reason reaches the user.

mibPath and externalDirs are cached in persistent variables on the first configured call (done from MibController.initializeLibraries during startup), so later calls may provide only libList.

Input Arguments:
  • libList - cell array of library identifiers to initialize. Valid identifiers: 'bm3d', 'omero', 'mij.jar', 'bioformats', 'imageselection', 'fiji', 'poi', 'imaris'

  • mibPath - (optional) char, MIB installation directory; cached persistently; when never provided, resolved via utils.getInstallationPath

  • externalDirs - (optional) struct, copy of preferences.ExternalDirs with the Fiji/OMERO/Imaris/BM3D installation paths; cached persistently; libraries that require it are skipped when it was never provided

Output Arguments:

(none)

Example 1 - make sure Bio-Formats is available before reading a file:

utils.ensureJavaLibraries({'bioformats'});
reader = bfGetReader(filename);
utils.fontSizeUpdate(hFig, Font)

FONTSIZEUPDATE - Update font size and family for all text widgets in a figure.

Syntax:

fontSizeUpdate(hFig, Font)
Input Arguments:
  • hFig - handle to the figure whose widgets should be updated

  • Font - struct with font settings:

    • .FontName - [char] font name (e.g. 'Arial')

    • .FontWeight - [char] 'normal' or 'bold'

    • .FontAngle - [char] 'normal' or 'italic'

    • .FontUnits - [char] units string (e.g. 'points')

    • .FontSize - [numeric] font size in the given units

Usage:

Example 1 - update font from a child controller when font preferences change

if obj.view.handles.UserInterfacePanel.FontSize ~= Font.FontSize ...
       || ~strcmp(obj.view.handles.UserInterfacePanel.FontName, Font.FontName)
    utils.fontSizeUpdate(obj.view.gui, obj.mibModel.preferences.System.Font);
end
utils.generateSequentialFilename(name, num, files_no, ext)

GENERATESEQUENTIALFILENAME - Build a zero-padded sequential filename.

Syntax:

fn = generateSequentialFilename(name, num, files_no, ext)

Returns a filename string where num is zero-padded to as many digits as needed to represent the total file count files_no.

Input Arguments:
  • name - [char] base filename string, e.g. 'image'

  • num - [numeric] current file index (1-based), e.g. 5

  • files_no - [numeric] total number of files in the sequence, e.g. 200

  • ext - [char] file extension string including dot, e.g. '.tif'

Output Arguments:
  • fn - [char] filename string, e.g. 'image_005.tif'

Note

When files_no == 1, no index suffix is added. Minimum zero-padding is 2 digits; padding width scales automatically with files_no.

Usage:

Example 1 - generate filenames for a 500-image sequence

for k = 1:500
    fn = utils.generateSequentialFilename('image', k, 500, '.tif');
    % k=1   -> 'image_001.tif'
    % k=42  -> 'image_042.tif'
    % k=500 -> 'image_500.tif'
end
utils.getDocsPath()

GETDOCSPATH - Get the root folder of the built user documentation.

Syntax:

docsPath = utils.getDocsPath()

The documentation lives in two different places relative to the code, and which one is right depends on how MIB was started:

  • source checkout - docs is a sibling of mib, so the pages are in <mibPath>/../docs/html

  • compiled standalone - the deployment scripts ship the pages next to the executable, so they are in <mibPath>/docs/html. There is no way to place them a level higher: the MATLAB installer always puts the folders listed in InstallerOptions.AdditionalFiles inside application

The deployed layout is tested first because mib/docs never exists in a checkout. When neither folder is present - a checkout with no built documentation - the checkout path is returned, which the callers then fail to find and open the page on mib.helsinki.fi instead.

Output Arguments:
  • docsPath - [char] full path to the docs/html folder; the path is not guaranteed to exist

Usage:

Example 1 - address of a single help page

helpFilePath = fullfile(utils.getDocsPath(), ...
    'user-interface', 'ribbon', 'dataset', 'dataset-alignment.html');
utils.getInstallationPath(softwareName)

GETINSTALLATIONPATH - Get the installation directory of a deployed MATLAB application.

Syntax:

path = getInstallationPath(softwareName)

In the development environment, uses which(softwareName) to locate the file. In deployed mode, uses ctfroot / process-inspection fallbacks.

Input Arguments:
  • softwareName - [char] name of the software entry-point m-file (e.g. 'mib3')

Output Arguments:
  • path - [char] full path to the installation directory; [] on failure

Usage:

Example 1 - get MIB installation directory

installDir = utils.getInstallationPath('mib3');
utils.getMaxParpoolWorkers()

GETMAXPARPOOLWORKERS - Define maximum number of parallel workers for deployed versions.

Syntax:

cpuParallelLimitMax = getMaxParpoolWorkers()

Returns the smaller of the hardware-available worker count and the platform-specific compiled-app limit (8 on Windows, 4 on macOS/Linux). In the MATLAB development environment, returns Inf (no limit).

Output Arguments:
  • cpuParallelLimitMax - [numeric] maximum number of workers available for parallel processing

Usage:

Example 1 - retrieve the worker limit

cpuParallelLimitMax = utils.getMaxParpoolWorkers();
utils.getMibVersionNumberic(mibVersionString)

GETMIBVERSIONNUMBERIC - Get MIB version as a numeric value from a version string.

Syntax:

mibVersionNumeric = getMibVersionNumberic(mibVersionString)

Two string formats are supported:

  • Release: 'ver. 2.909 / 06.08.2024' - mibVersionNumeric is extracted from the text between 'ver.' and '/'.

  • Beta: 'ver. 2.909 (beta 07) / 06.08.2024' - mibVersionNumeric is computed as version minus beta offset: 2.909 - (1000 - 7) / 1000000.

Input Arguments:
  • mibVersionString - [char] MIB version string as defined in mib3.m

Output Arguments:
  • mibVersionNumeric - [double] numeric representation of the MIB version

Usage:

Example 1 - parse a release version string

ver = utils.getMibVersionNumberic('ver. 2025.12 / 05.12.2025');

Example 2 - parse a beta version string

ver = utils.getMibVersionNumberic('ver. 2025.11 (beta 4) / 04.11.2025');
utils.getPrefDir()

GETPREFDIR - Get directory where MIB preferences are stored.

Syntax:

prefdir = getPrefDir()

Platform-specific locations:

  • Windows: C:\Users\Username\Matlab

  • macOS: /Users/username/Matlab

  • Linux: /home/username/Matlab

Output Arguments:
  • prefdir - [char] full path to the MIB preferences directory

Usage:

Example 1 - retrieve the preferences directory path

prefdir = utils.getPrefDir();
utils.getUserStatsCandidates()

GETUSERSTATSCANDIDATES - List folders where MIB user statistics can be kept.

Syntax:

candidates = getUserStatsCandidates()

Builds the list of locations offered to the user for storing the per-machine statistics shards (mib_user_<COMPUTERNAME>.mat, see utils.saveUserStats()). The list is ordered from the most likely to follow the user between workstations to the least:

  1. the folder named by the MIB_USER_STATS environment variable, when set - an explicit override so that IT can preconfigure a location for a whole facility;

  2. <OneDrive>\Apps\MIB, falling back to <OneDrive>\Documents\MIB and then <OneDrive>\MIB depending on which of those folders the account actually has. Apps is the folder OneDrive designates for third-party application data, so MIB does not land in the middle of the user’s own files. <OneDrive> itself comes from %OneDriveCommercial%, then %OneDrive%, then the HKCU\Software\Microsoft\OneDrive\Accounts\*\UserFolder registry values. The registry fallback matters because the environment variables are only present when the OneDrive client has run in the current session, which is not the case for a deployed MIB started from a service or a scheduled task. The OneDrive root is never constructed from %USERPROFILE% - it is frequently relocated to a different drive;

  3. <HOMESHARE>\MIB - the AD network home directory, which follows the user across domain workstations but is unreachable off site;

  4. the machine-local folder returned by utils.getUserStatsDir(), which is always offered as the last entry.

A candidate is listed only when its parent folder exists, so the returned list never contains an unusable entry. The MIB subfolder itself is not created here - utils.saveUserStats() creates it on first write.

Warning

This function touches the file system and, for HOMESHARE, the network. It must only be called from user-initiated code such as utils.dlgs.chooseUserStatsLocation(), never during startup: an unreachable UNC path can block for several seconds.

Output Arguments:
  • candidates - [struct] 1xN structure array, one entry per available location, with fields:

    • label - [char] short name shown in the chooser dialog

    • folder - [char] full path to the folder that would hold the shards

    • note - [char] one-line explanation shown under the label

    • syncs - [logical] true when the location is expected to follow the user to other workstations

Usage:

Example 1 - list the locations and show the first one

candidates = utils.getUserStatsCandidates();
fprintf('%s -> %s\n', candidates(1).label, candidates(1).folder);

See also: utils.getUserStatsDir, utils.loadUserStats, utils.saveUserStats, utils.dlgs.chooseUserStatsLocation

utils.getUserStatsDir()

GETUSERSTATSDIR - Get the machine-local directory for MIB user statistics.

Syntax:

statsDir = getUserStatsDir()

Returns the OS-appropriate per-user application data directory where the statistics files (user Tiers) are kept when no shared folder was chosen.

Platform-specific locations:

  • Windows: %APPDATA%\MathWorks\MIB\ (C:\Users\<user>\AppData\Roaming\MathWorks\MIB)

  • macOS: ~/Library/Application Support/MIB/

  • Linux: $XDG_DATA_HOME/MIB/ or ~/.local/share/MIB/

Warning

Despite its name, AppData\Roaming is machine-local. It is uploaded at logoff only when an administrator set a roaming profile path on the account object in Active Directory, which is uncommon; the profile of an ordinary domain-joined workstation reports RoamingConfigured = False and the folder never leaves the machine. Two things make this easy to misread: domain group policy often defines roaming-profile settings (AddAdminGroupToRUP, ExcludeProfileDirs and friends) for every account regardless of whether roaming is actually enabled, and Entra “Enterprise State Roaming” sounds relevant but only ever syncs Windows settings and Store-app data, never %APPDATA%. OneDrive’s Known Folder Move likewise covers Desktop, Documents and Pictures and explicitly excludes AppData.

Treat the returned folder as local to this computer. For statistics that follow the user between workstations, see utils.getUserStatsCandidates(), which also offers OneDrive and the AD network home directory.

On failure (environment variable unset, directory cannot be created) the function returns an empty string '' and the caller should fall back to utils.getPrefDir().

Output Arguments:
  • statsDir - [char] full path to the MIB user-stats directory, or '' when the location is unavailable

Usage:

Example 1 - retrieve the user-stats directory path

statsDir = utils.getUserStatsDir();

See also: utils.getPrefDir, utils.getUserStatsCandidates, utils.loadUserStats

utils.interpolateLines(img, max_pnts, lineWidth)

INTERPOLATELINES - Interpolate line selections between slices.

Syntax:

img = interpolateLines(img, max_pnts, lineWidth)

One of two interpolation methods selectable via MIB -> File -> Preferences.

Note

This method interpolates only non-closed lines. Use utils.interpolateShapes for filled shapes.

Input Arguments:
  • img - [uint8] binary image dataset, e.g. the Selection layer [height, width, z]

  • max_pnts (optional) - [numeric] maximum number of interpolation points (default: 140)

  • lineWidth (optional) - [numeric] line width in pixels (default: 4)

Output Arguments:
  • img - [uint8] binary image dataset with interpolated lines

Usage:

Example 1 - interpolate line selections across slices with default settings

selection = obj.mibModel.getData3D('selection', [], 3);
selection = utils.interpolateLines(selection);
obj.mibModel.setData3D(selection, 'selection', [], 3);
utils.interpolateShapes(img, max_pnts)

INTERPOLATESHAPES - Interpolate the shapes between the slices.

Syntax:

[img, boundingBox] = interpolateShapes(img, max_pnts)

One of two interpolation methods. The interpolation method can be selected in MIB -> File -> Preferences.

Note

This method can interpolate only filled shapes; use utils.interpolateLines for non-closed line selections.

Input Arguments:
  • img - [uint8] binary image dataset, e.g. the Selection layer [height, width, z]

  • max_pnts (optional) - [numeric] maximum number of points used for interpolation (default: 140)

Output Arguments:
  • img - [uint8] binary image dataset with interpolated shapes

  • boundingBox - [numeric] bounding box of the interpolated area [xMin, xMax, yMin, yMax, zMin, zMax]; [] when no interpolation was performed

Usage:

Example 1 - interpolate selection shapes across slices

selection = obj.mibModel.getData3D('selection', [], 3);
[selection, bb] = utils.interpolateShapes(selection, 140);
obj.mibModel.setData3D(selection, 'selection', [], 3);
utils.isosurfaceMibRendering(Volume, materialIndex, pixSize, boundingBox, options)

ISOSURFACEMIBRENDERING - Generate an isosurface mesh for one material from a label volume.

Syntax:

fv = isosurfaceMibRendering(Volume, materialIndex, pixSize, boundingBox)
fv = isosurfaceMibRendering(Volume, materialIndex, pixSize, boundingBox, options)

Ported and refactored from utils.mibRenderModel (MIB2). Unlike the original, this function is purely computational - it does not open a figure or call view3d. Intended for headless export pipelines such as STL saving.

Input Arguments:
  • Volume - [uint8/uint16] label array [H, W, D]; each voxel is a material index (0 = exterior)

  • materialIndex - [numeric] scalar index of the material to extract

  • pixSize - struct with physical voxel dimensions:

    • .x - voxel width

    • .y - voxel height

    • .z - voxel depth

    • .units - physical unit string

  • boundingBox - [numeric] [xMin xMax yMin yMax zMin zMax] - physical coordinates of dataset corners

  • options (optional) - struct with mesh generation parameters:

    • .reduce - target image width in pixels for volume down-sampling before isosurface extraction; 0 = no reduction

    • .smooth - isotropic Laplacian smoothing kernel width in X (pixels); Y/Z kernel sizes scaled by aspect ratio; 0 = no smoothing

    • .maxFaces - maximum number of faces in the output mesh; 0 = no limit

Output Arguments:
  • fv - struct with mesh data; [] when the material is absent or produces an empty surface:

    • .faces - [F x 3] double, triangle face indices

    • .vertices - [V x 3] double, vertex coordinates in physical space

Usage:

Example 1 - extract material 2 as an STL mesh

opts.reduce   = 500;
opts.smooth   = 5;
opts.maxFaces = 300000;
fv = utils.isosurfaceMibRendering(modelData, 2, dataset.image.pixSize, ...
    dataset.image.boundingBox, opts);
if ~isempty(fv)
    stlwrite('material_2.stl', fv);
end
utils.loadUserStats(statsFolder, options)

LOADUSERSTATS - Load and merge the per-machine MIB statistics shards.

Syntax:

[totalTiers, ownTiers, shardNames] = loadUserStats(statsFolder)
[totalTiers, ownTiers, shardNames] = loadUserStats(statsFolder, 'tierPointsCoef', 500)

MIB statistics are stored as one file per workstation (mib_user_<COMPUTERNAME>.mat, written by utils.saveUserStats()) so that a folder shared through OneDrive or a network home can be used from several machines at once. Because no two machines ever write the same file, a sync engine can never merge them incorrectly or produce conflict copies; this function does the merging instead, by summing the shards at load time.

Merge rules, matching the semantics of the Users.Tiers fields defined in utils.defaults.generatePreferences():

  • logStartDate - the earliest value across the shards, so the log still starts when the user first ran MIB anywhere;

  • tierLevel - recomputed from the summed collectedPoints using the same rule as the level-up check in MibImageDocument.gui_WindowButtonUpFcn (level up while collectedPoints > tierPointsCoef * 2^tierLevel). Summing the stored levels would be meaningless, since the level is derived, not counted;

  • every other numeric field is a monotonic counter and is summed.

Only per-workstation shards are read. A plain mib_user.mat in the same folder is ignored on purpose: that is the name MIB2 writes its own statistics to on every exit, and MIB3 takes those points over once through the handover in models.MibModel.initializePreferences(). Summing the file here as well would count the imported points a second time, and again after every MIB2 session.

Unreadable or corrupt shards are skipped with a warning rather than failing the load - a half-synchronised file on a slow OneDrive folder must never prevent MIB from starting.

Input Arguments:
  • statsFolder - [char] folder holding the shard files. A missing folder is not an error and yields empty outputs

  • options - [struct] optional name-value arguments:

    • tierPointsCoef - [numeric] coefficient of the level-up rule, normally preferences.Users.tierPointsCoef. Default: 500

Output Arguments:
  • totalTiers - [struct] merged statistics across all shards, or struct([]) when the folder holds no readable shard. Callers should test with isempty and fall back to the defaults

  • ownTiers - [struct] statistics of this workstation’s shard alone, or struct([]) when this machine has not written one yet. Needed by controllers.MibController.exitProgram() to write back only this machine’s contribution

  • shardNames - [cell] names of the shard files that were merged

Usage:

Example 1 - load the totals from the configured folder

statsFolder = fileparts(obj.preferences.System.UserStatsProfile);
[totalTiers, ownTiers] = utils.loadUserStats(statsFolder, ...
    'tierPointsCoef', obj.preferences.Users.tierPointsCoef);

See also: utils.saveUserStats, utils.getUserStatsCandidates, utils.defaults.generatePreferences

utils.moveWindowOutside(hObject, mibGUI, alignH, alignV)

MOVEWINDOWOUTSIDE - Position a dialog window alongside the main MIB figure.

Syntax:

hObject = moveWindowOutside(hObject, mibGUI)
hObject = moveWindowOutside(hObject, mibGUI, alignH, alignV)

Attempts to place the dialog beside the main window. Falls back to centring on the main figure when there is insufficient screen space.

Input Arguments:
  • hObject - handle of the window to be moved

  • mibGUI - handle to the main MIB GUI (obj.mibModel.mibGUI); pass [] to centre on screen

  • alignH (optional) - [char] horizontal alignment: 'left' (default), 'right', 'center'

  • alignV (optional) - [char] vertical alignment: 'top' (default), 'bottom', 'center'

Output Arguments:
  • hObject - handle to the repositioned window

Usage:

Example 1 - position a child dialog to the left of the main window

obj.view.gui = utils.moveWindowOutside(obj.view.gui, obj.mibModel.mibGUI);

Example 2 - position to the right and bottom

obj.view.gui = utils.moveWindowOutside(obj.view.gui, obj.mibModel.mibGUI, 'right', 'bottom');
utils.overrideDescriptions(handles, developerMode, fieldPath, exclusionList)

OVERRIDEDESCRIPTIONS - Override Description property of widgets to add the widget handle name to.

Syntax:

function stopped = overrideDescriptions(handles, developerMode, fieldPath, exclusionList)

the beginning of the Description field depending on the developerMode setting.

Input Arguments:
  • handles - handles structure of the view class (obj.handles)

  • developerMode - logical switch, when true - adds the handle label to the beginning of the Description field that is shown as a tooltip false - removes the handle label from the beginning of the Description field that is shown as a tooltip

  • fieldPath - char, optional string to specify the parent name when generating the handle. This text will be added before the handle tag into the tooltip

  • exclusionList - cell array of char, optional list of field names to skip. Fields matching any name in this list will not be renamed, and recursion will not descend into them. Matching is against the bare field name only (not the full path).

Output Arguments:
  • stopped - logical true if function exited early due to no change needed or first update done

Usage:

Example 1 - add handle name to tooltips (developer mode on)

developerMode = true;
utils.overrideDescriptions(obj.handles, developerMode);

Example 2 - skip two panels while adding handle labels

utils.overrideDescriptions(obj.handles, developerMode, 'obj.handles', {'segmentation', 'toolbar'});
utils.purgeChildController(parentObj, src)

PURGECHILDCONTROLLER - remove a child controller from its parent.

Syntax:

function purgeChildController(parentObj, src)

Called as the CloseEvent listener callback wired by utils.startController. Finds the child by class name, deletes it if still valid, and removes it from the parent’s tracking arrays.

Input Arguments:
  • parentObj - handle - parent controller (must have childControllers / childControllersIds)

  • src - handle - the child controller that fired CloseEvent

Usage:

Example 1 - wired internally by utils.startController (not called directly)

addlistener(child, 'CloseEvent', @(src,~) utils.purgeChildController(parentObj, src));
utils.resizeImage3d(img, scale, options)

RESIZEIMAGE3D - Resize a 3D or 4D image dataset.

Syntax:

imgOut = resizeImage3d(img, scale)
imgOut = resizeImage3d(img, scale, options)
Input Arguments:
  • img - [numeric] 3D (y, x, z) or 4D (y, x, z, c) dataset to resize

  • scale - [numeric] scalar or vector [scaleY, scaleX, scaleZ] resize factor; pass [] when options.width / options.height / options.depth are used instead

  • options (optional) - struct with resizing settings:

    • .algorithm - [char] resizing algorithm: 'imresize' (default), 'interpn', 'tformarray'

    • .width - [numeric] target width; overrides the scale parameter

    • .height - [numeric] target height; overrides the scale parameter

    • .depth - [numeric] target depth; overrides the scale parameter

    • .method - [char] interpolation method (depends on algorithm - see note below)

    • .imgType - [char] dataset type: '4D' or '3D' (auto-detected when absent)

    • .showWaitbar - [logical] show a progress bar (default: 1); set to 0 to suppress

    • .wb - handle to an existing uiprogressdlg; updated in place, NOT deleted on exit

    • .ParentFigure - handle to a parent figure; a local progress dialog is created/deleted when .wb is absent

Output Arguments:
  • imgOut - [numeric] resampled dataset (same class as input)

Note

Algorithm and method combinations:

  • 'imresize' (default, fastest) - uses imresize3 on R2017a+, otherwise resizes XY then Z. Methods: 'nearest', 'bilinear', 'bicubic' (default), 'lanczos2', 'lanczos3', etc.

  • 'interpn' - N-D gridded interpolation; faster than 'tformarray' but needs more memory. Methods: 'linear', 'nearest', 'cubic' (default), 'spline', 'pchip'.

  • 'tformarray' - spatial transform; slowest but most memory-friendly. Methods: 'nearest', 'linear', 'cubic'.

Usage:

Example 1 - resize uniformly to 50 %

imgOut = utils.resizeImage3d(img, 0.5);

Example 2 - resize to specific dimensions with bicubic interpolation

opts.width  = 512;
opts.height = 512;
opts.depth  = 64;
opts.method = 'bicubic';
imgOut = utils.resizeImage3d(img, [], opts);
utils.saveProjectStructure(rootFolder, outputFile, excludeFolders)

SAVEPROJECTSTRUCTURE - Generate a hierarchical text file listing the project folder structure.

Syntax:

saveProjectStructure(rootFolder, outputFile)
saveProjectStructure(rootFolder, outputFile, excludeFolders)
Input Arguments:
  • rootFolder - [char] root directory path to scan, e.g. 'C:\Projects\MIB' or pwd

  • outputFile - [char] output file path, e.g. 'project_structure.txt'

  • excludeFolders (optional) - [cell of char] folder names to skip (default: {'.git', 'assets', 'external'}). Matching is case-sensitive against bare folder names.

Usage:

Example 1 - scan current directory with default exclusions

utils.saveProjectStructure(pwd, 'structure.txt');

Example 2 - scan with custom exclusions

utils.saveProjectStructure(pwd, 'structure.txt', {'assets', 'docs', 'test_data'});

Example 3 - scan MIB mib/ subfolder

utils.saveProjectStructure('C:\Matlab\MIB3\mib', 'mib_structure.txt', ...
    {'external', 'assets', 'jars', 'plugins', 'guide'});
utils.saveUserStats(statsFolder, ownTiers)

SAVEUSERSTATS - Write this workstation’s MIB statistics shard.

Syntax:

shardPath = saveUserStats(statsFolder, ownTiers)

Writes mib_user_<COMPUTERNAME>.mat into statsFolder, creating the folder when needed. This machine only ever writes its own shard, which is what makes a shared folder (OneDrive, network home) safe: two workstations never write the same file, so the sync engine has nothing to resolve and no points can be lost. The shards are summed back together at load time by utils.loadUserStats().

Important

ownTiers must be this machine’s contribution alone, not the session total. The in-memory preferences.Users.Tiers holds the sum across all workstations, so the caller has to subtract the total that was loaded at startup and add the result to the shard it started from - see controllers.MibController.exitProgram(). Writing the session total here would re-count every other machine on every exit.

Input Arguments:
  • statsFolder - [char] destination folder for the shard

  • ownTiers - [struct] statistics contributed by this workstation, saved as the Tiers variable of the .mat file

Output Arguments:
  • shardPath - [char] full path of the file that was written

Usage:

Example 1 - store the shard next to the configured profile

statsFolder = fileparts(obj.mibModel.preferences.System.UserStatsProfile);
shardPath = utils.saveUserStats(statsFolder, ownTiers);

See also: utils.loadUserStats, utils.getUserStatsCandidates, controllers.MibController.exitProgram

utils.setMibTheme(themeName)

SETMIBTHEME - switch MIB to the light or dark theme, or back to the MATLAB theme.

Syntax:
success = utils.setMibTheme(themeName)

The theme is set through the session-only TemporaryValue of the MATLAB setting settings().matlab.appearance.MATLABTheme. This is the only route that also switches the AppContainer chrome (ribbon, panel title bars, document area); forcing a theme per figure with theme(fig, ...) leaves the ribbon in the MATLAB theme. Every figure receives the change, so each ThemeChangedFcn of MIB repaints its explicit colors.

Side effects:

  • the setting is global, so while MIB runs from MATLAB the MATLAB desktop and all other figures switch as well

  • TemporaryValue lasts for the MATLAB session only and never touches the saved PersonalValue of the user; 'System' removes it, returning to whatever the user set in MATLAB (which may itself be MATLAB’s own 'System', i.e. follow the operating system). controllers.MibController.exitProgram removes it on exit.

Releases without the setting (before R2025a), and runtimes where the settings API is not available, return false without an error. Investigation and the rejected per-figure route: development/notes/dark_light_scheme.md.

Input Arguments:
  • themeName - [char] 'System' (follow the MATLAB theme), 'Light' or 'Dark'; case-insensitive

Output Arguments:
  • success - [logical] true when the setting was applied

Usage:

Example 1 - force the dark theme, then return to the MATLAB theme

utils.setMibTheme('Dark');
utils.setMibTheme('System');

See also: utils.themeColors, utils.applyThemeColors

utils.startController(parentObj, controllerName, varargin)

STARTCONTROLLER - launch a child controller from any MIB controller.

Syntax:

function startController(parentObj, controllerName, varargin)

Works identically to controllers.MibController.startController but can be called from any controller that exposes the following properties: childControllers - cell array of open child controller handles childControllersIds - cell array of open child controller class names mibModel - handle to MibModel

The child controller must follow the MIB controller contract: Constructor MyController(mibModel) or MyController(mibModel, [], BatchOpt) Event CloseEvent - fired when the controller closes Property view - empty when running in batch mode (no GUI)

Input Arguments:
  • parentObj - handle - parent controller that owns the child

  • controllerName - char - fully-qualified class name, e.g. ‘controllers.ResampleDataset’

  • varargin{1} - (optional) extra arg passed to the child constructor (usually [])

  • varargin{2} - (optional) BatchOpt struct to run in batch mode, or NaN for returnBatchOpt

Usage:

Example 1 - open ResampleDataset GUI (interactive mode)

utils.startController(obj, 'controllers.ResampleDataset');

Example 2 - run ResampleDataset in batch mode (no GUI)

BatchOpt.ResamplingMode = {'Dimensions'};
BatchOpt.DimensionX = '256';
BatchOpt.DimensionY = '256';
utils.startController(obj, 'controllers.ResampleDataset', [], BatchOpt);
utils.struct2array(S)

STRUCT2ARRAY - Convert a scalar struct to a flat array of its field values.

Syntax:

result = struct2array(S)

Replacement for the built-in struct2array that was removed in MATLAB R2021b.

Input Arguments:
  • S - [struct] scalar input structure

Output Arguments:
  • result - array containing all field values of S concatenated horizontally

Usage:

Example 1 - flatten a struct of numeric values

S.a = 1; S.b = 2; S.c = 3;
result = utils.struct2array(S);   % result = [1 2 3]
utils.themeColors(themeSource)

THEMECOLORS - named MIB widget colors for the light or the dark theme.

Syntax:
palette = utils.themeColors(themeSource)

The single definition of the colors that MIB assigns explicitly to widgets and that therefore have to be adapted to the MATLAB theme. Colors left on auto (...ColorMode = 'auto') follow the theme by themselves and are not listed.

The light colors are the original MIB colors. The dark colors are darker tones of the same hues, chosen to keep a WCAG contrast of at least 4.5:1 against the near-white text ([0.851 0.851 0.851]) that the dark theme uses for buttons; the font color is therefore always left on auto. Measurements and the rejected alternative (pastels with black text) are in development/notes/dark_light_scheme.md.

Input Arguments:
  • themeSource - one of:

    • 'light' or 'dark' - the palette of that theme

    • a figure handle - the palette of the theme the figure currently uses (hFig.Theme.BaseColorStyle); releases without the figure Theme property (before R2025a) get the light palette

Output Arguments:
  • palette - [struct] RGB triplets, fields:

    • .bufferInMemory - Datasets panel, buffer with data but no file on disk

    • .bufferFileBacked - Datasets panel, buffer with data loaded from a file

    • .bufferSelected - Datasets panel, the currently shown buffer

    • .dialogAction - main action button of a dialog (e.g. Stitch, Continue), light [0.149 0.902 0.1804]

    • .dialogClose - Close/Cancel button of a dialog, light [1 0.5294 0.102]

    • .dialogSecondary - secondary action button, weaker than dialogAction (e.g. Update in BatchProcessing), light [0.6314 0.9412 0.6471]

    • .dialogStop - a running action that can be stopped (e.g. Stop protocol), light [1 0 0]

    • .fieldError - background of an input field (dropdown, edit field) that shows a missing or invalid input (e.g. the material dropdowns of Graphcut without a model), light [1 0 0]

    • .tabHighlight - background of a tab or panel that is set apart from the rest of the window (e.g. the Animation tab of VolRenApp), light [0.8 0.8 0.8]

    • .panelYellow, .panelBlue, .panelGreen - tinted background of a tab, panel or label that color-codes a part of a window (e.g. the Preprocess, Train and Predict tabs of DeepMIB), light [1 0.9804 0.7686], [0.7686 0.902 0.9882], [0.8588 0.9294 0.7804]. The dark versions keep the hue (amber-brown instead of olive for yellow) at a brightness slightly above the dark theme background, 7.4-8.1:1 with the auto text

    • .panelRed, .panelMint, .panelSky - further tab/panel tints (e.g. the three tabs of the GolgiOrientation plugin), light [0.9882 0.9216 0.9216] (pink), [0.9098 0.9882 0.902], [0.8196 0.9294 0.9686]; dark 7.5-8.9:1. The pink is kept desaturated in dark so that it does not read as an error red

    • .widgetMint - near-white buttons and input fields on those tints, light [0.9882 1 0.9882], dark a near-neutral field color (11.9:1)

    • .widgetYellow, .widgetBlue, .widgetGreen - buttons and input fields placed on the matching panel... color, light [1 0.9882 0.9098], [0.8784 0.9608 1], [0.9098 0.9608 0.9098]. Light: paler than the panel; dark: darker than the panel (10.4-10.6:1), following the dark theme, where input fields are darker than the background they sit on

    • .fieldYellow, .fieldBlue - input fields on the plain window background tinted to tell two kinds of values apart (e.g. the probability and the Min/Max spinners of the DeepMIB augmentation settings), light [0.9804 0.9765 0.8235], [0.8314 0.9333 1]. Dark: lighter than the background (6.7:1 and 7.6:1), because at the brightness of the theme’s own fields (darker than the background) the hue is no longer recognizable

    • .background - the theme’s own default background of figures, panels and buttons (light [0.9608 0.9608 0.9608], dark [0.1294 0.1294 0.1294]); used to recognize a default color that was copied from another widget and therefore no longer follows the theme

    • .tableCell - background of table cells painted explicitly with a uistyle (e.g. the value columns of the Preferences color tables), light [1 1 1], dark the theme’s field background; the table’s own ForegroundColor is ignored in the dark theme, so the cells must be dark for the auto text to be readable

    • .tableHighlight - background of a table cell marked as the current choice by a uistyle (e.g. the selected material in the Segmentation panel), light [0.2 0.6 1]; its text is .text

    • .text - normal text, equal to the auto font color of MATLAB widgets. For places that do not follow the theme by themselves: uihtml content (a web page that ignores the MATLAB theme, colored via CSS), tab titles set explicitly in App Designer and uistyle table cells

    • .disabledText - greyed-out text of table cells that are shown but not in use at the moment (e.g. the materials when the selection is restricted to a material), light [0.78 0.78 0.78]. Deliberately below 4.5:1 so that it reads as inactive, dark [0.4 0.4 0.4] gives 3.3:1 on .tableCell

    • .dimmedText - secondary, subdued text on the dialog background (e.g. the suffix line of utils.dlgs.showErrorDialog); dimmer than the normal text but still at least 4.5:1 against the background

    • .htmlLink - hyperlinks of uihtml content; the browser default dark blue is unreadable on the dark background

Usage:
palette = utils.themeColors(obj.UIFigure);
buttonHandle.BackgroundColor = palette.bufferSelected;

See also

utils.applyThemeColors, controllers.MibActiveDataset.paintBufferButton

utils.themeHtmlStyle(hFig, backgroundColor)

THEMEHTMLSTYLE - CSS that gives a uihtml page the colors of a dark-themed window.

Syntax:
styleTag = utils.themeHtmlStyle(hFig, backgroundColor)

A uihtml component renders a web page that ignores the MATLAB theme: it always shows a white background with black text, which stands out as a bright block in a dark window, and the browser default link color (dark blue) is unreadable on a dark background. In the dark theme this function returns a <style> element that sets the page background to backgroundColor, the text to utils.themeColors('dark').text and links to .htmlLink; in the light theme it returns an empty char, so the page keeps the browser defaults.

Insert the element before any style of the caller (first in <head>, or at the very beginning of an HTML fragment), so that the caller’s own styles still win. The colors are fixed at the moment the page is written: a window has to rewrite its uihtml content from its ThemeChangedFcn to follow a theme switch.

Input Arguments:
  • hFig - [matlab.ui.Figure] the window that holds the uihtml; its Theme.BaseColorStyle decides the result. Releases without the figure Theme property (before R2025a) are treated as light

  • backgroundColor - [RGB triplet] the color the page should take, usually the BackgroundColor of the uihtml parent or hFig.Color, so that the page merges into the window

Output Arguments:
  • styleTag - [char] '<style>html,body{...} a{...}</style>' in the dark theme, '' otherwise

Usage:
hHtml = obj.view.handles.infoText;
hHtml.HTMLSource = [utils.themeHtmlStyle(obj.view.gui, hHtml.Parent.BackgroundColor), ...
    '<p style="font-family: Sans-serif;">Text</p>'];

See also

utils.themeColors, utils.applyThemeColors

utils.traceCurve(img, options, mask)

TRACECURVE - Connect two points by searching for a minimum-gradient path.

Syntax:

[mask, status] = traceCurve(img, options)
[mask, status] = traceCurve(img, options, mask)

Based on the Accurate Fast Marching function by Dirk-Jan Kroon. Called from the Membrane Click Tracker segmentation tool.

Input Arguments:
  • img - original image used to probe gradients

  • options - struct with algorithm parameters:

    • .p1 - starting point coordinates [y; x]

    • .p2 - target point coordinates [y; x]

    • .scaleFactor - scale factor for amplifying intensity differences

    • .segmTrackBlackChk - 1 when signal is dark (black membrane), 0 for bright

    • .colorId - index of the colour channel to follow

  • mask (optional) - existing mask/selection layer to draw into

Output Arguments:
  • mask - [uint8] bitmap image with the connecting line (use as Selection layer)

  • status - [numeric] 1 on success, 0 on failure

Usage:

Example 1 - trace a curve between two points

options.p1 = [100; 150];
options.p2 = [200; 300];
options.scaleFactor = 1;
options.segmTrackBlackChk = 1;
options.colorId = 1;
[mask, status] = utils.traceCurve(img, options);
utils.unFocus(hObject)

UNFOCUS - Move focus away from the currently focused widget.

Syntax:

unFocus(hObject)

Temporarily disables and re-enables the widget to transfer focus back to the parent figure, preventing unwanted keyboard capture by input fields.

Input Arguments:
  • hObject - handle to the UI widget that should lose focus

Usage:

Example 1 - unfocus a button after clicking

utils.unFocus(obj.view.handles.panels.segmentation.handles.addMaterial);
utils.updateBatchOptCombineFields_Shared(BatchOpt, BatchOptInput)

UPDATEBATCHOPTCOMBINEFIELDS_SHARED - Merge BatchOpt fields from an input struct into a default struct.

Syntax:

BatchOpt = updateBatchOptCombineFields_Shared(BatchOpt, BatchOptInput)

Used by all tools that support Batch mode to merge caller-supplied options into the controller’s full default BatchOpt. Handles popup-menu cells (preserving the options list), numeric edit fields, and plain values.

Input Arguments:
  • BatchOpt - struct containing the full default BatchOpt for the controller

  • BatchOptInput - struct supplied by the caller (may be a subset of fields)

Output Arguments:
  • BatchOpt - merged struct with caller values applied over defaults

Usage:

Example 1 - merge user-supplied options into controller defaults

BatchOpt = utils.updateBatchOptCombineFields_Shared(BatchOpt, BatchOptInput);
utils.updateBatchOptFromGUI_Shared(BatchOpt, hObject)

UPDATEBATCHOPTFROMGUI_SHARED - Update a BatchOpt struct field from a GUI widget value.

Syntax:

BatchOpt = updateBatchOptFromGUI_Shared(BatchOpt, hObject)

Used by all Batch-mode-compatible tools to synchronise a single widget change into the corresponding BatchOpt field. Handles edit fields, checkboxes, dropdowns, radio button groups, tab groups, spinners, and numeric edit fields.

Input Arguments:
  • BatchOpt - current BatchOpt struct for the controller

  • hObject - handle to the GUI widget that triggered the change

Output Arguments:
  • BatchOpt - updated BatchOpt struct

Usage:

Example 1 - wire a widget callback to keep BatchOpt in sync

obj.BatchOpt = utils.updateBatchOptFromGUI_Shared(obj.BatchOpt, src);
utils.updateGUIFromBatchOpt_Shared(View, BatchOpt)

UPDATEGUIFROMBATCHOPT_SHARED - Populate GUI widgets from a BatchOpt struct.

Syntax:

View = updateGUIFromBatchOpt_Shared(View, BatchOpt)

Used by all Batch-mode-compatible tools to initialise the dialog widgets from a BatchOpt struct - e.g. when opening a dialog with a previously saved configuration. Handles edit fields, checkboxes, dropdowns, radio button groups, tab groups, spinners, and numeric edit fields.

Input Arguments:
  • View - View class of the controller (must expose View.Figure)

  • BatchOpt - BatchOpt struct whose fields drive the widget update

Output Arguments:
  • View - View class with updated widget values

Usage:

Example 1 - restore widget state when opening a dialog

obj.View = utils.updateGUIFromBatchOpt_Shared(obj.View, obj.BatchOpt);
utils.updatePixSizeAndResolution(img_info, pixSize, options)

UPDATEPIXSIZEANDRESOLUTION - Calculate update resolution fields in the imageData.img_info(‘ImageDescription’) or recalculate physical size of voxels.

Syntax:

[img_info, pixSize, result] = updatePixSizeAndResolution(img_info, pixSize)
[img_info, pixSize, result] = updatePixSizeAndResolution(img_info, pixSize, options)

Optionally shows an interactive dialog so the user can review/change voxel sizes before the update is applied.

  • If ‘BoundingBox’ information exist in the imageData.img_info(‘ImageDescription’) the function recalculates the imageData.pixSize based on information from the BoundingBox.

  • If ‘BoundingBox’ is missing, but imageData.img_info(‘XResolution’) is present the imageData.pixSize recalculated based on XResolution and YResolution information

  • If both ‘BoundingBox’ and ‘XResolution’ is missing, the resolution is recalculated based on imageData.pixSize

Input Arguments:
  • img_info - information about the dataset, an instance of the MATLAB dictionary class. Pass [] to skip the img_info resolution update (e.g. when only the dialog / pixSize update is needed).

  • pixSize - a structure (imageData.pixSize) with dimensions of voxels, .x .y .z .t .tunits .units the fields are:

    • .x - physical width of a pixel

    • .y - physical height of a pixel

    • .z - physical depth of a pixel

    • .t - time between the frames for 2D movies

    • .tunits - time units

    • .units - physical units for x, y, z. Possible values: [m, cm, mm, um, nm]

  • options - (optional) a struct with optional fields:

    • .showDialog - logical (default false); when true, prompt the user with an interactive dialog to review and edit the voxel sizes before applying

    • .ParentFigure - handle to the parent figure/window used to anchor the dialog

    • .mibPath - (char) MIB installation directory, used for help / icon lookup

    • .HelpUrl - (char) URL or path for the Help button shown in the dialog

    • .WindowStyle - [char] 'normal' (default) or 'modal'

Output Arguments:
  • img_info - updated imageData.img_info (unchanged and [] when img_info was passed as [])

  • pixSize - updated imageData.pixSize (unchanged when user cancels the dialog)

  • result - 1 on success, 0 when the user cancelled the interactive dialog

Note

Requires Width, Height, Depth fields in img_info when img_info is not [].

Usage:

Example 1 - update resolution fields in img_info from a known pixSize (no dialog)

pixSize.x = 0.05; pixSize.y = 0.05; pixSize.z = 0.2;
pixSize.t = 1; pixSize.units = 'um'; pixSize.tunits = 's';
[img_info, pixSize] = utils.updatePixSizeAndResolution(img_info, pixSize);

Example 2 - recalculate pixSize from BoundingBox / XResolution stored in img_info

[img_info, pixSize] = utils.updatePixSizeAndResolution(img_info);

Example 3 - interactive dialog only (no img_info update needed, e.g. from MibRibbon)

dlgOpts.showDialog   = true;
dlgOpts.ParentFigure = obj.view.gui;
dlgOpts.mibPath      = obj.mibModel.mibPath;
dlgOpts.HelpUrl      = fullfile(obj.mibModel.mibPath, 'techdoc/html/user-interface/menu/dataset/index.html#parameters');
[~, pixSize, result] = utils.updatePixSizeAndResolution([], obj.mibModel.I{id}.pixSize, dlgOpts);
if result == 0; return; end
obj.mibModel.I{id}.pixSize = pixSize;

Example 4 - interactive dialog + img_info update in one call (e.g. during save)

dlgOpts.showDialog   = true;
dlgOpts.ParentFigure = obj.mibGUI;
dlgOpts.mibPath      = obj.mibPath;
[img_info, pixSize, result] = utils.updatePixSizeAndResolution(img_info, currentPixSize, dlgOpts);
if result == 0; return; end