Need help or advice ? Come to the Icy club ! - Every Wenesday morning from 9h30 to 12h30 - Francois Jacob Building - Main hall - Pasteur
Register

Batch Spot Tracking with Auto Parameter Estimation

by nchenouard / Nicolas Chenouard

Use the Spot Detector and Spot Tracking plugin in a batch way (multiple movies directly loaded from a local location).
The parameters of the Spot Tracking plugin are estimated automatically.
Results are saved in XLS and XML files compatible with the Track Manager plugin.

version 2 (last version):

download to use and modify in Icy. How do I use scripts ? A Problem ? ask the community.
Changelog for this version: Added min size parameters for spot detection.
importClass(Packages.plugins.nchenouard.particletracking.SpotTrackingPlugin)
importClass(Packages.icy.type.DataType)
importClass(Packages.java.util.ArrayList)
importClass(Packages.java.util.Vector)
importClass(Packages.java.awt.geom.Point2D)
importClass(Packages.java.io.File)
importClass(Packages.java.awt.image.BufferedImage)

importClass(Packages.icy.file.Loader)
importClass(Packages.icy.gui.dialog.MessageDialog)
importClass(Packages.icy.sequence.Sequence)
importClass(Packages.icy.file.xls.XlsManager)
importClass(Packages.icy.file.FileUtil)
importClass(Packages.icy.file.Saver)
importClass(Packages.icy.type.DataType)
importClass(Packages.icy.image.IcyBufferedImage)
importClass(Packages.icy.gui.viewer.Viewer)
importClass(Packages.icy.canvas.Canvas2D)

importClass(Packages.org.w3c.dom.Document)
importClass(Packages.org.w3c.dom.Element)

importClass(Packages.plugins.tprovoost.scripteditor.uitools.filedialogs.FileDialog)
importClass(Packages.icy.util.XMLUtil)

importClass(Packages.plugins.fab.spotDetector.detector.UDWTWavelet)
importClass(Packages.plugins.fab.spotDetector.GlobalDetectionToken)
importClass(Packages.plugins.fab.spotDetector.DetectionSpot)
importClass(Packages.plugins.fab.trackmanager.TrackGroup)
importClass(Packages.plugins.fab.trackmanager.TrackSegment)


importClass(Packages.plugins.nchenouard.spot.DetectionResult)
importClass(Packages.plugins.nchenouard.spot.Spot)
importClass(Packages.plugins.nchenouard.particletracking.SpotTrackingPlugin)



  /////////////////////////////
 // USER DEFINED PARAMETERS //
/////////////////////////////

// detection parameters

// scale threshold parameters
parameterForScale1 = 0; // 0 means that the scale is not used
parameterForScale2 = 40;
parameterForScale3 = 0;
scaleParameters = [parameterForScale1, parameterForScale2, parameterForScale3]; 

detectNegative = false; // SET TO true IF DETECTION OF DARK PIXELS, false FOR BRIGHT PIXELS
useROIforWATComputation = false; // SET TO TRUE IF USE A ROI FOR WAT COMPUTATION, FALSE OTHERWISE

minSize = 2; // MINIMUM SIZE OF THE DETECTED SPOTS

// tracking parameter estimation
isDirectedMotion = true; // true FOR DIRECTED MOTION 
isSingleMotion = false; // true FOR SINGLE MOTION MODEL, false FOR MULTIPLE MOTION MODELS
isUpdateMotion = false; // true IF PARAMETERS OF MOTION MODELS ARE REEVALUATED ONLINE

// create a detector
detector = new UDWTWavelet()


// build the tracker
tracker = new SpotTrackingPlugin();
tracker.run()

  ////////////////////////////////////////
 // let the user select multiple files //
////////////////////////////////////////

var files = FileDialog.openMulti() 
if (files == null) throw "User cancelled!"

 ///////////////////////////////////////////
