How to increase the efficiency during fetching spot features in Matlab script

Hi, I have a problem with fetching trackmate spot results it in Matlab. I used the same way in the Trackmate Manual to export spot, edge and track numerical features after tracking.

But it seems that if I got a lot of tracks, this way cost a lot of time in fetching the spot feature data.

fm = model.getFeatureModel();
trackIDs = model.getTrackModel().trackIDs(true).size;

for id = 0:trackIDs-1
    v = fm.getTrackFeature(java.lang.Integer(id),'TRACK_MEAN_SPEED');
    vt = fm.getTrackFeature(java.lang.Integer(id),'TRACK_DURATION');
    vl = fm.getTrackFeature(java.lang.Integer(id),'TRACK_DISPLACEMENT');
    
    track = model.getTrackModel().trackSpots(java.lang.Integer(id));
    iterator = track.iterator();
    counter = 0;
    RawResults(id+1).Mean_Velocity = strcat(num2str(double(v)),string(model.getSpaceUnits()),'/',...
        string(model.getTimeUnits()));
    RawResults(id+1).Track_Duration = strcat(num2str(double(vt)),string(model.getTimeUnits()));
    RawResults(id+1).Track_Displacement = strcat(num2str(double(vl)),string(model.getSpaceUnits()));
    while(iterator.hasNext())
        spot = iterator.next();
        sid  = spot.ID();
        % Fetch spot features directly from spot.
        x = spot.getFeature('POSITION_X');
        y = spot.getFeature('POSITION_Y');
        t = spot.getFeature('FRAME');

        counter = counter + 1;
        RawResults(id+1).SpotID(counter) = sid;        
        RawResults(id+1).Position(counter,:) = [double(x),double(y)];
        RawResults(id+1).FrameNum(counter) = double(t);        

    end
    RawResults(id+1).SpotID = RawResults(id+1).SpotID(1:counter); 
    RawResults(id+1).Position = RawResults(id+1).Position(1:counter,:);
 end

Is there any solutions to increase the efficiency to fetch the spot data ? Something like parallel computing?

Any hint would be appreciated!
Kind regards

Hello @Andrew_li

Do you import the model into MATLAB from a TrackMate file?

“model” is create by fiji.plugin.trackmate.Model().
Here’s my entire Matlab code.

ImageJ;

import java.util.HashMap
import ij.*
import ImagePlus.*
import fiji.plugin.trackmate.*
import fiji.plugin.trackmate.detection.*
import fiji.plugin.trackmate.tracking.sparselap.*
import fiji.plugin.trackmate.tracking.*
import fiji.plugin.trackmate.visualization.hyperstack.*
import fiji.plugin.trackmate.providers.*
import fiji.plugin.trackmate.features.*
import fiji.plugin.trackmate.features.spot.*
import fiji.plugin.trackmate.action.*
import fiji.plugin.trackmate.io.*
import fiji.plugin.trackmate.features.track.*
import fiji.plugin.trackmate.util.*

% ---------------------------------------
% Pick a source image
% ---------------------------------------

% Get currently selected image
jpg_stack = dir('*.jpg');
firstImage = imread(jpg_stack(1).name);
windowStack = ij.ImageStack(size(firstImage,2),size(firstImage,1));

for ii = 1:length(jpg_stack)
	currImg = ij.IJ.openImage(jpg_stack(ii).name);
    windowStack.addSlice(currImg.getProcessor());
end
ip = currImg.getProcessor();
imp1 = ij.ImagePlus('title',ip);
imp2 = ij.ImagePlus('title',windowStack);

% width, height, nChannels, nSlices, nFrames
dims = imp2.getDimensions();

% nChannels, nSlices, nFrames
imp2.setDimensions(dims(3), dims(5), dims(4));

% -------------------------
% Instantiate model object
% -------------------------
   
model = Model();
   
% Set logger
model.setLogger(Logger.IJ_LOGGER)
   
% ------------------------
%  Prepare settings object
% ------------------------
      
settings = Settings();
settings.setFrom(imp2);

% Configure detector - We use a java map
settings.detectorFactory = DogDetectorFactory();
map = HashMap();
map.put('DO_SUBPIXEL_LOCALIZATION', true);
map.put('RADIUS', 4.);
map.put('TARGET_CHANNEL', 1);
map.put('THRESHOLD', 1.);
map.put('DO_MEDIAN_FILTERING', false);
settings.detectorSettings = map;
     
% Configure spot filters - Classical filter on quality
filter1 = FeatureFilter('QUALITY', 1.0, true);
settings.addSpotFilter(filter1);
      
% Configure tracker - We want to allow splits and fusions
settings.trackerFactory = SparseLAPTrackerFactory();
settings.trackerSettings = LAPUtils.getDefaultLAPSettingsMap(); % almost good enough
% settings.trackerSettings.put('ALLOW_TRACK_SPLITTING', false);
% settings.trackerSettings.put('ALLOW_TRACK_MERGING', false);
settings.trackerSettings.put('LINKING_MAX_DISTANCE',15.0);
settings.trackerSettings.put('GAP_CLOSING_MAX_DISTANCE',15.0);
settings.trackerSettings.put('MAX_FRAME_GAP',java.lang.Integer(3));
     
