Filter spots in TrackMate via scripting

Hi @tinevez,

As discussed, here’s the new post :wink:

I have a function where I’m using TrackMate to find the peaks in 3D objects to count number of objects. This is the function:

def count_cellDetection3D(implus, rad, thresh, subpix, med):
    """Function to detect the cells in 3D using TrackMate

    Arguments:
        implus {imagePlus} -- ImagePlus of the image to use for detection
        rad    {int}       -- Radius of the cell to detect, half the diameter
        thresh {int}       -- Intensity threshold for the detection
        subpix {bool}      -- Option for subpixel detection
        med {bool}         -- Option for median filter before detection

    Returns:
        cellCount {int} -- Number of cells found
    """
    dim = implus.getDimensions()
    cal = implus.getCalibration()

    implus2 = implus.duplicate()

    # Set the parameters for LogDetector
    img           = ImageJFunctions.wrap(implus2)
    interval      = img
    # cal           = implus.getCalibration()
    # calibration = [round(cal.pixelWidth,3), round(cal.pixelHeight,3), round(cal.pixelDepth,3)]
    calibration   = [cal.pixelWidth, cal.pixelHeight, cal.pixelDepth]

    radius     = rad  # the radius is half the diameter
    threshold  = thresh
    doSubpixel = subpix
    doMedian   = med

    # print cal.pixelDepth

    # Setup spot detector (see http://javadoc.imagej.net/Fiji/fiji/plugin/trackmate/detection/LogDetector.html)
    #
    # public LogDetector(RandomAccessible<T> img,
    #            Interval interval,
    #            double[] calibration,
    #            double radius,
    #            double threshold,
    #            boolean doSubPixelLocalization,
    #            boolean doMedianFilter)

    detector = LogDetector(img, interval, calibration, radius,
                           threshold, doSubpixel, doMedian)

    # Start processing and display the results
    if detector.process():
        # Get the list of peaks found
        peaks = detector.getResult()
        # print str(len(peaks)), "peaks were found."

        # Add points to ROI manager
        rm = RoiManager.getInstance()
        if not rm:
            rm = RoiManager()
        rm.reset()

        # Loop through all the peak that were found
        for peak in peaks:
            # Print the current coordinates
            # print peak.getDoublePosition(0), peak.getDoublePosition(1), peak.getDoublePosition(2)
            # Add the current peak to the Roi manager
            roi = PointRoi(peak.getDoublePosition(0) / cal.pixelWidth,
                           peak.getDoublePosition(1) / cal.pixelHeight)
            # print peak.getDoublePosition(2)/cal.pixelDepth
            roi.setPosition(
                int(round(peak.getDoublePosition(2) / cal.pixelDepth)) + 1)
            rm.addRoi(roi)
        # Show all ROIs on the image
        # rm.runCommand(imp2, "Show All")
        cellCount = rm.getCount()
        # Close the duplicate
        implus2.changes = False
        implus2.close()
    else:
        print "The detector could not process the data."
    return cellCount

As you can see from this code, there’s no Spots but I would still like to use some of the intensity filters that the GUI offers to only find the peak maximas corresponding to my objects. Is there a simple way using this function ?

Thank you very much.

Hello @lguerard

You cannot access directly the intensity with your script. BUT!
Actually the peaks variable in your script is made of TrackMate Spots.

So each element in this list is a Spot and it has a quality value.

For the LoGDetector, the quality value corresponds to the intensity in the LoG-filtered image at spot location. Maybe it can be used for what you wan to do?

1 Like

Oh great ! I didn’t even try but good to know ! I’ll have a look at it on Monday !

Can I also use the Mean Intensity value to filter out objects ? Some objects that TrackMate is detecting are super bright and we would like to avoid them by setting a below mean intensity filter which works great using the GUI.

Not simply with your script.
At this stage, I would recommend using TrackMate in your scrip and let it handle the mean intensity calculation. You can just adapt the TrackMate Jython script example https://imagej.net/Scripting_TrackMate#A_full_example with a single time-point movie.

Hello again,

I tried adapting the script with the FeatureFilter to only keep the spots I want. The logger tells me that it finds as many points as the GUI. But then after filtering I get an error telling me The Spot Collector is empty.

Am I missing something from this function ?

def runTM(imp, rad, thresh, subpix, med, mean_int):

    #----------------------------
    # Create the model object now
    #----------------------------
        
    # Some of the parameters we configure below need to have
    # a reference to the model at creation. So we create an
    # empty model now.
        
    model = Model()
        
    # Send all messages to ImageJ log window.
    model.setLogger(Logger.IJ_LOGGER)
        
        
        
    #------------------------
    # Prepare settings object
    #------------------------
        
    settings = Settings()
    settings.setFrom(imp)
        
    # Configure detector - We use the Strings for the keys
    settings.detectorFactory = LogDetectorFactory()
    settings.detectorSettings = { 
        'DO_SUBPIXEL_LOCALIZATION' : subpix,
        'RADIUS' : rad,
        'TARGET_CHANNEL' : 1,
        'THRESHOLD' : thresh,
        'DO_MEDIAN_FILTERING' : med,
    }  

    # Add the filter on mean intensity
    # Here 'false' takes everything BELOW the mean_int value
    filter1 = FeatureFilter('MEAN_INTENSITY', mean_int, False)
    settings.addSpotFilter(filter1)
    
    # Configure tracker - We want to allow merges and fusions
    settings.trackerFactory = SparseLAPTrackerFactory()
    settings.trackerSettings = LAPUtils.getDefaultLAPSettingsMap() # almost good enough
    # settings.trackerSettings['ALLOW_TRACK_SPLITTING'] = True
    # settings.trackerSettings['ALLOW_TRACK_MERGING'] = True

    # # Configure track analyzers - Later on we want to filter out tracks 
    # # based on their displacement, so we need to state that we want 
    # # track displacement to be calculated. By default, out of the GUI, 
    # # not features are calculated. 
        
    # # The displacement feature is provided by the TrackDurationAnalyzer.
        
    # settings.addTrackAnalyzer(TrackDurationAnalyzer())
        
    # # Configure track filters - We want to get rid of the two immobile spots at 
    # # the bottom right of the image. Track displacement must be above 10 pixels.
        
    # filter2 = FeatureFilter('TRACK_DISPLACEMENT', 10.0, False)
    # settings.addTrackFilter(filter2)

    print(str(settings))
        
    
    #-------------------
    # Instantiate plugin
    #-------------------
        
    trackmate = TrackMate(model, settings)
        
    #--------
    # Process
    #--------
        
    ok = trackmate.checkInput()
    if not ok:
        sys.exit(str(trackmate.getErrorMessage()))
        
    ok = trackmate.process()
    if not ok:
        sys.exit(str(trackmate.getErrorMessage()))

    print model.getSpots().getNSpots(True)

Thanks a lot ! :slight_smile:

EDIT: Here is the result of print(str(settings))

Image data:
For the image named: DUP_3004_12_sec13_2xzoom_1.tif.
Matching file 3004_12_sec13_2xzoom_1.tif in current folder.
Geometry:
  X =    0 -  138, dx = 0.156292
  Y =    0 -  144, dy = 0.156292
  Z =    0 -   17, dz = 0.396035
  T =    0 -    0, dt = 1.00000

Spot detection:
Detector: fiji.plugin.trackmate.detection.LogDetectorFactory@7ddd67bf.
Detector settings:
{'DO_SUBPIXEL_LOCALIZATION': True, 'TARGET_CHANNEL': 1, 'THRESHOLD': 40.0, 'RADIUS': 0.3, 'DO_MEDIAN_FILTERING': False}

No spot feature analyzers.
No edge feature analyzers.
No track feature analyzers.

Initial spot filter:
Initial quality filter value: 0.0.

Spot feature filters:
Set with 1 spot feature filters:
 - MEAN_INTENSITY < 150.0

Particle linking:
Tracker: fiji.plugin.trackmate.tracking.sparselap.SparseLAPTrackerFactory@32435a49.
Tracker settings:
{MAX_FRAME_GAP=2, ALTERNATIVE_LINKING_COST_FACTOR=1.05, LINKING_FEATURE_PENALTIES={}, LINKING_MAX_DISTANCE=15.0, GAP_CLOSING_MAX_DISTANCE=15.0, MERGING_FEATURE_PENALTIES={}, SPLITTING_MAX_DISTANCE=15.0, BLOCKING_VALUE=Infinity, ALLOW_GAP_CLOSING=true, ALLOW_TRACK_SPLITTING=false, ALLOW_TRACK_MERGING=false, MERGING_MAX_DISTANCE=15.0, SPLITTING_FEATURE_PENALTIES={}, CUTOFF_PERCENTILE=0.9, GAP_CLOSING_FEATURE_PENALTIES={}}

Track feature filters:
No track feature filters.

It’s probably because you did not tell TrackMate that you want to compute numerical features. So it have nothing to filter one.

You want to declare the feature computers in the settings. If you want to simply add all feature analyzers that can be found in your Fiji app, add this after creating the settings object:

from fiji.plugin.trackmate.providers import SpotAnalyzerProvider
from fiji.plugin.trackmate.providers import EdgeAnalyzerProvider
from fiji.plugin.trackmate.providers import TrackAnalyzerProvider

    # Add ALL the feature analyzers known to TrackMate, via
    # providers. 
    # They offer automatic analyzer detection, so all the 
    # available feature analyzers will be added. 

     
spotAnalyzerProvider = SpotAnalyzerProvider()
for key in spotAnalyzerProvider.getKeys():
    print( key )
    settings.addSpotAnalyzerFactory( spotAnalyzerProvider.getFactory( key ) )
     
edgeAnalyzerProvider = EdgeAnalyzerProvider()
for  key in edgeAnalyzerProvider.getKeys():
    print( key )
    settings.addEdgeAnalyzer( edgeAnalyzerProvider.getFactory( key ) )
     
trackAnalyzerProvider = TrackAnalyzerProvider()
for key in trackAnalyzerProvider.getKeys():
    print( key )
    settings.addTrackAnalyzer( trackAnalyzerProvider.getFactory( key ) )
1 Like

That worked indeed ! Thanks a lot ! :slight_smile:

Since I’m only interested in the mean intensity of the spots, can I only use the SpotAnalyzerProvider ? And do I need all the keys ?

Thanks a lot for your help !

1 Like