// iterate over the selected image files //
//////////////////////////////////////////
for (j = 0; j < files.length; ++j) {
    var f = files[j]
      ///////////////////////
     // load the sequence //
    ///////////////////////
    sequence = Loader.loadSequence(f)
    println("loaded sequence: "+ sequence.getName());

      ////////////////////////
     // perform detection ///
    ////////////////////////
    detectionResult = new DetectionResult();
    for ( frameNumber = 0 ; frameNumber < sequence.getSizeT() ; frameNumber++ )
    {
    	image = sequence.getImage( frameNumber , 0 ) // get image at t and z=0	
	tmpSequence = new Sequence();
	tmpSequence.addImage( 0 , image );
    	detector.detect(tmpSequence, detectNegative, useROIforWATComputation, scaleParameters)
    	detections = detector.getDetectionResult();
    	spotVector =  new Vector(detections.size());
    	for (k = 0; k < detections.size(); k++)
    	{
    		d = detections.get(k);
    		if (d.points.size() >= minSize){
  	  		spotVector.add(new Spot(d.getMassCenter().x, d.getMassCenter().y, d.getMassCenter().z));
    		}
    	}
    	detectionResult.setResult(frameNumber,spotVector)
    }
      ////////////////////////////////////////////////////
     // estimate the tracking parameters automatically //
    ////////////////////////////////////////////////////
  
    tracker.estimateParameters(isDirectedMotion, isSingleMotion, isUpdateMotion)


      //////////////////////
     // Perform tracking //
    //////////////////////
    mhtracker = tracker.mhTrackerManager.buildMHTracker(detectionResult);
    for (t = detectionResult.getFirstFrameTime(); t <= detectionResult.getLastFrameTime(); t++)
    {
    	mhtracker.track(t, detectionResult.getDetectionsAtT(t));
    }
    tracks = mhtracker.getCompleteTracks();
    tg = new TrackGroup(detectionResult.getSequence());
    for (i = 0; i < tracks.size(); i++)
    {
    	tg.addTrackSegment(tracks.get(i));
    }
    tg.setDescription("Bacth particle tracking");


      /////////////////////////////
     // Save tracks in XLS file //
    /////////////////////////////

    // copied from the track processor for tack export of Fabrice de Chaumont

    folder = f.getAbsolutePath().substring( 0 , f.getAbsolutePath().length() - f.getName().length() );
    // create a XLS file to output results
    trackXLSFile = new File ( folder + FileUtil.separator + f.getName()+"-tracksXLS.xls" );
    
    xls = new XlsManager( trackXLSFile );
    xls.createNewPage("Tracks");
    
    cursorY = 0;
    
    for ( k =  0; k < tracks.size(); k++ )
    {
	ts = tracks.get(k)
	cursorY++;
	xls.setLabel( 0 , cursorY, "track #");
	xls.setNumber( 1 , cursorY, tracks.indexOf( ts ) );
	cursorY++;
		
	xls.setLabel( 2 , cursorY, "t");
	xls.setLabel( 3 , cursorY, "x");
	xls.setLabel( 4 , cursorY, "y");
	xls.setLabel( 5 , cursorY, "z");
	cursorY++;
		
	detectionList = ts.getDetectionList();
		
	for (i = 0;  i < detectionList.size() ; i++  )
	{
		d = detectionList.get( i );
		xls.setNumber( 2 , cursorY , d.getT() );
		xls.setNumber( 3 , cursorY , d.getX() );
		xls.setNumber( 4 , cursorY , d.getY() );
		xls.setNumber( 5 , cursorY , d.getZ() );

		cursorY++;
	}
    }
    xls.SaveAndClose();

      ///////////////////////////////////////////////////////
     // Save tracks in TrackManager compatible xml format //
    ///////////////////////////////////////////////////////

    trackXMLFile = new File ( folder + FileUtil.separator + f.getName()+"-tracksXML.xml" );
    
    document = XMLUtil.createDocument( true );
    versionElement = XMLUtil.addElement( document.getDocumentElement() , "trackfile" ); 
    versionElement.setAttribute("version", "1");
    trackGroupElement = XMLUtil.addElement( document.getDocumentElement() , "trackgroup" );
    trackGroupElement.setAttribute("description", tg.getDescription() );
    for ( k = 0; k < tg.getTrackSegmentList().size(); k++ ){
    	trackSegment = tg.getTrackSegmentList().get(k)
    	trackElement = XMLUtil.addElement( trackGroupElement , "track" );				
    	trackElement.setAttribute( "id", ""+trackSegment.getId() );
	for ( m = 0; m < trackSegment.getDetectionList().size(); m++ ){					
		detection = trackSegment.getDetectionList().get(m);
		detectionElement = XMLUtil.addElement( trackElement , "detection" );
		detectionElement.setAttribute( "classname", detection.getClass().getName() );
		detection.saveToXML( detectionElement );
	}			
	}
    linklistElement = XMLUtil.addElement( document.getDocumentElement() , "linklist" );
    XMLUtil.saveDocument( document , trackXMLFile );
}

