Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@romainGuiet
Created February 5, 2021 12:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save romainGuiet/8e5e3450e6aab68075585ec5a820a837 to your computer and use it in GitHub Desktop.
Save romainGuiet/8e5e3450e6aab68075585ec5a820a837 to your computer and use it in GitHub Desktop.
a fake StarDist3D combining StarDist2D+TrackMate+LaRoME
#@File image_path
#@RoiManager rm
#@ CommandService command
#@ Double (label="Nuclei Proba. Threshold", value=0.5) threshold_proba_nuc
#@ Double (label="Nuclei min. intensity (A.U.)", value=10) minInt_nuc
#@Integer (label="Max Frame Gap") frameGap
#@Double (label="Linking Max Distance") linkDistance
#@Integer (label="Gap Closing Max Distance") gapClosingDistance
// authors : olvier.burri & romain.guiet (at) epfl.ch
// requires:
// PTBIOP update site - LaRoME
// StarDist and CSBDeep updates site
IJ.run("Close All", "");
def imp = IJ.openImage(image_path.toString() )
imp.show()
// stack might be z-stack, we convert to time-stack and add frame [1 sec]
def dimensions = imp.getDimensions()
if (dimensions[3] > dimensions[4]) IJ.run(imp, "Properties...", "channels=1 slices="+dimensions[4]+" frames="+dimensions[3]+" pixel_width=1.0000 pixel_height=1.0000 voxel_depth=1.0000 frame=[1 sec]");
res = command.run(StarDist2D, false, "input", imp,
"modelChoice", "Versatile (fluorescent nuclei)",
'probThresh',threshold_proba_nuc,
'nmsThresh',0.1).get()
// Get ROIs from the Manager
def rois = rm.getRoisAsArray() as List
rm.reset()
// Here we filter some rois by intensity
def fitlered_rois = []
rois.each{ roi ->
imp.setPosition( roi.getPosition() );
imp.setRoi(roi)
roi_stats = imp.getStatistics();
println roi_stats.mean
if ( roi_stats.mean > minInt_nuc) {
rm.addRoi(roi)
}
}
// Get updated ROIs from the Manager
rois = rm.getRoisAsArray() as List
// Use TrackMate for tracking, using the rois
def rt = RoiTracker.builder().setRoiList(rois)
.setMeasurementImage(imp)
.setMaxFrameGap(frameGap)
.setLinkingMaxDistance(linkDistance)
.setGapClosingMaxDistance(gapClosingDistance)
.build()
rt.buildSpots()
rt.trackSpots()
rt.renameRois()
//Sort ROI in the manager
rm.runCommand(imp,"Sort");
// Make 3D Labels using Pattern name
//IJ.runMacro('run("ROIs to Measurement Image" , "column_name=Pattern pattern=Track-(.*):.*");')
res = command.run(Rois2MeasurementMap, true, "imp", imp,
"column_name", "Pattern",
'pattern',"Track-(.*):.*")
import ch.epfl.biop.ij2command.*
import ij.*
import de.csbdresden.stardist.*
import de.csbdresden.csbdeep.commands.GenericNetwork
//https://imagej.net/Scripting_TrackMate
import fiji.plugin.trackmate.*
import fiji.plugin.trackmate.tracking.sparselap.*
import fiji.plugin.trackmate.tracking.LAPUtils
import fiji.plugin.trackmate.action.ExportTracksToXML
import groovy.transform.builder.*
import groovy.transform.ToString
import org.apache.commons.io.FilenameUtils
import ij.*
import ij.gui.*
import ij.gui.ShapeRoi
import ij.measure.ResultsTable
import ij.plugin.frame.RoiManager
import ij.plugin.ChannelSplitter
import ij.plugin.RoiEnlarger
import ij.plugin.RoiScaler
import ij.plugin.filter.*
import ij.process.ImageStatistics
/**
* RoiTracker class uses TrackMate LAP Tracker on detected ROIs
*
*/
@ToString(includeNames=true)
@Builder(prefix='set')
class RoiTracker {
List<Roi> roiList
int maxFrameGap = 2
double splittingDistance = 40
double linkingMaxDistance = 40
double gapClosingMaxDistance = 20
boolean isMerge = false
boolean isSplit = true
ImagePlus measurementImage
File outputFolder
Model model
Settings settings
SpotCollection sc
void buildSpots() {
sc = new SpotCollection()
model = new Model()
roiList.eachWithIndex{roi, idx ->
int frame = roi.getPosition() // for stack
IJ.log(""+frame)
def roiPos= measurementImage.getStackIndex( 1, 1, frame)
def ip = measurementImage.getStack().getProcessor( roiPos )
ip.setRoi(roi)
def radius = Math.sqrt( Math.PI / ip.getStatistics().area)
def spot = new Spot( roi.getContourCentroid()[0],roi.getContourCentroid()[1], 1 as double, radius, 50, roi.getName())
spot.putFeature( 'POSITION_T', frame ); // Here its a bug that needs to be solved, should be getTPosition
spot.putFeature( 'MEAN_INTENSITY', ip.getStatistics().mean);
spot.putFeature( 'AREA', ip.getStatistics().area);
spot.putFeature( 'ROI_INDEX', idx );
sc.add(spot, frame)
}
//Add the SpotCollection to the Model
model.beginUpdate()
model.setSpots(sc, true)
model.endUpdate()
println ( model )
println "Spots in model : "+model.getSpots().getNSpots(true)
}
void trackSpots() {
settings = new Settings()
// settings.setFrom(imp)
settings.trackerSettings = LAPUtils.getDefaultLAPSettingsMap()
settings.trackerSettings['MAX_FRAME_GAP'] = maxFrameGap
settings.trackerSettings['SPLITTING_MAX_DISTANCE'] = splittingDistance
settings.trackerSettings['LINKING_MAX_DISTANCE'] = linkingMaxDistance
settings.trackerSettings['GAP_CLOSING_MAX_DISTANCE'] = gapClosingMaxDistance
settings.trackerSettings['ALLOW_TRACK_SPLITTING'] = isSplit
settings.trackerSettings['ALLOW_TRACK_MERGING'] = isMerge
def tracker = new SparseLAPTrackerFactory().create(sc, settings.trackerSettings)
// Run TrackMate and store data into Model
tracker.process()
println "PROCESS done"
def tracks = tracker.getResult()
model.beginUpdate()
model.setTracks(tracks, true)
model.endUpdate()
println "Tracks in model : "+model.getTrackModel().nTracks(true)
}
void renameRois(){
def rm = RoiManager.getInstance()
def trackIDs = model.getTrackModel().trackIDs(false)
trackIDs.each {id ->
println(id + ' --- ')
def trackSpots = model.getTrackModel().trackSpots( id )
// order track's spots by frame
// ( to add corresponding ROIs in order to the roiManager)
def sorted = new ArrayList<Spot>( trackSpots );
def comparator = Spot.frameComparator;
Collections.sort( sorted, comparator );
sorted.each{
def t = it.getFeature( "FRAME" ) as int
def roi_idx = it.getFeature('ROI_INDEX') as int
rm.rename(roi_idx ,"Track-"+IJ.pad(id+1,5)+":Frame-"+IJ.pad(t,5))
//println (roi_idx)
}
}
}
void drawTracks(ImagePlus target) {
def ov = new Overlay()
def trackIDs = model.getTrackModel().trackIDs(false)
trackIDs.each {id ->
println(id + ' --- ')
def edges = model.getTrackModel().trackEdges(id)
edges.each{ edge ->
def x1 = edge.getSource().getFeature('POSITION_X')
def y1 = edge.getSource().getFeature('POSITION_Y')
def t1 = edge.getSource().getFeature('POSITION_T') as int
def x2 = edge.getTarget().getFeature('POSITION_X')
def y2 = edge.getTarget().getFeature('POSITION_Y')
def t2 = edge.getTarget().getFeature('POSITION_T')
def idx = edge.getSource().getFeature('ROI_INDEX') as int
def roi = roiList.get(idx)
ov.add(roi)
def current_line = new Line(x1, y1, x2, y2)
current_line.setPosition(t1)
ov.add(current_line)
}
}
target.setOverlay(ov)
}
ResultsTable obtainTrackResults() {
def rt = new ResultsTable()
def trackIDs = model.getTrackModel().trackIDs(false)
trackIDs.each {id ->
def spots = model.getTrackModel().trackSpots(id).toSorted{ it.getFeature('POSITION_T') }
spots.each{spot ->
rt.incrementCounter()
rt.addLabel( measurementImage.getTitle())
rt.addValue( "Track ID", id)
rt.addValue( "ROI name", spot.getName())
rt.addValue( "Frame", spot.getFeature('POSITION_T'))
rt.addValue( "Mean Intensity", spot.getFeature('MEAN_INTENSITY'))
rt.addValue( "Area", spot.getFeature('AREA'))
}
}
return rt
}
void export(outFile){
ExportTracksToXML.export(model, settings, outFile)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment