Simple LAP tracking for batch image sequence processing

Dear friends,
I am quite new to using script in TrackMate. After some adaptation of the example code I am still not able to reproduce the manually-done SimpleLAP tracking results by a script and I wonder whether anyone could help me.

My task is:

  • I have 140 folders, each contains a sequence of 500 images, in which there is one bead (bright) moving in sinusoidal waveform.
  • I want to track them and save the tracks into .xml file correspondingly

The problems are:

  1. It’s more sensitive to “blob diameter” and “threshold” than in manually usage of Trackmate, I wonder whether the SparseLAPTracker is working the same as SimpleLAPtracker in the plugin.
  2. Even there are some dot’s detected, there is usually no tracks. Even workable parameters are set
# Get currently selected image
IJ.run("Image Sequence...", "open=[O:\\160908 Calibration of SineWvfm\\freq46.0_ampl31.0\\1_0001.tif] convert sort");
imp = WindowManager.getCurrentImage()
#imp.show()
   
   
model = Model()
   
# Set logger
model.setLogger(Logger.IJ_LOGGER)
   
settings = Settings()
settings.setFrom(imp)
      
settings.detectorFactory = LogDetectorFactory()
settings.detectorSettings = { 
    'DO_SUBPIXEL_LOCALIZATION' : True,
    'RADIUS' : 4,
    'TARGET_CHANNEL' : 1,
    'THRESHOLD' : 5.,
    'DO_MEDIAN_FILTERING' : True,
}  
    

settings.trackerFactory = SparseLAPTrackerFactory()
settings.trackerSettings = LAPUtils.getDefaultLAPSettingsMap() #this sets tens of madatory settings
settings.trackerSettings['LINKING_MAX_DISTANCE'] = 15.0
settings.trackerSettings['GAP_CLOSING_MAX_DISTANCE']=15.0
settings.trackerSettings['MAX_FRAME_GAP']= 2
   
# Add an analyzer for some track features, such as the track mean speed.

#settings.addTrackAnalyzer(TrackSpeedStatisticsAnalyzer()) 
#settings.initialSpotFilterValue = 1
   
print(str(settings))
      
trackmate = TrackMate(model, settings)
     
ok = trackmate.checkInput()
if not ok:
    sys.exit(str(trackmate.getErrorMessage()))
     
ok = trackmate.process()
if not ok:
    sys.exit(str(trackmate.getErrorMessage()))
     
   
model.getLogger().log('Found ' + str(model.getTrackModel().nTracks(True)) + ' tracks.')
    
selectionModel = SelectionModel(model)
displayer =  HyperStackDisplayer(model, selectionModel, imp)
displayer.render()
displayer.refresh()
   

fm = model.getFeatureModel()
 
for id in model.getTrackModel().trackIDs(True):
 
    # Fetch the track feature from the feature model.
    v = fm.getTrackFeature(id, 'TRACK_MEAN_SPEED')
    model.getLogger().log('')
    model.getLogger().log('Track ' + str(id) + ': mean velocity = ' + str(v) + ' ' + model.getSpaceUnits() + '/' + model.getTimeUnits())
       
    track = model.getTrackModel().trackSpots(id)
    for spot in track:
        sid = spot.ID()
        # Fetch spot features directly from spot. 
        x=spot.getFeature('POSITION_X')
        y=spot.getFeature('POSITION_Y')
        t=spot.getFeature('FRAME')
        q=spot.getFeature('QUALITY')
        snr=spot.getFeature('SNR') 
        mean=spot.getFeature('MEAN_INTENSITY')
        model.getLogger().log('\tspot ID = ' + str(sid) + ': x='+str(x)+', y='+str(y)+', t='+str(t)+', q='+str(q) + ', snr='+str(snr) + ', mean = ' + str(mean))
1 Like

Hi @DidasW,

It looks like a problem with the physical calibration.
In TrackMate, all distances are in physical units (µm, mm, etc…) and not in pixel units.