%  Add the analyzers for some spot features.
%  You need to configure TrackMate with analyzers that will generate 
%  the data you need. 
%  Here we just add two analyzers for spot, one that computes generic
%  pixel intensity statistics (mean, max, etc...) and one that computes
%  an estimate of each spot's SNR. 
%  The trick here is that the second one requires the first one to be in
%  place. Be aware of this kind of gotchas, and read the docs. 
settings.addSpotAnalyzerFactory(SpotIntensityAnalyzerFactory())
settings.addSpotAnalyzerFactory(SpotContrastAndSNRAnalyzerFactory())
   
%  Add an analyzer for some track features, such as the track mean speed.
settings.addTrackAnalyzer(TrackSpeedStatisticsAnalyzer())
settings.addTrackAnalyzer(TrackDurationAnalyzer());
settings.addTrackAnalyzer(TrackLocationAnalyzer());

% settings.initialSpotFilterValue = java.lang.Double(1);

filter2 = FeatureFilter('TRACK_DISPLACEMENT',20,true);
settings.addTrackFilter(filter2);

filter3 = FeatureFilter('TRACK_DURATION',100,true);
settings.addTrackFilter(filter3);

%-------------------
% Instantiate plugin
%-------------------
     
trackmate = TrackMate(model, settings);
trackmate.setNumThreads(8); % As many threads as you want.
        
%--------
% Process
%--------

ok = trackmate.checkInput();
if ~ok
    display(trackmate.getErrorMessage());
end
  
ok = trackmate.process();
if ~ok
    display(trackmate.getErrorMessage());
end

%----------------
% Display results
%----------------
model.getLogger().log(strcat('Found ',num2str(model.getTrackModel().nTracks(true)),' tracks.'));

selectionModel = SelectionModel(model);
displayer = HyperStackDisplayer(model, selectionModel, imp2);
% displayer.render();
% displayer.refresh();
     
% Echo results

fm = model.getFeatureModel();
trackIDs = model.getTrackModel().trackIDs(true).size;

RawResults(1:trackIDs) = struct('Mean_Velocity',zeros(1,1),...
    'Track_Duration',zeros(1,1),...
    'Track_Displacement',zeros(1,1),...
    'SpotID',zeros(imp2.getNFrames,1),...
    'Position',zeros(imp2.getNFrames,2),...
    'FrameNum',zeros(imp2.getNFrames,1));

for id = 0:trackIDs-1
    v = fm.getTrackFeature(java.lang.Integer(id),'TRACK_MEAN_SPEED');
    vt = fm.getTrackFeature(java.lang.Integer(id),'TRACK_DURATION');
    vl = fm.getTrackFeature(java.lang.Integer(id),'TRACK_DISPLACEMENT');
    model.getLogger().log('');
    model.getLogger().log(strcat('Track ',num2str(id),': mean velocity = ',...
        num2str(double(v),8),' ',string(model.getSpaceUnits()),'/',...
        string(model.getTimeUnits())));
    
    track = model.getTrackModel().trackSpots(java.lang.Integer(id));
    iterator = track.iterator();
    counter = 0;
    RawResults(id+1).Mean_Velocity = strcat(num2str(double(v)),string(model.getSpaceUnits()),'/',...
        string(model.getTimeUnits()));
    RawResults(id+1).Track_Duration = strcat(num2str(double(vt)),string(model.getTimeUnits()));
    RawResults(id+1).Track_Displacement = strcat(num2str(double(vl)),string(model.getSpaceUnits()));
    while(iterator.hasNext())
        spot = iterator.next();
        sid  = spot.ID();
        % Fetch spot features directly from spot.
        x = spot.getFeature('POSITION_X');
        y = spot.getFeature('POSITION_Y');
        t = spot.getFeature('FRAME');
        r = spot.getFeature('RADIUS');
        q = spot.getFeature('QUALITY');
        counter = counter + 1;
        RawResults(id+1).SpotID(counter) = sid;        
        RawResults(id+1).Position(counter,:) = [double(x),double(y)]; %cost a lot of time
        RawResults(id+1).FrameNum(counter) = double(t);

        
        snr = spot.getFeature('SNR');
        mean = spot.getFeature('MEAN_INTENSITY');
    end
    RawResults(id+1).SpotID = RawResults(id+1).SpotID(1:counter); 
    RawResults(id+1).Position = RawResults(id+1).Position(1:counter,:);
    RawResults(id+1).FrameNum = RawResults(id+1).FrameNum(1:counter);
end

I tracked the execution time, found that convert java.lang.double to double cost a lot of time. Is there any efficient way to export data from model?

Best regards.

Your script is awesome! It’s a great idea to run TrackMate from MATLAB!

This I don’t know but I may have a hunch.

What you get when you do:
x = spot.getFeature('POSITION_X');
or any other feature is not a native double but a Java object java.lang.Double. Instead of casting it to the MATLAB double, maybe you could unbox it using the Java method. Like this:

xobj = spot.getFeature('POSITION_X');
x = xobj.doubleValue();

I am not sure it is good enough. Can you let us know?

1 Like

Many thanks.
This method works well that it reduced the running time to one-third of what it was.

Best regards

1 Like