-
Notifications
You must be signed in to change notification settings - Fork 82
Open
Labels
investigateAssignee should verify the issue and try to reproduce it.Assignee should verify the issue and try to reproduce it.
Description
Script writen in Jython
#@ String(label="File Path", required=False) input_path
#@ ImageJ ij
import os
import sys
from ij import IJ
from fiji.plugin.trackmate import Logger, Settings, Model, TrackMate
from fiji.plugin.trackmate.detection import LabelImageDetectorFactory
from fiji.plugin.trackmate.tracking.overlap import OverlapTrackerFactory
from fiji.plugin.trackmate.action import LabelImgExporter
from fiji.plugin.trackmate.features import FeatureFilter
from fiji.plugin.trackmate.features.track import TrackDurationAnalyzer, TrackBranchingAnalyzer
# Import the Enum class for label painting
from fiji.plugin.trackmate.action.LabelImgExporter import LabelIdPainting
# --- SETTINGS ---
IOU_THRESHOLD = 0.2
SCALE_FACTOR = 1.0
MIN_TRACK_DURATION = 5
MIN_SPLIT_EVENTS = 1
# Handle potential UTF-8 encoding issues in Fiji's Jython
reload(sys)
sys.setdefaultencoding('utf-8')
def process_image(imp):
if imp is None:
return
# --- Dimensions Fix ---
stack_size = imp.getStackSize()
if imp.getNSlices() > 1 and imp.getNFrames() == 1:
IJ.log(" [Fix] Converting Stack Z-slices to Time-frames...")
imp.setDimensions(1, 1, stack_size)
imp.setOpenAsHyperStack(True)
# 1. Setup
model = Model()
model.setLogger(Logger.IJ_LOGGER)
settings = Settings(imp)
# 2. Detector (Label Image)
settings.detectorFactory = LabelImageDetectorFactory()
settings.detectorSettings = {
'TARGET_CHANNEL': 1,
'SIMPLIFY_CONTOURS': False
}
# 3. Tracker (Overlap)
settings.trackerFactory = OverlapTrackerFactory()
settings.trackerSettings = settings.trackerFactory.getDefaultSettings()
settings.trackerSettings['MIN_IOU'] = float(IOU_THRESHOLD)
settings.trackerSettings['SCALE_FACTOR'] = float(SCALE_FACTOR)
# 4. Analyzers
settings.addAllAnalyzers()
# 5. Run Initial Processing
trackmate = TrackMate(model, settings)
if not trackmate.checkInput() or not trackmate.process():
IJ.log("[Error] TrackMate failed: " + str(trackmate.getErrorMessage()))
return
# =========================================================
# EXPORT 1: DURATION FILTER
# =========================================================
settings.getTrackFilters().clear()
filter_duration = FeatureFilter('TRACK_DURATION', float(MIN_TRACK_DURATION), True)
settings.addTrackFilter(filter_duration)
trackmate.execTrackFiltering(True)
IJ.log(" [Filter 1] Duration >= " + str(MIN_TRACK_DURATION))
IJ.log(" Tracks kept: " + str(model.getTrackModel().nTracks(True)))
export_labels(imp, trackmate, suffix="_Tracked")
# =========================================================
def export_labels(imp, trackmate, suffix):
try:
# Use LABEL_IS_TRACK_ID via class reference for Lineage Color consistency
paint_strategy = LabelIdPainting.LABEL_IS_TRACK_ID
exportSpotsAsDots = False
exportTracksOnly = True
# Calling static method directly
tracked_imp = LabelImgExporter.createLabelImagePlus(trackmate, exportSpotsAsDots, exportTracksOnly, paint_strategy)
except Exception as e:
IJ.log(" [Error] Export API failed: " + str(e))
return
if tracked_imp:
file_info = imp.getOriginalFileInfo()
folder = file_info.directory if file_info else IJ.getDirectory("current")
name = file_info.fileName if file_info else imp.getTitle()
base_name = os.path.splitext(name)[0].replace("_CleanSeg", "")
output_name = base_name + suffix + ".tif"
save_path = os.path.join(folder, output_name)
tracked_imp.setTitle(output_name)
IJ.saveAs(tracked_imp, "Tiff", save_path)
IJ.log(" [Success] Saved: " + output_name)
else:
IJ.log(" [Warn] No tracks passed filters for " + suffix)
So when automating a first round of tracking with Trackmate I encountered this issue. Possibly common knowledge, but it was not obvious to me so I decided to report it.
If a spot is filtered out by a Track filter, in this example a simple Track_duration filter = 5 (mins). Combining LabelIdPainting.LABEL_IS_TRACK_ID with exportTracksOnly = True resulted in some labels with a negative index.
This was fixed by turning exportTracksOnly = False, which made spots filtered out by a track filter behave as described:
"The spot label is the ID of the track it belongs to, plus one (+1). "
+ "Spots that do not belong to tracks are painted with a unique integer "
+ "larger than the last trackID in the dataset." ),
However, I did not find any documentation pertaining to this funky interaction, so I am leaving here the report.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
investigateAssignee should verify the issue and try to reproduce it.Assignee should verify the issue and try to reproduce it.