Trackmate script - Java heap memory problem

fiji
imagej
trackmate

#1

Hi,

I’ve written a script in FIJI to use Trackmate to analyze images in folders automatically. It works well when I use a dataset of images that have 30 timepoints, but when i try to run it on images that has 108 timepoints I run into java heap memory problems. I tried increasing the limit from 6GB to 12GB, but that didn’t help. I can run the files just fine using the Trackmate UI itself and the problem specifically comes up when I try to script it.

While looking for a solution, I came across this thread: https://github.com/fiji/TrackMate/issues/59
That seamed like a plausible cause of error, but as it is still not working Im not sure how to move onwards. Was that ever implemented or am I running into other problems?

Can anyone help me out? :slight_smile:

import os
from os import path

from java.lang import Long
from java.lang import String
from java.lang.Long import longValue
from java.util import ArrayList
from jarray import array
from java.lang.reflect import Array
import java
import csv
from ij import IJ


# TrackMate Dependencies
from fiji.plugin.trackmate import Model
from fiji.plugin.trackmate import Settings
from fiji.plugin.trackmate import TrackMate
from fiji.plugin.trackmate import SelectionModel
from fiji.plugin.trackmate import Logger
from fiji.plugin.trackmate.detection import LogDetectorFactory
from fiji.plugin.trackmate.tracking.sparselap import SparseLAPTrackerFactory
from fiji.plugin.trackmate.tracking import LAPUtils
import fiji.plugin.trackmate.visualization.hyperstack.HyperStackDisplayer as HyperStackDisplayer
import fiji.plugin.trackmate.features.FeatureFilter as FeatureFilter
import sys
import fiji.plugin.trackmate.features.track.TrackDurationAnalyzer as TrackDurationAnalyzer

from fiji.plugin.trackmate.tracking.kdtree import NearestNeighborTrackerFactory
import fiji.plugin.trackmate.features.TrackFeatureCalculator as TrackFeatureCalculator
import fiji.plugin.trackmate.action.ExportStatsToIJAction as ExportStatsToIJAction
import fiji.plugin.trackmate.action.ExportAllSpotsStatsAction as ExportAllSpotsStatsAction
import fiji.plugin.trackmate.action.TrackBranchAnalysis as TrackBranchAnalysis

from java.io import File
from fiji.plugin.trackmate.io import TmXmlWriter



#-------- Trackmate----------

#----------------------------
# 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()
print dir(model.logger)
#------------------------
# Prepare settings object
#------------------------
       
settings = Settings()

# Set logger
model.setLogger(Logger.IJ_LOGGER)
       
# Configure detector - We use the Strings for the keys
settings.detectorFactory = LogDetectorFactory()
settings.detectorSettings = { 
    'DO_SUBPIXEL_LOCALIZATION' : False,
    'RADIUS' : 17.5,
    'TARGET_CHANNEL' : 1,
    'THRESHOLD' : 25.,
    'DO_MEDIAN_FILTERING' : False,
}  
    
# Configure spot filters - Classical filter on quality
filter1 = FeatureFilter('QUALITY', 0.1, True)
settings.addSpotFilter(filter1)
     
# Configure tracker - We want to allow merges and fusions
settings.trackerFactory = SparseLAPTrackerFactory()
settings.trackerSettings = LAPUtils.getDefaultLAPSettingsMap()
settings.trackerSettings['ALLOW_TRACK_SPLITTING'] = True
settings.trackerSettings['ALLOW_TRACK_MERGING'] = True
settings.trackerSettings['LINKING_MAX_DISTANCE'] = 70.0
settings.trackerSettings['GAP_CLOSING_MAX_DISTANCE'] = 70.0
settings.trackerSettings['MAX_FRAME_GAP'] = 3


#settings.trackerFactory = NearestNeighborTrackerFactory()
#settings.trackerSettings = settings.trackerFactory.getDefaultSettings();
#settings.trackerSettings['LINKING_MAX_DISTANCE'] = 30.0
print(settings.trackerSettings)
    
# 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, True)
#settings.addTrackFilter(filter2)
    
# Send all messages to ImageJ log window.
model.setLogger(Logger.IJ_LOGGER)