This script has no documentation. A Problem ? ask the community.


Previous versions:


version 1:

download to use and modify in Icy.
Changelog for this version: initial version
importClass(Packages.plugins.nchenouard.particletracking.SpotTrackingPlugin)
importClass(Packages.icy.type.DataType)
importClass(Packages.java.util.ArrayList)
importClass(Packages.java.util.Vector)
importClass(Packages.java.awt.geom.Point2D)
importClass(Packages.java.io.File)
importClass(Packages.java.awt.image.BufferedImage)

importClass(Packages.icy.file.Loader)
importClass(Packages.icy.gui.dialog.MessageDialog)
importClass(Packages.icy.sequence.Sequence)
importClass(Packages.icy.file.xls.XlsManager)
importClass(Packages.icy.file.FileUtil)
importClass(Packages.icy.file.Saver)
importClass(Packages.icy.type.DataType)
importClass(Packages.icy.image.IcyBufferedImage)
importClass(Packages.icy.gui.viewer.Viewer)
importClass(Packages.icy.canvas.Canvas2D)

importClass(Packages.org.w3c.dom.Document)
importClass(Packages.org.w3c.dom.Element)

importClass(Packages.plugins.tprovoost.scripteditor.uitools.filedialogs.FileDialog)
importClass(Packages.icy.util.XMLUtil)

importClass(Packages.plugins.fab.spotDetector.detector.UDWTWavelet)
importClass(Packages.plugins.fab.spotDetector.GlobalDetectionToken)
importClass(Packages.plugins.fab.spotDetector.DetectionSpot)
importClass(Packages.plugins.fab.trackmanager.TrackGroup)
importClass(Packages.plugins.fab.trackmanager.TrackSegment)


importClass(Packages.plugins.nchenouard.spot.DetectionResult)
importClass(Packages.plugins.nchenouard.spot.Spot)
importClass(Packages.plugins.nchenouard.particletracking.SpotTrackingPlugin)



  /////////////////////////////
 // USER DEFINED PARAMETERS //
/////////////////////////////

// detection parameters

// scale threshold parameters
parameterForScale1 = 0; // 0 means that the scale is not used
parameterForScale2 = 80;
parameterForScale3 = 0;
scaleParameters = [parameterForScale1, parameterForScale2, parameterForScale3]; 

detectNegative = false; // SET TO true IF DETECTION OF DARK PIXELS, false FOR BRIGHT PIXELS
useROIforWATComputation = false; // SET TO TRUE IF USE A ROI FOR WAT COMPUTATION, FALSE OTHERWISE

// tracking parameter estimation
isDirectedMotion = true; // true FOR DIRECTED MOTION 
isSingleMotion = false; // true FOR SINGLE MOTION MODEL, false FOR MULTIPLE MOTION MODELS
isUpdateMotion = false; // true IF PARAMETERS OF MOTION MODELS ARE REEVALUATED ONLINE

// create a detector
detector = new UDWTWavelet()


// build the tracker
tracker = new SpotTrackingPlugin();
tracker.run()

  ////////////////////////////////////////
 // let the user select multiple files //
////////////////////////////////////////

var files = FileDialog.openMulti() 
if (files == null) throw "User cancelled!"

 ///////////////////////////////////////////
