Class SeedOverlay

java.lang.Object
sc.fiji.snt.seed.SeedOverlay

public class SeedOverlay extends Object
Transient, in-memory store of SeedPoints used to render candidate tracing seeds (e.g., the output of a deep-learning point detector) on SNT's canvas and to feed them to downstream consumers (autotracers, click-to-trace anchors).

Lifecycle: not persisted with the .traces file. Cleared when the active image changes (see SNT.initialize(ij.ImagePlus)). Users may import additional CSVs (with ImportSeedPointsCmd "Import Seed Points (CSV)…" or another command) at any time. Headless/CLI callers that do not need unit conversion or import guardrails can instead read a CSV directly via loadCsv(File, boolean).

Threading: intended to be accessed from the Swing EDT (panel UI, canvas paint). Bulk loaders should use addAll(Collection) to trigger a single listener fire and a single spatial-index rebuild.

Spatial queries: nearest(double, double, double, double) uses a lazily-built KD-tree from Smile. The tree is invalidated by any mutating call; threshold/visibility changes do not invalidate it (queries are not threshold-aware by default: callers should pre-filter via filtered() if threshold-aware nearest-neighbor is required).

Author:
Tiago Ferreira
See Also:
  • Field Details

  • Constructor Details

    • SeedOverlay

      public SeedOverlay()
  • Method Details

    • size

      public int size()
      Returns:
      the number of seeds currently held (irrespective of threshold).
    • isEmpty

      public boolean isEmpty()
      Returns:
      true if no seeds are held.
    • countOutOfBounds

      public int countOutOfBounds(long[] dims, double[] spacing, double[] offset)
      Counts seeds whose voxel coordinates fall outside the given image bounds.

      Coordinates are interpreted as physical (calibrated) world units. Per SNT#getWorldOriginOffset()'s (world = voxelIndex * spacing + offset), offset is subtracted before dividing by spacing to recover the voxel index - omitting it misreports every seed as out-of-bounds whenever the tethered image/source is not anchored at world (0,0,0), regardless of how much of the source is currently materialized. A seed is considered out-of-bounds when its rounded voxel index is negative or ≥ the dimension on any axis. The z-axis is only checked when dims.length >= 3.

      Parameters:
      dims - image dimensions in voxels (length 2 for 2D, 3 for 3D); if null or length < 2, returns 0
      spacing - pixel size per axis in physical units; should match dims length. null returns 0
      offset - world origin offset per axis (see SNT#getWorldOriginOffset()); null or too short is treated as all-zero (i.e., world == pixel * spacing)
      Returns:
      number of seeds outside the image bounds
    • visibleSize

      public int visibleSize()
      Returns:
      the number of seeds whose confidence falls in [lowConfidence, highConfidence].
    • add

      public void add(SeedPoint seed)
      Adds a single seed. Fires listeners and invalidates the spatial index. Prefer addAll(Collection) for batches.
    • addAll

      public void addAll(Collection<? extends SeedPoint> batch)
      Bulk-adds seeds. Fires listeners once at the end and invalidates the spatial index once.
      Parameters:
      batch - seeds to append; ignored if null or empty
    • replaceAll

      public void replaceAll(Collection<? extends SeedPoint> replacement)
      Replaces the current contents with the given seeds. Equivalent to clear() followed by addAll(Collection), but only fires listeners and rebuilds the spatial index once.
      Parameters:
      replacement - the new contents (may be null/empty, which behaves like clear())
    • clear

      public void clear()
      Removes all seeds. Fires listeners.
    • remove

      public boolean remove(SeedPoint seed)
      Removes a single seed by reference equality. Selection is updated. Fires listeners and invalidates indices if the seed was present.
      Returns:
      true if the seed was present and removed
    • removeAll

      public int removeAll(Collection<? extends SeedPoint> batch)
      Bulk-removes seeds by reference equality. Fires listeners once at the end if anything was removed.
      Returns:
      the number of seeds actually removed
    • removeAt

      public SeedPoint removeAt(int index)
      Removes the seed at the given (data-list) index. Fires listeners.
      Returns:
      the removed seed, or null if the index was out of range
    • replaceAt

      public boolean replaceAt(int index, SeedPoint replacement)
      Replaces the seed at the given index. If replacement is the same reference as the existing seed, this is a no-op. Selection is preserved (the new seed inherits the selection state of the old one). Fires listeners on actual change.
      Returns:
      true on success, false if the index was out of range or the replacement was null or identical
    • replaceAllAt

      public int replaceAllAt(Map<Integer,SeedPoint> replacements)
      Bulk-replaces seeds at multiple positions, firing listeners and invalidating the spatial index once at the end. Entries with out-of-range indices or null replacements are silently skipped.
      Parameters:
      replacements - map of (model-index, new-seed). null or empty input is a no-op.
      Returns:
      the number of slots actually mutated
    • indexOf

      public int indexOf(SeedPoint seed)
      Returns the index of seed in the data list, or -1 if absent. Reference identity (via List.indexOf(java.lang.Object)) is used.
    • scaleConfidence

      public int scaleConfidence(Collection<SeedPoint> seeds, double factor)
      Multiplies the confidence of seeds by factor, clamping each result to [0, 1]. A SeedPoint.confidence of NaN ("no basis to judge", see SeedConfidence) is left as NaN since it fails both clamp comparisons. Seeds not present in the data list (e.g. selected then removed elsewhere) are silently skipped. Fires listeners once via replaceAllAt(Map).
      Parameters:
      seeds - seeds to rescale, typically a table selection
      factor - confidence multiplier, e.g. 0.9 to decrease by 10%, 1.1 to increase by 10%
      Returns:
      the number of seeds actually rescaled
    • scaleRadius

      public int scaleRadius(Collection<SeedPoint> seeds, double factor)
      Multiplies the physical radius of seeds by factor, clamping each result to >= 0 (radius has no upper bound, unlike confidence). Seeds not present in the data list are silently skipped. Fires listeners once via replaceAllAt(Map).
      Parameters:
      seeds - seeds to rescale, typically a table selection
      factor - radius multiplier, e.g. 0.9 to decrease by 10%, 1.1 to increase by 10%
      Returns:
      the number of seeds actually rescaled
    • getSelectedSeeds

      public Set<SeedPoint> getSelectedSeeds()
      Returns:
      an unmodifiable, insertion-ordered view of the currently selected seeds. The result is a snapshot (independent collection).
    • isSelected

      public boolean isSelected(SeedPoint seed)
      Returns:
      true if seed is currently selected.
    • setSelectedSeeds

      public void setSelectedSeeds(Collection<? extends SeedPoint> selection)
      Replaces the selection set. Seeds not present in the data list are silently ignored. Fires listeners if the resulting selection differs.
    • clearSelection

      public void clearSelection()
      Clears the selection. Fires listeners if anything was previously selected.
    • removeSelected

      public int removeSelected()
      Removes all currently selected seeds from the data list.
      Returns:
      the number of seeds removed (0 if nothing was selected)
    • get

      public SeedPoint get(int index)
      Returns:
      seed at index (0-based).
    • list

      public List<SeedPoint> list()
      Returns a defensive snapshot of all held seeds (a fresh ArrayList, safe to iterate while the overlay continues to mutate on another thread).
      Returns:
      a freshly allocated list snapshot
    • filtered

      public List<SeedPoint> filtered()
      Returns a new list of seeds whose confidence falls in [lowConfidence, highConfidence]. O(N); the result is a snapshot, not a live view.
    • topKByConfidence

      public List<SeedPoint> topKByConfidence(int k)
      Returns up to k seeds from the visible range ([lowConfidence, highConfidence]) with the highest confidence. The result is a snapshot (independent list). Internally uses a cached sort that is rebuilt only when the overlay's data mutates.
      Parameters:
      k - maximum number of seeds to return; values <= 0 return an empty list
      Returns:
      up to k seeds sorted by descending confidence
    • getLowConfidence

      public double getLowConfidence()
      Returns:
      the lower bound of the visible confidence range, in [0, 1].
    • getHighConfidence

      public double getHighConfidence()
      Returns:
      the upper bound of the visible confidence range, in [0, 1].
    • setConfidenceRange

      public void setConfidenceRange(double low, double high)
      Sets the visible confidence range. Values are clamped to [0, 1]; if low > high the bounds are swapped. Fires listeners if either bound changed.
    • getTransparency

      public double getTransparency()
      Returns:
      the current global transparency multiplier in [0, 1]. 1.0 = fully opaque.
    • setTransparency

      public void setTransparency(double t)
      Sets the global transparency multiplier (clamped to [0, 1]). Fires listeners if the value changed.
    • getColorMode

      public SeedOverlay.ColorMode getColorMode()
      Returns:
      how seed LUT slots are picked at render time. Never null; defaults to SeedOverlay.ColorMode.CONFIDENCE.
    • setColorMode

      public void setColorMode(SeedOverlay.ColorMode mode)
      Sets the rendering color mode. Fires listeners if the value changed. null is treated as SeedOverlay.ColorMode.CONFIDENCE.
    • getColorTable

      public net.imglib2.display.ColorTable getColorTable()
      Returns:
      the active LUT for confidence-to-color mapping. Never null.
    • getColorTableName

      public String getColorTableName()
      Returns:
      the canonical name of the active LUT (e.g. "Viridis").
    • setColorTable

      public void setColorTable(String name)
      Sets the active LUT. If name is not recognised by ColorMaps.get(String), this is a no-op. Fires listeners on success.
    • getUnknownConfidenceColor

      public Color getUnknownConfidenceColor()
      Returns:
      the fallback color used for NaN-confidence seeds in SeedOverlay.ColorMode.CONFIDENCE mode. Never null.
    • setUnknownConfidenceColor

      public void setUnknownConfidenceColor(Color color)
      Sets the fallback color used for NaN-confidence seeds in SeedOverlay.ColorMode.CONFIDENCE mode. null resets to default. Fires listeners on success.
    • isVisible

      public boolean isVisible()
      Returns:
      true if seeds should be drawn on the canvas.
    • setVisible

      public void setVisible(boolean visible)
      Sets visibility; fires listeners if the value changed.
    • nearest

      public SeedPoint nearest(double x, double y, double z, double maxDistance)
      Returns the seed closest to (x, y, z) in physical units, or null if the overlay is empty or no seed lies within maxDistance.

      Note: this query does not filter by confidence threshold. Use filtered() and search that list manually if threshold-aware nearest-neighbor is required.

      Parameters:
      x - query physical X
      y - query physical Y
      z - query physical Z (use 0 for 2D)
      maxDistance - maximum acceptable distance in physical units; pass Double.POSITIVE_INFINITY to disable
      Returns:
      the nearest seed, or null
    • saveAs

      public void saveAs(File file) throws IOException
      Writes all held seeds to a CSV file with the canonical header x,y,z,confidence,radius. Channel/frame are written only if any seed has them set (extra columns appended).
      Parameters:
      file - destination file (will be overwritten)
      Throws:
      IOException - on write failure
    • parseCsv

      Parses a seed CSV with header x,y,z,confidence,radius (plus optional channel,frame,type,source), assuming coordinates are already in physical (image-calibrated) units. Callers needing voxel to physical conversion (e.g. ImportSeedPointsCmd) should convert the returned seeds themselves before calling addAll(Collection) or replaceAll(Collection). Use loadCsv(File, boolean) for the common case of physical-unit CSVs
      Parameters:
      file - the CSV file to read
      Returns:
      the parsed seeds and the number of skipped rows
      Throws:
      IOException - if the file cannot be read
      SeedOverlay.CsvHeaderException - if a required column is missing
      See Also:
    • parseCsv

      public static SeedOverlay.CsvImportResult parseCsv(String filePathOrURL) throws IOException, SeedOverlay.CsvHeaderException
      String/URL counterpart of parseCsv(File), for script-friendly callers and remote CSVs. Local paths and remote URLs (e.g. https://.../seeds.csv) are both accepted; a remote URL is downloaded to a temporary local file first (see SNTUtils.downloadToTempFile(String))
      Parameters:
      filePathOrURL - local path or remote URL to a seed CSV
      Returns:
      the parsed seeds and the number of skipped rows
      Throws:
      IOException - if the file/URL cannot be read
      SeedOverlay.CsvHeaderException - if a required column is missing
    • loadCsv

      public SeedOverlay.CsvImportResult loadCsv(File file, boolean replace) throws IOException, SeedOverlay.CsvHeaderException
      Parses file via parseCsv(File) and inserts the result into this overlay. Coordinates are assumed to already be in physical units; voxel-indexed CSVs need unit conversion first, so parse them with parseCsv(File) and insert the (converted) seeds via addAll(Collection)/replaceAll(Collection) instead
      Parameters:
      file - the CSV file to read
      replace - if true, replaces the current seeds; if false, appends
      Returns:
      the parse result (seeds inserted, plus skipped-row count)
      Throws:
      IOException - if the file cannot be read
      SeedOverlay.CsvHeaderException - if a required column is missing
    • loadCsv

      public SeedOverlay.CsvImportResult loadCsv(String filePathOrURL, boolean replace) throws IOException, SeedOverlay.CsvHeaderException
      Throws:
      IOException
      SeedOverlay.CsvHeaderException
      See Also:
    • addListener

      public void addListener(SeedOverlay.SeedOverlayListener listener)
      Registers a listener (no-op if already registered).
    • removeListener

      public void removeListener(SeedOverlay.SeedOverlayListener listener)
      Removes a listener (no-op if not registered).