If you use the TrackMate GUI, it is able to pick the physical calibration from the image.
In your script, maybe you don’t, so all distances are in pixel by default, while you have been using physical units in the GUI.

Can you confirm this is the problem?

1 Like

Dear Tineves,

Thanks for your advice. I tried again for a couple of times. Now I can confirm that my image are all in pixel size. However I think that may not be the problem, as when I use Trackmate manually, the input and output are also both in pixel instead of um. (Calibration are done by post analysis of the exported xml file).

There does exist a good news. During my “Brownian” trials, I was able to reproduced my messy script tracking by its manual counterpart. It seems to be related to the T-Z swap

The successful trackings were are done by firstly clicking yes at"It appears this image has 1 timepoint but 500 slices, do you want to swap Z and T".

I wonder whether you could kindly tell me how to do that in script editor by Jython?

Oh yes, this must be the Z vs T swap indeed.
There is no change to get the tracking right of the image dimensionality is not correct.
As for how to do this in python, just look at what we do in the method that invert T and Z:

Any news on this issue?

Dear Tinevez,
Thanks for your suggestion and I think that is actually the point. However as I am not familiar with how to use the GuiUtils method, I failed to make the “Swap T with Z” dialogue pop up.

Would you please help me with that too? Below is how I am using it now:

from ij import IJ, ImagePlus, ImageStack, WindowManager
import sys
import fiji.plugin.trackmate.action.ExportStatsToIJAction as ExportStatsToIJAction
import fiji.plugin.trackmate.action.ExportTracksToXML as ExportTracksToXML
import fiji.plugin.trackmate.detection.DetectorKeys as DetectorKeys
import fiji.plugin.trackmate.detection.DogDetectorFactory as DogDetectorFactory
import fiji.plugin.trackmate.detection.LogDetectorFactory as LogDetectorFactory
import fiji.plugin.trackmate.features.FeatureFilter as FeatureFilter
import fiji.plugin.trackmate.features.FeatureAnalyzer as FeatureAnalyzer
import fiji.plugin.trackmate.features.track.TrackDurationAnalyzer as TrackDurationAnalyzer
import fiji.plugin.trackmate.features.ModelFeatureUpdater as ModelFeatureUpdater
import fiji.plugin.trackmate.features.SpotFeatureCalculator as SpotFeatureCalculator
import fiji.plugin.trackmate.features.spot.SpotContrastAndSNRAnalyzerFactory as SpotContrastAndSNRAnalyzerFactory
import fiji.plugin.trackmate.features.spot.SpotContrastAndSNRAnalyzer as SpotContrastAndSNRAnalyzer
import fiji.plugin.trackmate.features.spot.SpotIntensityAnalyzerFactory as SpotIntensityAnalyzerFactory
import fiji.plugin.trackmate.features.track.TrackSpeedStatisticsAnalyzer as TrackSpeedStatisticsAnalyzer
import fiji.plugin.trackmate.io.TmXmlReader as TmXmlReader
import fiji.plugin.trackmate.io.TmXmlWriter as TmXmlWriter
import fiji.plugin.trackmate.Logger as Logger
import fiji.plugin.trackmate.Model as Model
import fiji.plugin.trackmate.SelectionModel as SelectionModel
import fiji.plugin.trackmate.Settings as Settings
import fiji.plugin.trackmate.TrackMate as TrackMate
import fiji.plugin.trackmate.tracking.sparselap.SparseLAPTrackerFactory as SparseLAPTrackerFactory
import fiji.plugin.trackmate.tracking.LAPUtils as LAPUtils
import fiji.plugin.trackmate.util.TMUtils as TMUtils
import fiji.plugin.trackmate.visualization.hyperstack.HyperStackDisplayer as HyperStackDisplayer

import fiji.plugin.trackmate.gui.GuiUtils as GuiUtils
 
# Get currently selected image

IJ.run("Image Sequence...", "open=[D:\\000 RAW DATA FILES\\freq56.0_ampl52.0\\1_0001.tif] convert sort");
imp = WindowManager.getCurrentImage()
GuiUtils()  
   