inputfolder = '.../trackmate/experiments/'
outputfolder = '/.../trackmate/output/'



for folders in os.listdir(inputfolder):
    
    # Specific for mac computers, leave this (wont hurt on PC)
    if not folders.endswith('.DS_Store'):

        # If outputfolder does not exist, create it
        if not os.path.isdir(outputfolder + folders):
            os.makedirs(outputfolder + folders)

        # For all files(images) in folder

        for files in os.listdir(inputfolder + folders):
            imp = IJ.openImage(inputfolder + folders + '/' + files)

            ##
            imp.show()
            
            #Save resultant image using Bio-Formats
            imp = IJ.getImage();

            # Trackmate
            settings.setFrom(imp)
            trackmate = TrackMate(model, settings)

	        #--------
	        # Process
	        #--------

            ok = trackmate.checkInput()
            print ok
            if not ok:
                sys.exit(str(trackmate.getErrorMessage()))#

            ok = trackmate.process()
            print ok
    
            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()

    
            # The feature model, that stores edge and track features
            fm = model.getFeatureModel()

            model.getLogger().log(str(model))
    

            TrackFeatureCalculator(model,settings).process()
            ExportStatsToIJAction().execute(trackmate)
            IJ.selectWindow('Track statistics');
            IJ.saveAs('Results', outputfolder + folders + '/Track statistics_' + str(files) + '.csv');
            IJ.selectWindow('Spots in tracks statistics');
            IJ.saveAs('Results', outputfolder + folders + '/Spots in tracks statistics_' + str(files) + '.csv');

        

print("Done")
#success = uploadImage(str2d, gateway)
gateway.disconnect()	

Traceback (most recent call last):
  File "/Users/.../Desktop/temp/TrackmateAuto.py", line 182, in <module>
    ok = trackmate.process()
	at net.imglib2.img.basictypeaccess.array.AbstractFloatArray.<init>(AbstractFloatArray.java:50)
	at net.imglib2.img.basictypeaccess.array.FloatArray.<init>(FloatArray.java:47)
	at net.imglib2.img.basictypeaccess.array.FloatArray.createArray(FloatArray.java:58)
	at net.imglib2.img.basictypeaccess.array.FloatArray.createArray(FloatArray.java:43)
	at net.imglib2.img.array.ArrayImgFactory.create(ArrayImgFactory.java:91)
	at net.imglib2.img.array.ArrayImgFactory.create(ArrayImgFactory.java:68)
	at net.imglib2.img.array.ArrayImgFactory.create(ArrayImgFactory.java:57)
	at net.imglib2.algorithm.fft2.FFT.realToComplex(FFT.java:116)
	at net.imglib2.algorithm.fft2.FFT.realToComplex(FFT.java:335)
	at net.imglib2.algorithm.fft2.FFT.realToComplex(FFT.java:74)
	at net.imglib2.algorithm.fft2.FFTConvolution.computeKernelFFT(FFTConvolution.java:578)
	at net.imglib2.algorithm.fft2.FFTConvolution.convolve(FFTConvolution.java:508)
	at fiji.plugin.trackmate.detection.LogDetector.process(LogDetector.java:145)
	at fiji.plugin.trackmate.TrackMate$1.run(TrackMate.java:377)
	at net.imglib2.multithreading.SimpleMultiThreading.startAndJoin(SimpleMultiThreading.java:126)
	at fiji.plugin.trackmate.TrackMate.execDetection(TrackMate.java:458)
	at fiji.plugin.trackmate.TrackMate.process(TrackMate.java:661)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
