Created
February 5, 2021 12:22
-
-
Save romainGuiet/8e5e3450e6aab68075585ec5a820a837 to your computer and use it in GitHub Desktop.
a fake StarDist3D combining StarDist2D+TrackMate+LaRoME
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#@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