model = Model()
   
# Set logger
model.setLogger(Logger.IJ_LOGGER)
   
settings = Settings()
settings.setFrom(imp)
  
settings.detectorFactory = LogDetectorFactory()
settings.detectorSettings = { 
'DO_SUBPIXEL_LOCALIZATION' : True,
'RADIUS' : 7.0,
'TARGET_CHANNEL' : 1,
'THRESHOLD' : 10.0,
'DO_MEDIAN_FILTERING' : True,
 }  


settings.trackerFactory = SparseLAPTrackerFactory()
settings.trackerSettings = LAPUtils.getDefaultLAPSettingsMap() #this sets tens of madatory settings
settings.trackerSettings['LINKING_MAX_DISTANCE'] = 15.0
settings.trackerSettings['GAP_CLOSING_MAX_DISTANCE']=15.0
settings.trackerSettings['MAX_FRAME_GAP']= 2
   
# Add an analyzer for some track features, such as the track mean speed.

#settings.addTrackAnalyzer(TrackSpeedStatisticsAnalyzer()) 
#settings.initialSpotFilterValue = 1
   
print(str(settings))
  
trackmate = TrackMate(model, settings)
 
ok = trackmate.checkInput()
if not ok:
    sys.exit(str(trackmate.getErrorMessage()))
 
ok = trackmate.process()
if not ok:
sys.exit(str(trackmate.getErrorMessage()))
 
   
model.getLogger().log('Found ' + str(model.getTrackModel().nTracks(True)) + ' tracks.')
    
selectionModel = SelectionModel(model)
displayer =  HyperStackDisplayer(model, selectionModel, imp)
displayer.render()
displayer.refresh()
   

fm = model.getFeatureModel()
 
for id in model.getTrackModel().trackIDs(True):
 
    # Fetch the track feature from the feature model.
    v = fm.getTrackFeature(id, 'TRACK_MEAN_SPEED')
    model.getLogger().log('')
    model.getLogger().log('Track ' + str(id) + ': mean velocity = ' + str(v) + ' ' + model.getSpaceUnits() + '/' + model.getTimeUnits())
       
    track = model.getTrackModel().trackSpots(id)
    for spot in track:
        sid = spot.ID()
        # Fetch spot features directly from spot. 
        x=spot.getFeature('POSITION_X')
        y=spot.getFeature('POSITION_Y')
        t=spot.getFeature('FRAME')
        q=spot.getFeature('QUALITY')
        snr=spot.getFeature('SNR') 
        mean=spot.getFeature('MEAN_INTENSITY')
        model.getLogger().log('\tspot ID = ' + str(sid) + ': x='+str(x)+', y='+str(y)+', t='+str(t)+', q='+str(q) + ', snr='+str(snr) + ', mean = ' + str(mean))

Something like this should work:

final int[] dims = imp.getDimensions(); imp.setDimensions( dims[ 2 ], dims[ 4 ], dims[ 3 ] );

This permutes Z and T.
Best
jy

1 Like

Thanks really a lot ~! The tracking works now, I can see the tracks on the screen just like what I saw when manually using trackmate.

I incorporated your code like this.

IJ.run("Image Sequence...", "open=[D:\\000 RAW DATA FILES\\freq56.0_ampl52.0\\1_0001.tif] convert sort");
imp = WindowManager.getCurrentImage()
dims = imp.getDimensions();
imp.setDimensions( dims[ 2 ], dims[ 4 ], dims[ 3 ] );

If I put "final int " in front of “imp”, it will say:

SyntaxError: (“mismatched input ‘int’ expecting NEWLINE”, (‘New_.py’, 35, 6, ‘final int dims = imp.getDimensions();\n’))

However, it seems that the output (XYZ coordinates) or saving xml file is still not working.
According to the error code, “java.lang.NullPointerException: java.lang.NullPointerException”, the problem may be in the following code

