Commit f5df793f authored by Daniel Felipe  GONZALEZ OBANDO's avatar Daniel Felipe GONZALEZ OBANDO
Browse files

enabled volume constraint in Plugin GUI

parent 4be794ba
bin
pluginfile-active-contours*.jar
/ActiveContours.jar
......@@ -80,33 +80,26 @@ import plugins.kernel.roi.roi3d.ROI3DStack;
import plugins.nchenouard.spot.Detection;
import vtk.vtkObjectBase;
public class ActiveContours extends EzPlug implements EzStoppable, Block
{
public class ActiveContours extends EzPlug implements EzStoppable, Block {
public static final String CONTOUR_BASE_NAME = "Contour #";
public static final String CONTOUR_ID = "contourId";
private class LocalRegionStatisticsComputer implements Callable<Object>
{
private class LocalRegionStatisticsComputer implements Callable<Object> {
final ActiveContour contour;
final boolean maskBased;
public LocalRegionStatisticsComputer(ActiveContour contour, boolean maskBased)
{
public LocalRegionStatisticsComputer(ActiveContour contour, boolean maskBased) {
this.contour = contour;
this.maskBased = maskBased;
}
@Override
public Object call()
{
try
{
public Object call() {
try {
double cin = contour.computeAverageIntensity(contour instanceof Mesh3D ? regionData : regionDataSummed,
maskBased ? contourMask_buffer : null);
region_cin.put(trackGroup.getValue().getTrackSegmentWithDetection(contour), cin);
}
catch (TopologyException topo)
{
} catch (TopologyException topo) {
System.err.println("Removing a contour. Reason: " + topo.getMessage());
allContoursAtTimeT.remove(contour);
evolvingContoursAtTimeT.remove(contour);
......@@ -115,18 +108,15 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
}
}
private class LocalBackgroundStatisticsComputer implements Callable<Object>
{
private class LocalBackgroundStatisticsComputer implements Callable<Object> {
final ActiveContour contour;
public LocalBackgroundStatisticsComputer(ActiveContour contour)
{
public LocalBackgroundStatisticsComputer(ActiveContour contour) {
this.contour = contour;
}
@Override
public Object call()
{
public Object call() {
TrackSegment segment = trackGroup.getValue().getTrackSegmentWithDetection(contour);
double cout = contour.computeBackgroundIntensity(regionData, contourMask_buffer);
......@@ -137,8 +127,7 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
}
}
private class ContourInitializer implements Callable<Object>
{
private class ContourInitializer implements Callable<Object> {
final ROI roi;
final int z;
final int t;
......@@ -148,8 +137,7 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
final List<TrackSegment> endedTracks;
public ContourInitializer(ROI roi, int z, int t, Tuple3d pixelSize, int convWinSize,
List<TrackSegment> activeTracks, List<TrackSegment> justEndedTracks)
{
List<TrackSegment> activeTracks, List<TrackSegment> justEndedTracks) {
super();
this.roi = roi;
......@@ -161,9 +149,9 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
this.endedTracks = justEndedTracks;
}
// test if the object is colliding an existing contour or if we need to discard it for other reason
private boolean colliding()
{
// test if the object is colliding an existing contour or if we need to discard
// it for other reason
private boolean colliding() {
// // image bounds
// final Rectangle imageBounds = inputData.getBounds2D();
// // minus one (to detect object on border)
......@@ -173,8 +161,7 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
// imageBounds.height -= 2;
// test if object is intersecting with current active contours
for (TrackSegment segment : activeTracks)
{
for (TrackSegment segment : activeTracks) {
// get contour for this active track
final ActiveContour contour = (ActiveContour) segment.getLastDetection();
// get ROI from contour
......@@ -189,8 +176,7 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
}
@Override
public Object call()
{
public Object call() {
// object colliding active contours ? --> discard it
if (colliding())
return null;
......@@ -202,15 +188,13 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
return null;
// does it overlap with a track that terminates in the previous frame?
for (TrackSegment track : endedTracks)
{
for (TrackSegment track : endedTracks) {
final ActiveContour previousContour = (ActiveContour) track.getLastDetection();
// get ROI from contour
final ROI previousContourROI = previousContour.toROI(ROIType.POLYGON, null);
// object is intersecting previous contour ?
if (roi.intersects(previousContourROI))
{
if (roi.intersects(previousContourROI)) {
System.out.println(
"Found link at time " + t + ", position (" + contour.getX() + ";" + contour.getY() + ")");
// add contour to the track
......@@ -230,14 +214,12 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
}
}
private class ContourDuplicator implements Callable<Object>
{
private class ContourDuplicator implements Callable<Object> {
final TrackSegment segment;
final int t;
final int convWinSize;
public ContourDuplicator(TrackSegment segment, int t, int convWinSize)
{
public ContourDuplicator(TrackSegment segment, int t, int convWinSize) {
super();
this.segment = segment;
......@@ -246,8 +228,7 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
}
@Override
public Object call()
{
public Object call() {
Detection detection;
detection = segment.getDetectionAtTime(t);
......@@ -308,19 +289,16 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
public final EzVarDouble convergence_criterion = new EzVarDouble("Convergence criterion", 0.001, 0, 1, 0.0001);
public final EzVarInteger convergence_nbIter = new EzVarInteger("Max. iterations", 100000, 100, 100000, 1000);
public enum ExportROI
{
public enum ExportROI {
NO, ON_INPUT, ON_NEW_IMAGE, AS_LABELS
}
public enum ROIType
{
public enum ROIType {
AREA(ROI2DArea.class), POLYGON(ROI2DPolygon.class);
final Class<? extends ROI> clazz;
private ROIType(Class<? extends ROI> clazz)
{
private ROIType(Class<? extends ROI> clazz) {
this.clazz = clazz;
}
}
......@@ -339,7 +317,7 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
private final HashMap<TrackSegment, Double> volumes = new HashMap<TrackSegment, Double>();
public final EzVarBoolean volume_constraint = new EzVarBoolean("Volume constraint", false);
public final EzVarDouble volume_weight = new EzVarDouble("Volume weight", 0.01, 0,1, 0.01);
public final EzVarDouble volume_weight = new EzVarDouble("Volume weight", 0.01, 0, 1, 0.001);
public final EzButton showTrackManager;
......@@ -375,22 +353,17 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
private long lastVtkGCTime = 0L;
public ActiveContours()
{
public ActiveContours() {
super();
multiThreadService.setThreadName("Active Contours");
showTrackManager = new EzButton("Send to track manager", new ActionListener()
{
showTrackManager = new EzButton("Send to track manager", new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
ThreadUtil.invokeLater(new Runnable()
{
public void actionPerformed(ActionEvent e) {
ThreadUtil.invokeLater(new Runnable() {
@Override
public void run()
{
public void run() {
if (trackGroup.getValue() == null)
return;
if (trackGroup.getValue().getTrackSegmentList().isEmpty())
......@@ -406,14 +379,12 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
});
}
public TrackGroup getTrackGroup()
{
public TrackGroup getTrackGroup() {
return trackGroup.getValue();
}
@Override
public void initialize()
{
public void initialize() {
addEzComponent(showAdvancedOptions);
addEzComponent(input);
......@@ -500,27 +471,25 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
tracking.addVisibilityTriggerTo(tracking_newObjects, true);
addEzComponent(volume_constraint);
tracking.addVisibilityTriggerTo(volume_constraint, true);
addEzComponent(volume_weight);
volume_constraint.addVisibilityTriggerTo(volume_weight, true);
addEzComponent(showTrackManager);
setTimeDisplay(true);
// TODO: we disabled volume constraint feature as it doesn't work and sometime end to crazy contour (Stephane)
volume_constraint.setValue(Boolean.FALSE);
volume_constraint.setEnabled(false);
}
@Override
public void loadParameters(File file)
{
public void loadParameters(File file) {
super.loadParameters(file);
// TODO: disabled as the feature is broken (Stephane)
volume_constraint.setValue(Boolean.FALSE);
}
@Override
public void execute()
{
public void execute() {
output_labels.setValue(null);
volumes.clear();
roiOutput.setValue(null);
......@@ -545,7 +514,8 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
tracks.setDescription("Active contours (" + new Date().toString() + ")");
trackGroup.setValue(tracks);
// initialize the mask buffer once (used to calculate average intensities inside/outside)
// initialize the mask buffer once (used to calculate average intensities
// inside/outside)
final Rectangle3D.Integer bounds3d = inputData.getBounds5D().toRectangle3D().toInteger();
final Rectangle bounds2d = inputData.getBounds2D();
final BooleanMask2D[] maskSlices = new BooleanMask2D[bounds3d.sizeZ];
......@@ -555,11 +525,9 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
contourMask_buffer = new BooleanMask3D(bounds3d, maskSlices);
if (!Icy.getMainInterface().isHeadLess())
{
if (!Icy.getMainInterface().isHeadLess()) {
// replace any ActiveContours Painter object on the sequence by ours
for (Overlay existingOverlay : inputData.getOverlays())
{
for (Overlay existingOverlay : inputData.getOverlays()) {
if (existingOverlay instanceof ActiveContoursOverlay)
existingOverlay.remove();
}
......@@ -577,18 +545,13 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
ROI field = null;
final Sequence boundSource = evolution_bounds.getValue();
if (boundSource != null)
{
if (boundSource != null) {
final List<ROI> rois = boundSource.getROIs();
if (rois.size() > 0)
{
try
{
if (rois.size() > 0) {
try {
field = ROIUtil.merge(rois, BooleanOperator.OR);
}
catch (UnsupportedOperationException e)
{
} catch (UnsupportedOperationException e) {
throw new VarException(evolution_bounds.getVariable(), "Cannot compute the evolution bounds: "
+ e.getMessage()
+ "\nIf you are not sure how to fix this, change this parameter to \"No Sequence\"");
......@@ -597,12 +560,10 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
}
// no specific field ? limit to sequence bounds
if (field == null)
{
if (field == null) {
if (inputData.getSizeZ() == 1)
field = new ROI2DRectangle(0, 0, inputData.getWidth(), inputData.getHeight());
else
{
else {
final ROI3DStack<ROI2DRectangle> field3D = new ROI3DStack<ROI2DRectangle>(ROI2DRectangle.class);
for (int z = 0; z < inputData.getSizeZ() - 1; z++)
......@@ -612,11 +573,11 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
}
}
for (int t = startT; t <= endT; t++)
{
for (int t = startT; t <= endT; t++) {
int iteration;
// if sizeT changed during AC processing (i already did it to shorthen processing time :p)
// if sizeT changed during AC processing (i already did it to shorthen
// processing time :p)
if (t >= inputData.getSizeT())
break;
......@@ -676,27 +637,21 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
int maxId = 0;
// get maximum id
for (ROI roi : roiOutput.getValue())
{
try
{
for (ROI roi : roiOutput.getValue()) {
try {
// get object id
final int contourId = Integer.parseInt(roi.getProperty(CONTOUR_ID));
if (contourId > maxId)
maxId = contourId;
}
catch (Exception e)
{
} catch (Exception e) {
// ignore
}
}
// then fix ROI names
final int nbPaddingDigits = (int) Math.floor(Math.log10(maxId));
for (ROI roi : roiOutput.getValue())
{
try
{
for (ROI roi : roiOutput.getValue()) {
try {
// get object id
final int contourId = Integer.parseInt(roi.getProperty(CONTOUR_ID));
final String roiName = roi.getName();
......@@ -706,19 +661,15 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
else
roi.setName(
CONTOUR_BASE_NAME + StringUtil.toString(contourId, nbPaddingDigits) + " (" + roiName + ")");
}
catch (Exception e)
{
} catch (Exception e) {
// ignore
}
}
if (getUI() != null)
{
if (getUI() != null) {
Sequence out = inputData;
switch (output_rois.getValue())
{
switch (output_rois.getValue()) {
case ON_NEW_IMAGE:
out = SequenceUtil.getCopy(inputData);
out.setName(inputData.getName() + " + Active contours");
......@@ -760,23 +711,17 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
regionDataSummed = null;
}
boolean executeMultiThread(Collection<Callable<Object>> tasks, String messageOnError) throws Exception
{
try
{
boolean executeMultiThread(Collection<Callable<Object>> tasks, String messageOnError) throws Exception {
try {
// force wait completion for all tasks
for (Future<Object> res : multiThreadService.invokeAll(tasks))
res.get();
return true;
}
catch (InterruptedException e)
{
} catch (InterruptedException e) {
// restore the interrupted flag
Thread.currentThread().interrupt();
}
catch (Exception e)
{
} catch (Exception e) {
if (StringUtil.isEmpty(messageOnError))
throw e;
......@@ -787,8 +732,7 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
return false;
}
private void initData(int t)
{
private void initData(int t) {
final int edgeChannel = edge_c.getValue().intValue();
final int regionChannel = region_c.getValue().intValue();
......@@ -819,39 +763,33 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
regionData = new Sequence(OMEUtil.createOMEXMLMetadata(inputData.getOMEXMLMetadata()), "region data");
// convert float data rescaled to [0..1]
for (int z = 0; z < bounds.sizeZ; z++)
{
for (int z = 0; z < bounds.sizeZ; z++) {
IcyBufferedImage img;
img = currentFrame.getImage(0, z, edgeChannel);
img = IcyBufferedImageUtil.convertType(img, DataType.FLOAT, new Scaler[] {edgeScaler});
img = IcyBufferedImageUtil.convertType(img, DataType.FLOAT, new Scaler[] { edgeScaler });
edgeData.setImage(0, z, img);
img = currentFrame.getImage(0, z, regionChannel);
img = IcyBufferedImageUtil.convertType(img, DataType.FLOAT, new Scaler[] {regionScaler});
img = IcyBufferedImageUtil.convertType(img, DataType.FLOAT, new Scaler[] { regionScaler });
regionData.setImage(0, z, img);
}
try
{
try {
// smooth the signal
Sequence gaussian = Kernels1D.CUSTOM_GAUSSIAN.createGaussianKernel1D(1).toSequence();
Convolution1D.convolve(edgeData, gaussian, gaussian, null);
Convolution1D.convolve(regionData, gaussian, gaussian, null);
}
catch (Exception e)
{
} catch (Exception e) {
System.err.println("Warning: error while smoothing the signal: " + e.getMessage());
}
// summed region data (use to accelerate intensity calculations)
regionDataSummed = SequenceUtil.getCopy(regionData);
for (int z = 0; z < bounds.sizeZ; z++)
{
for (int z = 0; z < bounds.sizeZ; z++) {
final float[] regionDataSliceSummed = regionDataSummed.getDataXYAsFloat(0, z, 0);
for (int j = 0; j < bounds.sizeY; j++)
{
for (int j = 0; j < bounds.sizeY; j++) {
// start at the second pixel (index 1) of each line
int offset = (j * bounds.sizeX) + 1;
......@@ -865,31 +803,27 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
}
}
private void initCurrentContours(final int t)
{
private void initCurrentContours(final int t) {
// prepare parameters
final int convWinSize = convergence_winSize.getValue().intValue() * 2;
// use multi threading to initiate current contours (by duplicating ones from previous frame)
// use multi threading to initiate current contours (by duplicating ones from
// previous frame)
final List<Callable<Object>> tasks = new ArrayList<Callable<Object>>();
try
{
try {
// duplicate contours from the previous frame
for (TrackSegment segment : trackGroup.getValue().getTrackSegmentList())
tasks.add(new ContourDuplicator(segment, t, convWinSize));
// execute tasks
executeMultiThread(tasks, "couldn't duplicate a contour");
}
catch (Exception e)
{
} catch (Exception e) {
e.printStackTrace();
System.err.println("Warning: (reason: " + e.getMessage() + "). Moving on...");
}
}
private void addNewContours(final int t)
{
private void addNewContours(final int t) {
// prepare parameters
final TrackGroup tg = trackGroup.getValue();
final List<TrackSegment> tracks = trackGroup.getValue().getTrackSegmentList();
......@@ -910,47 +844,38 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
final List<Callable<Object>> tasks = new ArrayList<Callable<Object>>();
final List<TrackSegment> newTracks = new ArrayList<TrackSegment>();
try
{
try {
// initialize new contours
for (ROI roi : objects)
tasks.add(new ContourInitializer(roi, currentZ, t, pixelSize, convWinSize, activeTracks,
justEndedTracks));
// force wait completion for all tasks
for (Future<Object> res : multiThreadService.invokeAll(tasks))
{
for (Future<Object> res : multiThreadService.invokeAll(tasks)) {
final TrackSegment track = (TrackSegment) res.get();
// a new track was created ? --> add it
if (track != null)
newTracks.add(track);
}
}
catch (InterruptedException e)
{
} catch (InterruptedException e) {
// restore the interrupted flag
Thread.currentThread().interrupt();
}
catch (Exception e)
{
} catch (Exception e) {
e.printStackTrace();
System.err.println("Warning: couldn't initialize a contour (reason: " + e.getMessage() + ").");
}
// add new created tracks
synchronized (tg)
{
synchronized (tg) {
for (TrackSegment track : newTracks)
tg.addTrackSegment(track);
}
synchronized (region_cin)
{
synchronized (region_cin) {
for (TrackSegment track : newTracks)
region_cin.put(track, Double.valueOf(0d));
}
synchronized (region_cout)
{
synchronized (region_cout) {
for (TrackSegment track : newTracks)
region_cout.put(track, Double.valueOf(0d));
}
......@@ -959,14 +884,11 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
/**
* Returns all {@link TrackSegment} ending at the specified time point
*/
private List<TrackSegment> getTracksEndingAt(List<TrackSegment> tracks, int t)
{
private List<TrackSegment> getTracksEndingAt(List<TrackSegment> tracks, int t) {
final List<TrackSegment> result = new ArrayList<TrackSegment>();
if (t >= 0)
{
for (TrackSegment track : tracks)
{
if (t >= 0) {
for (TrackSegment track : tracks) {
// get last detection for this track
final Detection detection = track.getLastDetection();
......@@ -979,13 +901,11 @@ public class ActiveContours extends EzPlug implements EzStoppable, Block
return result;
}
private List<ROI> getRoisOf(int t)
{
private List<ROI> getRoisOf(int t) {
List<ROI> result = CollectionUtil.asArrayList(roiInput.getValue());
// protocol mode, no ROI ? --> cannot continue
if (result.isEmpty())
{