java.lang.OutOfMemoryError: java.lang.OutOfMemoryError: Java heap space

	at org.python.core.Py.JavaError(Py.java:552)
	at org.python.core.Py.JavaError(Py.java:543)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:190)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:206)
	at org.python.core.PyObject.__call__(PyObject.java:480)
	at org.python.core.PyObject.__call__(PyObject.java:484)
	at org.python.core.PyMethod.__call__(PyMethod.java:126)
	at org.python.pycode._pyx0.f$0(/Users/.../Desktop/temp/TrackmateAuto.py:212)
	at org.python.pycode._pyx0.call_function(/Users/.../Desktop/temp/TrackmateAuto.py)
	at org.python.core.PyTableCode.call(PyTableCode.java:171)
	at org.python.core.PyCode.call(PyCode.java:18)
	at org.python.core.Py.runCode(Py.java:1614)
	at org.python.core.__builtin__.eval(__builtin__.java:497)
	at org.python.core.__builtin__.eval(__builtin__.java:501)
	at org.python.util.PythonInterpreter.eval(PythonInterpreter.java:259)
	at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:57)
	at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:31)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
	at org.scijava.script.ScriptModule.run(ScriptModule.java:160)
	at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
	at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.OutOfMemoryError: Java heap space
	at net.imglib2.img.basictypeaccess.array.AbstractFloatArray.<init>(AbstractFloatArray.java:50)
	at net.imglib2.img.basictypeaccess.array.FloatArray.<init>(FloatArray.java:47)
	at net.imglib2.img.basictypeaccess.array.FloatArray.createArray(FloatArray.java:58)
	at net.imglib2.img.basictypeaccess.array.FloatArray.createArray(FloatArray.java:43)
	at net.imglib2.img.array.ArrayImgFactory.create(ArrayImgFactory.java:91)
	at net.imglib2.img.array.ArrayImgFactory.create(ArrayImgFactory.java:68)
	at net.imglib2.img.array.ArrayImgFactory.create(ArrayImgFactory.java:57)
	at net.imglib2.algorithm.fft2.FFT.realToComplex(FFT.java:116)
	at net.imglib2.algorithm.fft2.FFT.realToComplex(FFT.java:335)
	at net.imglib2.algorithm.fft2.FFT.realToComplex(FFT.java:74)
	at net.imglib2.algorithm.fft2.FFTConvolution.computeKernelFFT(FFTConvolution.java:578)
	at net.imglib2.algorithm.fft2.FFTConvolution.convolve(FFTConvolution.java:508)
	at fiji.plugin.trackmate.detection.LogDetector.process(LogDetector.java:145)
	at fiji.plugin.trackmate.TrackMate$1.run(TrackMate.java:377)
	at net.imglib2.multithreading.SimpleMultiThreading.startAndJoin(SimpleMultiThreading.java:126)
	at fiji.plugin.trackmate.TrackMate.execDetection(TrackMate.java:458)
	at fiji.plugin.trackmate.TrackMate.process(TrackMate.java:661)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:188)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:206)
	at org.python.core.PyObject.__call__(PyObject.java:480)
	at org.python.core.PyObject.__call__(PyObject.java:484)
	at org.python.core.PyMethod.__call__(PyMethod.java:126)
	at org.python.pycode._pyx0.f$0(/Users/.../Desktop/temp/TrackmateAuto.py:212)
	at org.python.pycode._pyx0.call_function(/Users/.../Desktop/temp/TrackmateAuto.py)
	at org.python.core.PyTableCode.call(PyTableCode.java:171)
	at org.python.core.PyCode.call(PyCode.java:18)
	at org.python.core.Py.runCode(Py.java:1614)
	at org.python.core.__builtin__.eval(__builtin__.java:497)

#2

The bug you refer to should have been fixed.
I will try to eliminate the obvious.

  • Can you give us the dimensions of your image?
  • Could you try to run your script by settings the number of threads TrackMate can use ot 1? You can set that in ImageJ preferences,

#3

Thanks for the quick reply!

Its 2048x2048, about 1GB large in total (if that matters)

I changed the threads to 1 but I still get the same error. I did this with and without restarting FIJI. And when trackmate is initiated it logs: Starting detection process using 8 threads. Detection processes 1 fram simultaneously and allocated 8 threads per frame. Doesn’t seem to come into effect. I changed in Edit->Options->Memory & threads


#4

There are 2D images? or 3D stack?

If the threading does not work, set it from the script with

trackmate = TrackMate(model, settings)
trackmate.setNumThreads( 1 )

#5

My bad, I looked into the specific format of the image and notices that the Z and T dimensions were swapped, once that was taken care of everything worked. You can close this issue. Thanks for the help!


#6

Ouf!

:slight_smile:

Popolopopo