for id in model.getTrackModel().trackIDs(True):
 
    # Fetch the track feature from the feature model.
    v = fm.getTrackFeature(id, 'TRACK_MEAN_SPEED')
    model.getLogger().log('')
    model.getLogger().log('Track ' + str(id) + ': mean velocity = ' + str(v) + ' ' + model.getSpaceUnits() + '/' + model.getTimeUnits())
       
    track = model.getTrackModel().trackSpots(id)
    for spot in track:
        sid = spot.ID()
        # Fetch spot features directly from spot. 
        x=spot.getFeature('POSITION_X')
        y=spot.getFeature('POSITION_Y')
        t=spot.getFeature('FRAME')
        q=spot.getFeature('QUALITY')
        snr=spot.getFeature('SNR') 
        mean=spot.getFeature('MEAN_INTENSITY')
        model.getLogger().log('\tspot ID = ' + str(sid) + ': x='+str(x)+', y='+str(y)+', t='+str(t)+', q='+str(q) + ', snr='+str(snr) + ', mean = ' + str(mean))

Dear Tinevez,

Sorry to bother you again. After the discussion last time, I modified the template found on internet and succeeded in doing batch tracking. Here I would like to share this simple code to help new users who encounter the same problem.

from ij import IJ, ImagePlus, ImageStack, WindowManager
import sys
import fiji.plugin.trackmate.action.ExportStatsToIJAction as ExportStatsToIJAction
import fiji.plugin.trackmate.action.ExportTracksToXML as ExportTracksToXML
import fiji.plugin.trackmate.detection.DetectorKeys as DetectorKeys
import fiji.plugin.trackmate.detection.DogDetectorFactory as DogDetectorFactory
import fiji.plugin.trackmate.detection.LogDetectorFactory as LogDetectorFactory
import fiji.plugin.trackmate.features.FeatureFilter as FeatureFilter
import fiji.plugin.trackmate.features.FeatureAnalyzer as FeatureAnalyzer
import fiji.plugin.trackmate.features.track.TrackDurationAnalyzer as TrackDurationAnalyzer
import fiji.plugin.trackmate.features.ModelFeatureUpdater as ModelFeatureUpdater
import fiji.plugin.trackmate.features.SpotFeatureCalculator as SpotFeatureCalculator
import fiji.plugin.trackmate.features.spot.SpotContrastAndSNRAnalyzerFactory as SpotContrastAndSNRAnalyzerFactory
import fiji.plugin.trackmate.features.spot.SpotContrastAndSNRAnalyzer as SpotContrastAndSNRAnalyzer
import fiji.plugin.trackmate.features.spot.SpotIntensityAnalyzerFactory as SpotIntensityAnalyzerFactory
import fiji.plugin.trackmate.features.track.TrackSpeedStatisticsAnalyzer as TrackSpeedStatisticsAnalyzer
import fiji.plugin.trackmate.io.TmXmlReader as TmXmlReader
import fiji.plugin.trackmate.io.TmXmlWriter as TmXmlWriter
import fiji.plugin.trackmate.Logger as Logger
import fiji.plugin.trackmate.Model as Model
import fiji.plugin.trackmate.SelectionModel as SelectionModel
import fiji.plugin.trackmate.Settings as Settings
import fiji.plugin.trackmate.TrackMate as TrackMate
import fiji.plugin.trackmate.tracking.sparselap.SparseLAPTrackerFactory as SparseLAPTrackerFactory
import fiji.plugin.trackmate.tracking.LAPUtils as LAPUtils
import fiji.plugin.trackmate.util.TMUtils as TMUtils
import fiji.plugin.trackmate.visualization.hyperstack.HyperStackDisplayer as HyperStackDisplayer

import fiji.plugin.trackmate.gui.GuiUtils as GuiUtils
 
# Get currently selected image
#**--------------------MODIFY THE FOLDER PATH, '--------------------------**
IJ.run("Image Sequence...", "open=[D:\\z_0001.tif] convert sort");
# change the folder_path to what you need
 
imp = WindowManager.getCurrentImage()
dims = imp.getDimensions();
imp.setDimensions( dims[ 2 ], dims[ 4 ], dims[ 3 ] );
  
