Class SomaUtils

java.lang.Object
sc.fiji.snt.tracing.auto.SomaUtils

public class SomaUtils extends Object
Utilities for automatic soma detection and ROI generation.

Provides methods to detect the soma (cell body) in fluorescent images using a combined EDT-intensity approach, flood fill the region, extract contours, and convert to ImageJ ROIs.

Three detection modes are available:
Author:
Tiago Ferreira
See Also:
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final record 
    Container for soma detection results.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final String
    Output type: Circular ROI with estimated radius
    static final String
    Output type: Area ROI from flood fill contour
    static final String
    Output type: Point ROI at soma center
  • Method Summary

    Modifier and Type
    Method
    Description
    static double
    computeMaskArea(net.imglib2.img.Img<net.imglib2.type.logic.BitType> mask, double[] spacing)
    Computes the area of a binary mask.
    static double[]
    computeMaskCentroid(net.imglib2.img.Img<net.imglib2.type.logic.BitType> mask, double[] spacing)
    Computes the centroid of a binary mask.
    static double
    computeMinimumThreshold(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source)
    Computes the Minimum auto-threshold of the given image.
    static double
    computeOtsuThreshold(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source)
    Computes Otsu's threshold using ImageJ Ops.
    detectAllSomas(net.imagej.ImgPlus<?> source)
    Detects all somas using ImgPlus with default settings.
    detectAllSomas(net.imagej.ImgPlus<?> source, double threshold, int zSlice, double minRadius)
    Detects all somas using ImgPlus with automatic spacing.
    detectAllSomas(net.imagej.ImgPlus<?> source, double threshold, int zSlice, double minRadius, double minSomaDistance)
    Detects all somas using ImgPlus with automatic spacing and NMS.
    detectAllSomas(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, double threshold)
    Detects all somas using default minimum radius.
    detectAllSomas(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, double threshold, double minRadius)
    Detects all somas using EDT local maxima approach.
    detectAllSomas(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, double threshold, double minRadius, double minSomaDistance)
    Detects all somas in a 2D image using EDT + local maxima + NMS.
    detectSoma(net.imagej.ImgPlus<?> source)
    Full soma detection using ImgPlus with automatic thresholding.
    detectSoma(net.imagej.ImgPlus<?> source, double threshold, int zSlice)
    Full soma detection using ImgPlus with spacing extracted automatically.
    detectSoma(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, double threshold, double[] spacing)
    Full soma detection: finds center, floods region, extracts contour.
    detectSomaAt(net.imagej.ImgPlus<?> source, long seedX, long seedY, double threshold, int zSlice)
    Detects soma at a specific seed point using ImgPlus.
    detectSomaAt(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, long seedX, long seedY, double threshold)
    Detects soma at a specific seed point.
    detectSomasAt(ij.ImagePlus imp, Collection<ij.gui.Roi> rois)
    Detects somas at the centroids of the given ROIs.
    detectSomasAt(net.imagej.ImgPlus<?> source, List<long[]> seeds)
    Detects somas at the given seed coordinates using an ImgPlus.
    detectSomasAt(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, List<long[]> seeds)
    Detects somas at the given seed coordinates.
    static double
    Estimates the minimum inter-soma distance from a list of detected somas using single-linkage hierarchical clustering with gap analysis.
    static <T extends net.imglib2.type.numeric.RealType<T>>
    double
    estimateMinSomaDistance(List<SomaUtils.SomaResult> somas, net.imglib2.RandomAccessibleInterval<T> source)
    Estimates the minimum inter-soma distance using a hybrid approach: EDT-thickness filtering followed by spatial gap analysis.
    static Polygon
    extractContour(net.imglib2.img.Img<net.imglib2.type.logic.BitType> mask)
    Extracts the boundary contour from a binary mask using Moore boundary tracing.
    static <T extends net.imglib2.type.numeric.RealType<T>>
    List<SomaUtils.SomaResult>
    filterSomasByIntensity(List<SomaUtils.SomaResult> somas, net.imglib2.RandomAccessibleInterval<T> source)
    Filters a list of detected somas by sampling the source image intensity at each soma center and applying Otsu's threshold to separate real (bright) somas from false detections (dim).
    static <T extends net.imglib2.type.numeric.RealType<T>>
    List<SomaUtils.SomaResult>
    filterSomasByThickness(List<SomaUtils.SomaResult> somas, net.imglib2.RandomAccessibleInterval<T> source)
    Filters a list of detected somas by their local EDT thickness, using Otsu's method on the EDT value distribution to separate thick (real soma) from thin (artifact) detections.
    static net.imglib2.img.Img<net.imglib2.type.logic.BitType>
    floodFillSoma(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, long seedX, long seedY, double threshold)
    Creates a binary mask of the soma region using flood fill from seed point.
    static Path
    roiToSomaPath(ij.gui.Roi roi, double[] spacing)
    Creates a single-node soma Path from an ImageJ ROI.
    static Path
    roiToSomaPath(ij.gui.Roi roi, Path referencePath)
    Creates a single-node soma Path from an ImageJ ROI using calibration from a reference Path.
    static <T extends net.imglib2.type.numeric.RealType<T>>
    List<SomaUtils.SomaResult>
    selectTopSomasByThickness(List<SomaUtils.SomaResult> somas, net.imglib2.RandomAccessibleInterval<T> source, int n)
    Selects the top-N somas by EDT thickness (distance to nearest background pixel at each soma's center), ranking by descending EDT value.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

  • Method Details

    • detectSoma

      public static SomaUtils.SomaResult detectSoma(net.imagej.ImgPlus<?> source, double threshold, int zSlice)
      Full soma detection using ImgPlus with spacing extracted automatically.

      Convenience method that extracts spacing from the ImgPlus calibration.

      Parameters:
      source - input image (2D or 3D ImgPlus)
      threshold - intensity threshold. Use -1 for Otsu, NaN for mean.
      zSlice - Z-slice to use (0-indexed), or -1 for middle slice
      Returns:
      SomaResult containing center, mask, contour, and radius; or null if detection fails
      See Also:
    • detectSoma

      public static SomaUtils.SomaResult detectSoma(net.imagej.ImgPlus<?> source)
      Full soma detection using ImgPlus with automatic thresholding.

      Convenience method using Otsu's threshold and spacing from ImgPlus calibration.

      Parameters:
      source - input image (2D or 3D ImgPlus)
      Returns:
      SomaResult containing center, mask, contour, and radius; or null if detection fails
      See Also:
    • detectSoma

      public static SomaUtils.SomaResult detectSoma(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, double threshold, double[] spacing)
      Full soma detection: finds center, floods region, extracts contour.
      Parameters:
      source - input image (2D)
      threshold - intensity threshold. Use -1 for Otsu, NaN for mean.
      spacing - voxel spacing [x, y], or null for unit spacing
      Returns:
      SomaResult containing center, mask, contour, and radius; or null if detection fails
    • detectSomaAt

      public static SomaUtils.SomaResult detectSomaAt(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, long seedX, long seedY, double threshold)
      Detects soma at a specific seed point.

      Useful for interactive detection where user clicks near a soma.

      Parameters:
      source - input image (2D)
      seedX - X coordinate of seed point (voxels)
      seedY - Y coordinate of seed point (voxels)
      threshold - intensity threshold. Use -1 for Otsu, NaN for mean.
      Returns:
      SomaResult, or null if seed is in background or detection fails
    • detectSomaAt

      public static SomaUtils.SomaResult detectSomaAt(net.imagej.ImgPlus<?> source, long seedX, long seedY, double threshold, int zSlice)
      Detects soma at a specific seed point using ImgPlus.
      Parameters:
      source - input image (2D or 3D ImgPlus)
      seedX - X coordinate of seed point (voxels)
      seedY - Y coordinate of seed point (voxels)
      threshold - intensity threshold. Use -1 for Otsu, NaN for mean.
      zSlice - Z-slice to use (0-indexed), or -1 for middle slice
      Returns:
      SomaResult, or null if seed is in background or detection fails
    • detectSomasAt

      public static List<SomaUtils.SomaResult> detectSomasAt(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, List<long[]> seeds)
      Detects somas at the given seed coordinates. Each seed is passed to detectSomaAt(RandomAccessibleInterval, long, long, double) with an auto-computed threshold (Otsu). Seeds that fall in the background or fail detection are silently skipped.

      This is useful when soma locations are already known (e.g., from manual annotation, ROI centroids, or an external detector) and only the contour/radius characterization is needed. The returned list is directly compatible with AbstractGWDTTracer.traceMultiSoma(List).

      Important: Since seeds are user-provided (i.e., pre-curated), callers should disable automatic soma filtering on the tracer before passing the results to AbstractGWDTTracer.traceMultiSoma(List):

      
       List<SomaResult> somas = SomaUtils.detectSomasAt(source, seeds);
       tracer.setAutoFilter(false);
       List<Tree> trees = tracer.traceMultiSoma(somas);
       
      Otherwise, the tracer's heuristic reduction pipeline may discard valid somas. See AbstractGWDTTracer.setAutoFilter(boolean).
      Parameters:
      source - input image (2D)
      seeds - list of long[]{x, y} pixel coordinates
      Returns:
      list of successfully detected SomaResults (may be smaller than seeds if some seeds are invalid); sorted by radius (largest first)
      See Also:
    • detectSomasAt

      public static List<SomaUtils.SomaResult> detectSomasAt(net.imagej.ImgPlus<?> source, List<long[]> seeds)
      Detects somas at the given seed coordinates using an ImgPlus.

      Each seed can be either long[]{x, y} or long[]{x, y, z}. For 3D images, the Z coordinate determines which slice is used for soma characterization:

      • z >= 0: the specified slice (0-indexed) is used directly
      • z < 0 (or seed has only 2 elements): Z is resolved automatically per soma using MIP-based intensity lookup

      For 2D images, the Z component (if present) is ignored.

      Since seeds are user-provided, callers should call setAutoFilter(false) on the tracer before passing the results to AbstractGWDTTracer.traceMultiSoma(List).

      Parameters:
      source - input image (2D or 3D ImgPlus)
      seeds - list of long[]{x, y} or long[]{x, y, z} pixel coordinates. Z is 0-indexed; -1 means auto-resolve via MIP-based intensity lookup
      Returns:
      list of successfully detected SomaResults, sorted by radius (largest first)
      See Also:
    • detectSomasAt

      public static List<SomaUtils.SomaResult> detectSomasAt(ij.ImagePlus imp, Collection<ij.gui.Roi> rois)
      Detects somas at the centroids of the given ROIs. This is a convenience method that extracts centroids via RoiConverter.getCentroids(java.util.Collection) and delegates to detectSomasAt(ImgPlus, List).

      This supports any ROI type (point, area, line, composite). For area ROIs, the contour centroid is used; for point ROIs, the point coordinates are used directly. The Z coordinate for each seed is derived from Roi.getZPosition(): ROIs associated with a specific slice use that slice; ROIs without slice association have their Z resolved automatically via MIP-based intensity lookup.

      Since seeds are user-provided, callers should call setAutoFilter(false) on the tracer before passing the results to AbstractGWDTTracer.traceMultiSoma(List). Example:

      
       List<SomaResult> somas = SomaUtils.detectSomasAt(imp, rois);
       tracer.setAutoFilter(false);
       List<Tree> trees = tracer.traceMultiSoma(somas);
       
      Parameters:
      imp - the source image (ImagePlus)
      rois - ROIs whose centroids serve as soma seeds
      Returns:
      list of successfully detected SomaResults, sorted by radius (largest first)
      See Also:
    • detectAllSomas

      public static List<SomaUtils.SomaResult> detectAllSomas(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, double threshold, double minRadius)
      Detects all somas using EDT local maxima approach. Finds local maxima in the distance transform - these correspond to centers of thick structures (somas), not thin structures (neurites).
      Parameters:
      source - input image (2D)
      threshold - intensity threshold. Use -1 for Otsu, NaN for mean.
      minRadius - minimum soma radius in voxels to include (filters small debris)
      Returns:
      list of SomaResult, sorted by radius (largest first); empty list if none found
    • detectAllSomas

      public static List<SomaUtils.SomaResult> detectAllSomas(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, double threshold, double minRadius, double minSomaDistance)
      Detects all somas in a 2D image using EDT + local maxima + NMS.

      Pipeline: threshold → binary mask → EDT → local maxima (with minRadius filter) → non-maximum suppression (with minSomaDistance) → flood fill for each maximum → SomaResult.

      Parameters:
      source - input image (2D)
      threshold - intensity threshold. Use -1 for Otsu, NaN for mean.
      minRadius - minimum soma radius in voxels to include
      minSomaDistance - minimum distance (in voxels) between soma centers. If > 0, non-maximum suppression is applied to eliminate clusters of spurious detections. Should reflect the minimum known distance between real somas in the image.
      Returns:
      list of SomaResult, sorted by radius (largest first); empty list if none found
    • detectAllSomas

      public static List<SomaUtils.SomaResult> detectAllSomas(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, double threshold)
      Detects all somas using default minimum radius.
      Parameters:
      source - input image (2D)
      threshold - intensity threshold. Use -1 for Otsu, NaN for mean.
      Returns:
      list of SomaResult, sorted by radius (largest first)
    • detectAllSomas

      public static List<SomaUtils.SomaResult> detectAllSomas(net.imagej.ImgPlus<?> source, double threshold, int zSlice, double minRadius)
      Detects all somas using ImgPlus with automatic spacing.
      Parameters:
      source - input image (2D or 3D ImgPlus)
      threshold - intensity threshold. Use -1 for Otsu, NaN for mean.
      zSlice - Z-slice to use (0-indexed), or -1 for automatic detection. When -1 and the image is 3D, detection runs on a max-intensity projection and Z is resolved per soma from the peak intensity in the original stack. When ≥ 0, detection runs on that single Z-plane only. Ignored for 2D images.
      minRadius - minimum soma radius in voxels
      Returns:
      list of SomaResult, sorted by radius (largest first)
    • detectAllSomas

      public static List<SomaUtils.SomaResult> detectAllSomas(net.imagej.ImgPlus<?> source, double threshold, int zSlice, double minRadius, double minSomaDistance)
      Detects all somas using ImgPlus with automatic spacing and NMS.

      For 3D images, the behavior depends on zSlice:

      • zSlice ≥ 0: detection runs on the specified Z-plane only (useful for interactive GUI where the user is viewing a specific plane)
      • zSlice < 0: a max-intensity projection (MIP) is computed and soma (x, y) centers are detected on it. For each detected soma, the Z coordinate is then resolved independently by finding the Z-plane with the peak intensity at that (x, y) column. This allows detection of somas spread across different Z-planes without requiring the user to specify one.
      For 2D images, zSlice is ignored.
      Parameters:
      source - input image (2D or 3D ImgPlus)
      threshold - intensity threshold. Use -1 for Otsu, NaN for mean.
      zSlice - Z-slice (0-indexed), or -1 for automatic MIP-based detection. See above.
      minRadius - minimum soma radius in voxels
      minSomaDistance - minimum distance (in voxels) between soma centers for non-maximum suppression. If ≤ 0, NMS is skipped.
      Returns:
      list of SomaResult, sorted by radius (largest first)
    • detectAllSomas

      public static List<SomaUtils.SomaResult> detectAllSomas(net.imagej.ImgPlus<?> source)
      Detects all somas using ImgPlus with default settings.
      Parameters:
      source - input image (2D or 3D ImgPlus)
      Returns:
      list of SomaResult, sorted by radius (largest first)
    • selectTopSomasByThickness

      public static <T extends net.imglib2.type.numeric.RealType<T>> List<SomaUtils.SomaResult> selectTopSomasByThickness(List<SomaUtils.SomaResult> somas, net.imglib2.RandomAccessibleInterval<T> source, int n)
      Selects the top-N somas by EDT thickness (distance to nearest background pixel at each soma's center), ranking by descending EDT value.

      Experimental. Known limitations: The EDT is computed from a binary mask obtained by applying the Minimum auto-threshold to the source image (see computeEdtAtSomaCenters(java.util.List<sc.fiji.snt.tracing.auto.SomaUtils.SomaResult>, net.imglib2.RandomAccessibleInterval<T>)). For images with large connected foreground regions (common in compressed formats like JPEG, or images with dense neuropil), the EDT at a point measures the distance to the nearest below-threshold pixel — not the local soma body half-width. False detections located deep inside such regions can receive artificially high EDT values (hundreds of pixels), ranking higher than real somas whose EDT only reflects the soma's actual radius (~15-20 px). In testing, this caused 4 of 5 selected somas to be false detections.

      For reliable soma selection, prefer using AbstractGWDTTracer.setMinSomaDistance(double) instead, which drives standard NMS and consolidation without depending on global EDT.

      Type Parameters:
      T - pixel type
      Parameters:
      somas - list of detected somas
      source - the original source image (2D), used for EDT computation
      n - number of somas to keep (must be ≥ 1)
      Returns:
      the top-N somas sorted by EDT thickness (highest first), or the original list if n >= somas.size() or inputs are invalid
      See Also:
    • filterSomasByThickness

      public static <T extends net.imglib2.type.numeric.RealType<T>> List<SomaUtils.SomaResult> filterSomasByThickness(List<SomaUtils.SomaResult> somas, net.imglib2.RandomAccessibleInterval<T> source)
      Filters a list of detected somas by their local EDT thickness, using Otsu's method on the EDT value distribution to separate thick (real soma) from thin (artifact) detections.

      The method computes an EDT using the Minimum auto-threshold for binarization (see computeEdtAtSomaCenters(java.util.List<sc.fiji.snt.tracing.auto.SomaUtils.SomaResult>, net.imglib2.RandomAccessibleInterval<T>)), samples the EDT value at each soma center, then applies a second Otsu threshold on those sampled values. Somas with EDT above the second Otsu are kept.

      Experimental: known limitations: This method shares the same fundamental limitation as selectTopSomasByThickness(java.util.List<sc.fiji.snt.tracing.auto.SomaUtils.SomaResult>, net.imglib2.RandomAccessibleInterval<T>, int): the EDT depends on a global binarization threshold, which may not produce meaningful local thickness measurements for images with large connected foreground regions. The second Otsu (on the EDT values themselves) partially compensates: it can separate the bimodal distribution of "high EDT at false detections deep inside foreground" from "low EDT at artifacts near boundaries": but the resulting threshold is image- dependent and may be too aggressive (filtering out real somas) or too lenient (keeping false detections). In testing with a JPEG image, this method reduced 495 detections to 18, losing 1 of 5 real somas.

      Used internally by the auto-estimation branch of AbstractGWDTTracer.traceMultiSoma(List) when neither nSomas nor minSomaDistance is specified.

      Type Parameters:
      T - pixel type
      Parameters:
      somas - list of detected somas (at least 2 for meaningful filtering)
      source - the original source image used for detection (2D)
      Returns:
      filtered list containing only somas with EDT thickness above Otsu's threshold; returns the original list if filtering is not applicable or produces degenerate results
      See Also:
    • filterSomasByIntensity

      public static <T extends net.imglib2.type.numeric.RealType<T>> List<SomaUtils.SomaResult> filterSomasByIntensity(List<SomaUtils.SomaResult> somas, net.imglib2.RandomAccessibleInterval<T> source)
      Filters a list of detected somas by sampling the source image intensity at each soma center and applying Otsu's threshold to separate real (bright) somas from false detections (dim).

      Note: for JPEG images, intensity alone may not discriminate well because compression artifacts can create bright spots. Prefer filterSomasByThickness(java.util.List<sc.fiji.snt.tracing.auto.SomaUtils.SomaResult>, net.imglib2.RandomAccessibleInterval<T>) which uses geometric thickness (EDT) as the discriminator.

      Type Parameters:
      T - pixel type
      Parameters:
      somas - list of detected somas (at least 2 for meaningful filtering)
      source - the original source image used for detection (2D)
      Returns:
      filtered list containing only somas with center intensity above Otsu's threshold; returns the original list if filtering is not applicable (fewer than 2 somas, or Otsu produces degenerate threshold)
    • estimateMinSomaDistance

      public static double estimateMinSomaDistance(List<SomaUtils.SomaResult> somas)
      Estimates the minimum inter-soma distance from a list of detected somas using single-linkage hierarchical clustering with gap analysis.

      This overload does not filter by intensity and operates directly on the provided soma list. For images with many false detections (e.g., JPEG artifacts), prefer estimateMinSomaDistance(List, RandomAccessibleInterval) which pre-filters somas by intensity before clustering.

      Parameters:
      somas - list of detected somas (at least 3 required)
      Returns:
      estimated minimum distance between real soma centers (in voxels), or 0 if fewer than 3 somas or no clear gap is found
      See Also:
    • estimateMinSomaDistance

      public static <T extends net.imglib2.type.numeric.RealType<T>> double estimateMinSomaDistance(List<SomaUtils.SomaResult> somas, net.imglib2.RandomAccessibleInterval<T> source)
      Estimates the minimum inter-soma distance using a hybrid approach: EDT-thickness filtering followed by spatial gap analysis.

      Pipeline:

      1. Thickness filter (experimental): recompute EDT from source using the Minimum auto-threshold, sample EDT at each soma center, apply Otsu on those values to separate thick from thin detections, see filterSomasByThickness(java.util.List<sc.fiji.snt.tracing.auto.SomaUtils.SomaResult>, net.imglib2.RandomAccessibleInterval<T>)
      2. Spatial gap analysis: run single-linkage hierarchical clustering on the surviving somas, find the largest ratio gap in merge heights, return the geometric mean of the gap boundaries

      Experimental: The quality of the estimate depends heavily on step 1 (thickness filtering), which has known limitations for images with large connected foreground regions, see filterSomasByThickness(java.util.List<sc.fiji.snt.tracing.auto.SomaUtils.SomaResult>, net.imglib2.RandomAccessibleInterval<T>) javadoc. The gap analysis in step 2 is well-founded (standard hierarchical clustering), but is only as good as the input somas it receives.

      Type Parameters:
      T - pixel type
      Parameters:
      somas - list of detected somas (at least 3 required)
      source - the original source image, used for EDT computation
      Returns:
      estimated minimum distance between real soma centers (in voxels), or 0 if estimation fails
      See Also:
    • floodFillSoma

      public static net.imglib2.img.Img<net.imglib2.type.logic.BitType> floodFillSoma(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source, long seedX, long seedY, double threshold)
      Creates a binary mask of the soma region using flood fill from seed point.
      Parameters:
      source - the input image (2D)
      seedX - seed X coordinate (voxels)
      seedY - seed Y coordinate (voxels)
      threshold - pixels above this value are considered foreground
      Returns:
      binary mask where TRUE = soma region, or null if seed is in background
    • extractContour

      public static Polygon extractContour(net.imglib2.img.Img<net.imglib2.type.logic.BitType> mask)
      Extracts the boundary contour from a binary mask using Moore boundary tracing.
      Parameters:
      mask - binary mask (TRUE = foreground)
      Returns:
      polygon contour, or null if mask is empty
    • computeMaskCentroid

      public static double[] computeMaskCentroid(net.imglib2.img.Img<net.imglib2.type.logic.BitType> mask, double[] spacing)
      Computes the centroid of a binary mask.
      Parameters:
      mask - binary mask
      spacing - voxel spacing [x, y] for physical coordinates, or null for voxel coords
      Returns:
      centroid as [x, y], or null if mask is empty
    • computeMaskArea

      public static double computeMaskArea(net.imglib2.img.Img<net.imglib2.type.logic.BitType> mask, double[] spacing)
      Computes the area of a binary mask.
      Parameters:
      mask - binary mask
      spacing - voxel spacing [x, y], or null for voxel count
      Returns:
      area in physical units squared, or voxel count if spacing is null
    • computeOtsuThreshold

      public static double computeOtsuThreshold(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source)
      Computes Otsu's threshold using ImageJ Ops.
      Parameters:
      source - the input image
      Returns:
      Otsu threshold value
    • computeMinimumThreshold

      public static double computeMinimumThreshold(net.imglib2.RandomAccessibleInterval<? extends net.imglib2.type.numeric.RealType<?>> source)
      Computes the Minimum auto-threshold of the given image. The Minimum method finds the valley between two peaks in the histogram, making it more restrictive than Otsu for images with large bright regions.
      Parameters:
      source - the input image
      Returns:
      Minimum threshold value
    • roiToSomaPath

      public static Path roiToSomaPath(ij.gui.Roi roi, Path referencePath)
      Creates a single-node soma Path from an ImageJ ROI using calibration from a reference Path.
      Parameters:
      roi - the ROI to convert (must not be null)
      referencePath - a Path from which to extract spacing and units (may be null for pixel units)
      Returns:
      a single-node soma path, or null if ROI is null
      See Also:
    • roiToSomaPath

      public static Path roiToSomaPath(ij.gui.Roi roi, double[] spacing)
      Creates a single-node soma Path from an ImageJ ROI.

      Converts any ROI to a soma path centered at the ROI's centroid. For area ROIs (polygon, oval, freehand, etc.), the radius is estimated from the equivalent circle area. For non-area ROIs (point, line), no radius is assigned.

      Parameters:
      roi - the ROI to convert (must not be null)
      spacing - voxel spacing [x, y, z] for physical coordinates, or null for pixel units
      Returns:
      a single-node soma path, or null if ROI is null