// iterate over the selected image files //
//////////////////////////////////////////
for (j = 0; j < files.length; ++j) {
    var f = files[j]
      ///////////////////////
     // load the sequence //
    ///////////////////////
    sequence = Loader.loadSequence(f)
    println("loaded sequence: "+ sequence.getName());

      ////////////////////////
     // perform detection ///
    ////////////////////////
    detectionResult = new DetectionResult();
    for ( frameNumber = 0 ; frameNumber < sequence.getSizeT() ; frameNumber++ )
    {
    	image = sequence.getImage( frameNumber , 0 ) // get image at t and z=0	
	tmpSequence = new Sequence();
	tmpSequence.addImage( 0 , image );
    	detector.detect(tmpSequence, detectNegative, useROIforWATComputation, scaleParameters)
    	detections = detector.getDetectionResult();
    	spotVector =  new Vector(detections.size());
    	for (k = 0; k < detections.size(); k++)
    	{
    		d = detections.get(k);
    		spotVector.add(new Spot(d.getMassCenter().x, d.getMassCenter().y, d.getMassCenter().z));
    	}
    	detectionResult.setResult(frameNumber,spotVector)
    }
      ////////////////////////////////////////////////////
     // estimate the tracking parameters automatically //
    ////////////////////////////////////////////////////
  
    tracker.estimateParameters(isDirectedMotion, isSingleMotion, isUpdateMotion)


      //////////////////////
     // Perform tracking //
    //////////////////////
    mhtracker = tracker.mhTrackerManager.buildMHTracker(detectionResult);
    for (t = detectionResult.getFirstFrameTime(); t <= detectionResult.getLastFrameTime(); t++)
    {
    	mhtracker.track(t, detectionResult.getDetectionsAtT(t));
    }
    tracks = mhtracker.getCompleteTracks();
    tg = new TrackGroup(detectionResult.getSequence());
    for (i = 0; i < tracks.size(); i++)
    {
    	tg.addTrackSegment(tracks.get(i));
    }
    tg.setDescription("Bacth particle tracking");


      /////////////////////////////
     // Save tracks in XLS file //
    /////////////////////////////

    // copied from the track processor for tack export of Fabrice de Chaumont

    folder = f.getAbsolutePath().substring( 0 , f.getAbsolutePath().length() - f.getName().length() );
    // create a XLS file to output results
    trackXLSFile = new File ( folder + FileUtil.separator + f.getName()+"-tracksXLS.xls" );
    
    xls = new XlsManager( trackXLSFile );
    xls.createNewPage("Tracks");
    
    cursorY = 0;
    
    for ( k =  0; k < tracks.size(); k++ )
    {
	ts = tracks.get(k)
	cursorY++;
	xls.setLabel( 0 , cursorY, "track #");
	xls.setNumber( 1 , cursorY, tracks.indexOf( ts ) );
	cursorY++;
		
	xls.setLabel( 2 , cursorY, "t");
	xls.setLabel( 3 , cursorY, "x");
	xls.setLabel( 4 , cursorY, "y");
	xls.setLabel( 5 , cursorY, "z");
	cursorY++;
		
	detectionList = ts.getDetectionList();
		
	for (i = 0;  i < detectionList.size() ; i++  )
	{
		d = detectionList.get( i );
		xls.setNumber( 2 , cursorY , d.getT() );
		xls.setNumber( 3 , cursorY , d.getX() );
		xls.setNumber( 4 , cursorY , d.getY() );
		xls.setNumber( 5 , cursorY , d.getZ() );

		cursorY++;
	}
    }
    xls.SaveAndClose();

      ///////////////////////////////////////////////////////
     // Save tracks in TrackManager compatible xml format //
    ///////////////////////////////////////////////////////

    trackXMLFile = new File ( folder + FileUtil.separator + f.getName()+"-tracksXML.xml" );
    
    document = XMLUtil.createDocument( true );
    versionElement = XMLUtil.addElement( document.getDocumentElement() , "trackfile" ); 
    versionElement.setAttribute("version", "1");
    trackGroupElement = XMLUtil.addElement( document.getDocumentElement() , "trackgroup" );
    trackGroupElement.setAttribute("description", tg.getDescription() );
    for ( k = 0; k < tg.getTrackSegmentList().size(); k++ ){
    	trackSegment = tg.getTrackSegmentList().get(k)
    	trackElement = XMLUtil.addElement( trackGroupElement , "track" );				
    	trackElement.setAttribute( "id", ""+trackSegment.getId() );
	for ( m = 0; m < trackSegment.getDetectionList().size(); m++ ){					
		detection = trackSegment.getDetectionList().get(m);
		detectionElement = XMLUtil.addElement( trackElement , "detection" );
		detectionElement.setAttribute( "classname", detection.getClass().getName() );
		detection.saveToXML( detectionElement );
	}			
	}
    linklistElement = XMLUtil.addElement( document.getDocumentElement() , "linklist" );
    XMLUtil.saveDocument( document , trackXMLFile );
}


Icy script publication Id : Y6I7C1