model = Model()

# Set logger
model.setLogger(Logger.IJ_LOGGER)  
settings = Settings()
settings.setFrom(imp)

# Setting recognition parameters
settings.detectorFactory = LogDetectorFactory()
settings.detectorSettings = { 
    'DO_SUBPIXEL_LOCALIZATION' : True,
    'RADIUS' : 8.0,
    'TARGET_CHANNEL' : 1,
    'THRESHOLD' : 4.0,
    'DO_MEDIAN_FILTERING' : True,
}  

# Setting tracking parameters
settings.trackerFactory = SparseLAPTrackerFactory()
settings.trackerSettings = LAPUtils.getDefaultLAPSettingsMap() #this sets tens of madatory settings
settings.trackerSettings['LINKING_MAX_DISTANCE'] = 30.0
settings.trackerSettings['GAP_CLOSING_MAX_DISTANCE']=30.0
settings.trackerSettings['MAX_FRAME_GAP']= 5

# Start Trackmate.   
trackmate = TrackMate(model, settings)    
ok = trackmate.checkInput()
print 'CheckInput = %s'%ok
if not ok:
    sys.exit(str(trackmate.getErrorMessage()))
     
ok = trackmate.process()
print 'TrackMate.process = %s'%ok
if not ok:
    sys.exit(str(trackmate.getErrorMessage()))


# Write in the logger, found xxx tracks
model.getLogger().log('Found ' + str(model.getTrackModel().nTracks(True)) + ' tracks.')

    
selectionModel = SelectionModel(model)
displayer =  HyperStackDisplayer(model, selectionModel, imp)# after this, track still not displayed
displayer.render() #track displayed
displayer.refresh()

fm = model.getFeatureModel()
#print fm 
f = open('D:\\test track.dat','w') # create file to store track info.
for id in model.getTrackModel().trackIDs(True):
    track = model.getTrackModel().trackSpots(id)
    for spot in track:
        sid = spot.ID()
        # Fetch spot features directly from spot. 
        x=spot.getFeature('POSITION_X')
        y=spot.getFeature('POSITION_Y')
        t=spot.getFeature('FRAME')
        f.write('%d\t%f\t%f\n'%(t,x,y))
  
f.close()
1 Like

Thanks for your help all along and I apologize for not having shared it earlier (thought it may not of significance) :slight_smile:

Sorry to bump this thread, and for the novice question.
I have been trying to adapt the above script to batch process several folders of tiffs using settings I have optimised in the GUI, and export .xml tracks for MSD analysis but am unsure which command to use in the IJ.run (command) line for it to process all tiffs in the folder given. Also, what should the remainder of the script look like using the defaults above for it to simply output the .xml files in the same directory?

Also, is SparseLAPtracker the same as Simple LAP tracker in the GUI?

Many thanks

IJ.run(“Image Sequence…”, “open=[D:\z_0001.tif] convert sort”);

this line import all tif images in the folder.
Also one helpful tip: you can try using RECORD function under MACROS, to see what command does each manual operation correspond to.

Usually when running in batch, I output tracking results in .txt or .dat file. In that case

#print fm
f = open(‘D:\test track.dat’,‘w’) # create file to store track info.
for id in model.getTrackModel().trackIDs(True):
track = model.getTrackModel().trackSpots(id)
for spot in track:
sid = spot.ID()
# Fetch spot features directly from spot.
x=spot.getFeature(‘POSITION_X’)
y=spot.getFeature(‘POSITION_Y’)
t=spot.getFeature(‘FRAME’)
f.write(’%d\t%f\t%f\n’%(t,x,y))

f.close()

These lines are doing the job. If you want the output to be in the same folder, change the file path defined in:
f = open(‘D:\test track.dat’,‘w’)

I am not sure how to output the whole meta data and the tracks in a full xml file.

As for the last question, I am not an expert and can’t help.

Best,
Da

Thanks, Maybe @tinevez could comment on command to export .xml tracks?
Thanks!