diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 109b3db2a12014d3f01146592dd98a94f0991899..fccfa6a6aedbf02467344129fa2435fbd8ed4daa 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,6 +2,7 @@ stages:
- build
- test
- deploy
+ - versioning
variables:
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
@@ -21,10 +22,21 @@ maven:
paths:
- target/*.jar
+release:
+ image: maven:3.6.3-jdk-11
+ stage: versioning
+ when: manual
+ script:
+ - curl --fail https://raw.githubusercontent.com/scijava/scijava-scripts/main/release-version.sh | bash -s -- --dry-run
+# script with dry-run option
+# - curl --fail https://raw.githubusercontent.com/scijava/scijava-scripts/main/release-version.sh | bash -s -- --dry-run
+
+
pages:
image: maven:3.6.3-jdk-11
stage: deploy
+ when: manual
script:
- mvn javadoc:javadoc
- mkdir .public
@@ -35,16 +47,59 @@ pages:
- public
-selectionParamaterSweep:
+ParamaterSweep_mouche:
image: maven:3.6.3-jdk-11
stage: test
when: manual
script:
- - mvn -Dtest=ParameterSweep test
+ - mvn -Dtest=ParameterSweepMouche test
artifacts:
paths:
- target/*.csv
+
+ParamaterSweep_cochlée:
+ image: maven:3.6.3-jdk-11
+ stage: test
+ when: manual
+ script:
+ - mvn -Dtest=ParameterSweepCochlee2 test
+ artifacts:
+ paths:
+ - target/*.csv
+
+ParamaterSweep_culture:
+ image: maven:3.6.3-jdk-11
+ stage: test
+ when: manual
+ script:
+ - mvn -Dtest=ParameterSweepCulture test
+ artifacts:
+ paths:
+ - target/*.csv
+
+ParamaterSweep_organoid:
+ image: maven:3.6.3-jdk-11
+ stage: test
+ when: manual
+ script:
+ - mvn -Dtest=ParameterSweepOrganoid test
+ artifacts:
+ paths:
+ - target/*.csv
+
+
+ParamaterSweep_phantom:
+ image: maven:3.6.3-jdk-11
+ stage: test
+ when: manual
+ script:
+ - mvn -Dtest=ParameterSweepPhantom test
+ artifacts:
+ paths:
+ - target/*.csv
+
+
doubleParamaterSweep:
image: maven:3.6.3-jdk-11
stage: test
diff --git a/README.md b/README.md
index c178a77e220d80b11eef9d6e369121becde0d68d..9cad74eb1c504f4773fdf9ac309698097f2b229b 100644
--- a/README.md
+++ b/README.md
@@ -5,8 +5,8 @@
The program takes a 3D stack as input and generates the projection of all surfaces contained in the 3D stack as 2D
images. That process can be divided into 3 stages :
-- first the selection of all the pixels belonging to any surface
-- second the regrouping of those selected pixels to produce a height map for each surface
+- first the selection of all the pixels belonging to any selectedPixels
+- second the regrouping of those selected pixels to produce a height map for each selectedPixels
- third the use of each height map to extract a projection according to a given projection's method (only MIP for now).

diff --git a/doc/Organoid.tif b/doc/Organoid.tif
new file mode 100644
index 0000000000000000000000000000000000000000..7835f2ddfd6e66c44469d387eb0dad922f1ef946
Binary files /dev/null and b/doc/Organoid.tif differ
diff --git a/pom.xml b/pom.xml
index 6fa0e3145087d1f7e6b8a82e83b6f9cb8fca57c7..b2933c0db3268856f3112662bce8738b16e8ca35 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
<groupId>org.example</groupId>
<artifactId>zellige-core</artifactId>
- <version>1.0-SNAPSHOT</version>
+ <version>1.0.0-SNAPSHOT</version>
<name>Zellige-core</name>
@@ -77,6 +77,14 @@
</excludes>
</configuration>
</plugin>
+ <!-- <plugin>-->
+ <!-- <groupId>org.apache.maven.plugins</groupId>-->
+ <!-- <artifactId>maven-compiler-plugin</artifactId>-->
+ <!-- <configuration>-->
+ <!-- <source>8</source>-->
+ <!-- <target>8</target>-->
+ <!-- </configuration>-->
+ <!-- </plugin>-->
</plugins>
</build>
@@ -102,6 +110,12 @@
</exclusion>
</exclusions>
</dependency>
+ <!-- https://mvnrepository.com/artifact/org.jzy3d/jzy3d-svm-mapper -->
+ <dependency>
+ <groupId>org.jzy3d</groupId>
+ <artifactId>jzy3d-svm-mapper</artifactId>
+ <version>2.0.0</version>
+ </dependency>
<dependency>
<groupId>org.smurn</groupId>
@@ -211,6 +225,21 @@
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.9</version>
</dependency>
+ <dependency>
+ <groupId>org.openjfx</groupId>
+ <artifactId>javafx-controls</artifactId>
+ <version>17.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openjfx</groupId>
+ <artifactId>javafx-fxml</artifactId>
+ <version>17.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openjfx</groupId>
+ <artifactId>javafx-swing</artifactId>
+ <version>18-ea+4</version>
+ </dependency>
<!-- <dependency>-->
<!-- <groupId>org.jacoco</groupId>-->
@@ -250,6 +279,8 @@
<license.organizationName>Institut Pasteur</license.organizationName>
<license.copyrightOwners>Institut Pasteur</license.copyrightOwners>
<enforcer.skip>true</enforcer.skip>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
</properties>
<developers>
diff --git a/src/main/java/fr/pasteur/ida/zellige/Main.java b/src/main/java/fr/pasteur/ida/zellige/Main.java
index 0e66c540b8a975da2532fb0e190b58edb4aabd3a..b48a91a5b49c870bad44928a102d5029d2d828cb 100644
--- a/src/main/java/fr/pasteur/ida/zellige/Main.java
+++ b/src/main/java/fr/pasteur/ida/zellige/Main.java
@@ -25,15 +25,16 @@ public class Main
{
- public static < T extends RealType < T > & NativeType < T > > void main( String[] args ) throws Exception
+ public static < T extends RealType< T > & NativeType< T > > void main( String[] args ) throws Exception
{
// Launch ImageJ.
ImageJ ij = new ImageJ();
// Input of the image.
- final String imagePath = args[ 0 ]; /* The image path goes here !!!! */
-
+ final String imagePath =// "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\files\\SNR\\snr_000\\multiSurfaces\\phantoms_snr0.mat.tif";
+ args[ 0 ]; /* The image path goes here !!!! */
+ System.out.println( imagePath );
/* JY version for opening files. */
final SCIFIOImgPlus< ? > imgPlus = IO.openImgs( imagePath ).get( 0 );
@@ -41,8 +42,8 @@ public class Main
/* User Parameters AKA arguments to run the program*/
- double amplitude = Double.parseDouble( args[ 1 ] );
- double otsu = Double.parseDouble( args[ 2 ] );
+ int amplitude = Integer.parseInt( args[ 1 ] );
+ int otsu = Integer.parseInt( args[ 2 ] );
int islandSize = Integer.parseInt( args[ 3 ] );
int connexity = Integer.parseInt( args[ 4 ] );
double sigmaXY = Double.parseDouble( args[ 5 ] );
@@ -95,10 +96,10 @@ public class Main
DisplayParameters displayParameters = new DisplayParameters(
true,
- false,
- false,
true,
- false );
+ true,
+ true,
+ true, true );
IJ.log( "Type: " + imgPlus.firstElement().getClass().toGenericString() );
if ( stackImage.numDimensions() == 3 )// Is it a stack ?
@@ -107,10 +108,21 @@ public class Main
( stackImage, stackImage.factory() );
rse.select( pretreatmentParameters, classificationParameters, postTreatmentParameters );
rse.construct( constructionParameters );
+// for ( ReferenceSurface< T > referenceSurface : rse.getReferenceSurfaces() )
+// {
+// writeHeightMap( referenceSurface.getzMap(), imgPlus.getName(), referenceSurface.getIndex() );
+// }
if ( ! GraphicsEnvironment.isHeadless() )
{
- rse.project( projectionParameters, displayParameters );
+ try
+ {
+ rse.project( projectionParameters, displayParameters );
+ }
+ catch ( Exception e )
+ {
+ System.out.println( e.getMessage() );
+ }
}
}
else
diff --git a/src/main/java/fr/pasteur/ida/zellige/ReferenceSurfaceExtraction.java b/src/main/java/fr/pasteur/ida/zellige/ReferenceSurfaceExtraction.java
index f02dcbfde5ce8d4240161a86223dd9ae6aa3287c..e094ffe92641945fb23c0e9c170ba689dcc783a0 100644
--- a/src/main/java/fr/pasteur/ida/zellige/ReferenceSurfaceExtraction.java
+++ b/src/main/java/fr/pasteur/ida/zellige/ReferenceSurfaceExtraction.java
@@ -13,16 +13,25 @@ import fr.pasteur.ida.zellige.steps.projection.NoPossibleDisplayException;
import fr.pasteur.ida.zellige.steps.projection.ProjectionParameters;
import fr.pasteur.ida.zellige.steps.projection.ReferenceSurfaceProjection;
import fr.pasteur.ida.zellige.steps.selection.Selection;
+import fr.pasteur.ida.zellige.steps.selection.classification.AmplitudeClassification;
+import fr.pasteur.ida.zellige.steps.selection.classification.Classification;
import fr.pasteur.ida.zellige.steps.selection.classification.ClassificationParameters;
+import fr.pasteur.ida.zellige.steps.selection.classification.OtsuClassification;
import fr.pasteur.ida.zellige.steps.selection.exception.DataValidationException;
import fr.pasteur.ida.zellige.steps.selection.exception.EmptyOutputException;
import fr.pasteur.ida.zellige.steps.selection.exception.NoClassificationException;
+import fr.pasteur.ida.zellige.steps.selection.postTreatment.PostTreatment;
import fr.pasteur.ida.zellige.steps.selection.postTreatment.PostTreatmentParameters;
+import fr.pasteur.ida.zellige.steps.selection.pretreatment.Pretreatment;
import fr.pasteur.ida.zellige.steps.selection.pretreatment.PretreatmentParameters;
import net.imglib2.RandomAccessibleInterval;
+import net.imglib2.img.Img;
import net.imglib2.img.ImgFactory;
+import net.imglib2.img.array.ArrayImgFactory;
import net.imglib2.type.NativeType;
+import net.imglib2.type.logic.BitType;
import net.imglib2.type.numeric.RealType;
+import net.imglib2.type.numeric.real.FloatType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,7 +49,13 @@ public class ReferenceSurfaceExtraction< T extends RealType< T > & NativeType< T
private final RandomAccessibleInterval< T > input;
private final ImgFactory< T > factory;
+ private final String filter = "GaussianBlur";
+ private final double filterParameter = 2;
+ private Img< FloatType > pretreatedImg;
+ private Img< FloatType > amplitudeImg;
+ private Img< FloatType > otsuImg;
+ // private FloatType otsuValue;
private Pixels[][] maximums;
private final static double adequacy = 1;
@@ -58,6 +73,9 @@ public class ReferenceSurfaceExtraction< T extends RealType< T > & NativeType< T
private int SS_smallSurfaces;
private int SS_goodSurfaces;
private static final String derivativeMethod = FORWARD;
+ private Img< BitType > selectedAmplitude;
+ private Img< BitType > selectedOtsu;
+ private Img< BitType > selectionOutput;
public ReferenceSurfaceExtraction( RandomAccessibleInterval< T > input, ImgFactory< T > factory )
@@ -71,14 +89,52 @@ public class ReferenceSurfaceExtraction< T extends RealType< T > & NativeType< T
return adequacy;
}
+ public void computeClassificationImages() throws DataValidationException
+ {
+ pretreatedImg = Pretreatment.run( input, filterParameter );
+ computeImages( pretreatedImg );
+ }
+
+ private void computeImages( RandomAccessibleInterval< FloatType > input ) throws DataValidationException
+ {
+ ImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() );
+ amplitudeImg = AmplitudeClassification.computeAmplitudeImage( input, factory );
+ otsuImg = OtsuClassification.computeOtsuImage( input, factory );
+ }
+
+ public void runAmplitudeClassification( int userThreshold )
+ {
+ LOGGER.info( "Amplitude threshold value after user ={}", userThreshold );
+ selectedAmplitude = AmplitudeClassification.applyThreshold( amplitudeImg, userThreshold );
+ }
+
+ public void runOtsuClassification( int userThreshold )
+ {
+ selectedOtsu = OtsuClassification.applyLocalThreshold( pretreatedImg, otsuImg, userThreshold );
+ }
+
+ public void runInterClassification()
+ {
+ selectionOutput = Classification.interClassification( selectedAmplitude, selectedAmplitude.factory(), selectedOtsu );
+ System.out.println( "The selected output has been changed" );
+ }
+
+ public void runPostTreatment( PostTreatmentParameters postTreatmentParameters ) throws DataValidationException
+ {
+ maximums = PostTreatment.run( selectionOutput, postTreatmentParameters );
+ }
+
+
public void select( PretreatmentParameters pretreatmentParameters, ClassificationParameters classificationParameters, PostTreatmentParameters postTreatmentParameters ) throws NoClassificationException, EmptyOutputException, DataValidationException
{
/* First step : Pixel selection */
LOGGER.info( "Running selection..." );
maximums = Selection.run( input, pretreatmentParameters, classificationParameters, postTreatmentParameters );
// displayMaximums( maximums );
+// writeSelectedPixels( maximums, "Phantom" );
}
+
public void construct( ConstructionParameters[] constructionParameters ) throws NoSurfaceFoundException
{
LOGGER.info( "Running construction..." );
@@ -109,6 +165,7 @@ public class ReferenceSurfaceExtraction< T extends RealType< T > & NativeType< T
referenceSurfaces.addAll( ConstructionCompletion.run( input, factory, finalSurfaces ) );
// referenceSurfaceInstantiation( finalSurfaces );
LOGGER.debug( " Constructions of {} surfaces.", referenceSurfaces.size() );
+
}
@@ -122,6 +179,17 @@ public class ReferenceSurfaceExtraction< T extends RealType< T > & NativeType< T
}
}
+
+ public void setMaximums( Pixels[][] maximums )
+ {
+ this.maximums = maximums;
+ }
+
+ public Img< BitType > getSelectionOutput()
+ {
+ return selectionOutput;
+ }
+
public ArrayList< ReferenceSurface< T > > getReferenceSurfaces()
{
return referenceSurfaces;
@@ -203,6 +271,16 @@ public class ReferenceSurfaceExtraction< T extends RealType< T > & NativeType< T
return SS_startingOS_count;
}
+ public String getFilter()
+ {
+ return filter;
+ }
+
+ public double getFilterParameter()
+ {
+ return filterParameter;
+ }
+
}
diff --git a/src/main/java/fr/pasteur/ida/zellige/command/Zellige.java b/src/main/java/fr/pasteur/ida/zellige/command/Zellige.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d26a67db57ad126ab29996dd79ccc98a11a772c
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/command/Zellige.java
@@ -0,0 +1,77 @@
+package fr.pasteur.ida.zellige.command;
+
+
+import fr.pasteur.ida.zellige.gui.MainAppFrame;
+import net.imagej.DatasetService;
+import net.imagej.ImageJ;
+import net.imagej.display.ImageDisplayService;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.scijava.command.Command;
+import org.scijava.log.LogService;
+import org.scijava.plugin.Parameter;
+import org.scijava.plugin.Plugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+
+@Plugin( type = Command.class, menuPath = "Plugins>Zellige>" )
+public class Zellige< T extends RealType< T > & NativeType< T > > implements Command
+{
+
+ @Parameter
+ private ImageJ ij;
+
+ @Parameter
+ private LogService logService;
+
+ @Parameter
+ private ImageDisplayService imageDisplayService;
+
+ @Parameter
+ private ImageDisplayService image;
+
+ @Parameter
+ DatasetService datasetService;
+
+
+ public static void main( String[] args ) throws IOException
+ {
+ String currentFolder = FileSystems.getDefault()
+ .getPath( "" )
+ .toAbsolutePath()
+ .toString();
+ String imageFilePath = "doc/Organoid.tif";
+
+ // Launch ImageJ.
+ ImageJ ij = new ImageJ();
+ ij.launch( args );
+
+ // Load the image.
+ Object obj = ij.io().open( new File( currentFolder, imageFilePath ).getAbsolutePath() );
+
+ // for large images
+// final SCIFIOConfig config = new SCIFIOConfig();
+// config.imgOpenerSetImgModes( SCIFIOConfig.ImgMode.PLANAR );
+//
+// final Dataset obj = ij.scifio().datasetIO().open( imageFilePath, config );
+ // Display it.
+ ij.ui().show( obj );
+
+ ij.command().run( Zellige.class, true );
+ }
+
+ @Override
+ public void run()
+ {
+
+ // Launch JavaFX interface
+ MainAppFrame app = new MainAppFrame( ij, image, logService );
+ app.setTitle( "Zellige" );
+ app.init();
+
+ }
+}
+
+
diff --git a/src/main/java/fr/pasteur/ida/zellige/command/ZelligeCommand.java b/src/main/java/fr/pasteur/ida/zellige/command/ZelligeCommand.java
index 39f4992982316f6de6cb85892cde5ab3b005e884..ac863a1a4a9269b4f5a4ed5da7bc24e8274e2408 100644
--- a/src/main/java/fr/pasteur/ida/zellige/command/ZelligeCommand.java
+++ b/src/main/java/fr/pasteur/ida/zellige/command/ZelligeCommand.java
@@ -41,11 +41,11 @@ public class ZelligeCommand< T extends RealType< T > & NativeType< T > > extends
@Parameter
private LogService logService;
- @Parameter( label = "Amplitude threshold", min = "0", max = "2", stepSize = "0.1" )
- private double amplitude = 1;
+ @Parameter( label = "Amplitude threshold", min = "0", max = "255", stepSize = "1" )
+ private int amplitude = 5;
- @Parameter( label = "Otsu threshold", min = "0", max = "2", stepSize = "0.1" )
- private double otsu = 0.1;
+ @Parameter( label = "Otsu threshold", min = "0", max = "255", stepSize = "1" )
+ private int otsu = 5;
@Parameter( label = "XY blur radius", min = "0", max = "10" )
private int sigmaXY = 1;
@@ -141,6 +141,23 @@ public class ZelligeCommand< T extends RealType< T > & NativeType< T > > extends
// Fixed parameters for now...
String filter = "GaussianBlur";
double filterParameter = 2;
+ IJ.log( "Input image : " + dataset.getName() );
+ IJ.log( "filter : " + filter );
+ IJ.log( "filter parameter : " + filterParameter );
+ IJ.log( "amplitude : " + amplitude );
+ IJ.log( "threshold : " + otsu );
+ IJ.log( "connexity : " + connexity );
+ IJ.log( "island size : " + islandSize );
+ IJ.log( "sigmaXY : " + sigmaXY );
+ IJ.log( "sigmaZ : " + sigmaZ );
+ IJ.log( "starting os size1 : " + startingOsSize1 );
+ IJ.log( "overlap1 :" + overlap1 );
+ IJ.log( "connexityRate1 :" + connexityRate1 );
+ IJ.log( "starting os size2 : " + startingOsSize2 );
+ IJ.log( "overlap2 :" + overlap2 );
+ IJ.log( "connexityRate2 :" + connexityRate2 );
+ IJ.log( "surface Minimum size factor : " + surfaceMinSizeFactor );
+ IJ.log( "delta : " + delta );
PretreatmentParameters pretreatmentParameters = null;
try
{
@@ -187,7 +204,7 @@ public class ZelligeCommand< T extends RealType< T > & NativeType< T > > extends
false,
false,
true,
- false );
+ false, true );
if ( img.numDimensions() == 3 )// Is it a stack ?
diff --git a/src/main/java/fr/pasteur/ida/zellige/command/ZelligeCommandGui.java b/src/main/java/fr/pasteur/ida/zellige/command/ZelligeCommandGui.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c1cc1dee9ff3e4dc5d263fcc40d6a74902825de
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/command/ZelligeCommandGui.java
@@ -0,0 +1,54 @@
+package fr.pasteur.ida.zellige.command;
+
+import net.imagej.ImageJ;
+import net.imagej.display.ImageDisplayService;
+import net.imagej.ops.OpService;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.scijava.command.ContextCommand;
+import org.scijava.log.LogService;
+import org.scijava.plugin.Parameter;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+
+//@Plugin( type = ZelligeCommandGui.class, name = "Zellige", menuPath = "Plugins > Process > Zellige" )
+public class ZelligeCommandGui< T extends RealType< T > & NativeType< T > > extends ContextCommand
+{
+
+ @Parameter
+ protected OpService ops;
+ @Parameter
+ private ImageDisplayService imageDisplayService;
+ @Parameter
+ private LogService logService;
+
+ public static void main( String[] args ) throws IOException
+ {
+ String currentFolder = FileSystems.getDefault()
+ .getPath( "" )
+ .toAbsolutePath()
+ .toString();
+ String imageFilePath = "doc/Cochlée1.tif";
+
+ // Launch ImageJ.
+ ImageJ ij = new ImageJ();
+ ij.launch( args );
+
+ // Load the image.
+ Object obj = ij.io().open( new File( currentFolder, imageFilePath ).getAbsolutePath() );
+
+ // Display it.
+ ij.ui().show( obj );
+
+
+ ij.command().run( ZelligeCommandGui.class, true );
+ }
+
+ @Override
+ public void run()
+ {
+
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/element/Projection.java b/src/main/java/fr/pasteur/ida/zellige/element/Projection.java
index 888d2cb0ebcb42963224b8bbe9caaa2b88c43caa..1a7b9ce4ab1aecf0ba3cfed5f95c1cd06eba7f3f 100644
--- a/src/main/java/fr/pasteur/ida/zellige/element/Projection.java
+++ b/src/main/java/fr/pasteur/ida/zellige/element/Projection.java
@@ -2,38 +2,37 @@ package fr.pasteur.ida.zellige.element;
import net.imglib2.img.Img;
import net.imglib2.type.NativeType;
+import net.imglib2.type.logic.BitType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.numeric.integer.UnsignedShortType;
public class Projection< T extends RealType< T > & NativeType< T > >
{
private Img< T > projection;
- private Img< UnsignedShortType > projectionHeightMap;
- private Img< T > HeightMapSubVolumeMask;
- private Img< T > extractedHeightMapSubStack;
-// private int index;
-// private int delta;
-// private String projectionType;
+ private Img< UnsignedShortType > extractedHeightMap;
+ private Img< T > segmentedSurface;
+ private Img< T > reduced3DSpace;
+ private Img< BitType > segmentedSurfaceMask;
- public Img< T > getHeightMapSubVolumeMask()
+ public Img< T > getSegmentedSurface()
{
- return HeightMapSubVolumeMask;
+ return segmentedSurface;
}
- public void setHeightMapSubVolumeMask( Img< T > heightMapSubVolumeMask )
+ public void setSegmentedSurface( Img< T > segmentedSurface )
{
- this.HeightMapSubVolumeMask = heightMapSubVolumeMask;
+ this.segmentedSurface = segmentedSurface;
}
- public Img< UnsignedShortType > getProjectionHeightMap()
+ public Img< UnsignedShortType > getExtractedHeightMap()
{
- return projectionHeightMap;
+ return extractedHeightMap;
}
- public void setProjectionHeightMap( Img< UnsignedShortType > projectionHeightMap )
+ public void setExtractedHeightMap( Img< UnsignedShortType > extractedHeightMap )
{
- this.projectionHeightMap = projectionHeightMap;
+ this.extractedHeightMap = extractedHeightMap;
}
public Img< T > get()
@@ -46,15 +45,23 @@ public class Projection< T extends RealType< T > & NativeType< T > >
this.projection = projection;
}
- public Img< T > getExtractedHeightMapSubStack()
+ public Img< T > getReduced3DSpace()
{
- return extractedHeightMapSubStack;
+ return reduced3DSpace;
}
- public void setExtractedHeightMapSubStack( Img< T > extractedHeightMapSubStack )
+ public void setReduced3DSpace( Img< T > reduced3DSpace )
{
- this.extractedHeightMapSubStack = extractedHeightMapSubStack;
+ this.reduced3DSpace = reduced3DSpace;
}
+ public Img< BitType > getSegmentedSurfaceMask()
+ {
+ return segmentedSurfaceMask;
+ }
+ public void setSegmentedSurfaceMask( Img< BitType > segmentedSurfaceMask )
+ {
+ this.segmentedSurfaceMask = segmentedSurfaceMask;
+ }
}
diff --git a/src/main/java/fr/pasteur/ida/zellige/element/Surface.java b/src/main/java/fr/pasteur/ida/zellige/element/Surface.java
index f8e44e2d7097227b222b6bf5970f3545f11b8059..b99ebd67b26690b1abbfc037b43a9d2981bf0b2c 100644
--- a/src/main/java/fr/pasteur/ida/zellige/element/Surface.java
+++ b/src/main/java/fr/pasteur/ida/zellige/element/Surface.java
@@ -118,10 +118,45 @@ public class Surface
}
}
- return inCommon / (double) count;
+ return inCommon / ( double ) count;
}
-
-
+
+ public boolean isTheSameSurfaceAs( Surface other )
+ {
+ for ( int i = 0; i <= this.getHeight() - 1; i++ )
+ {
+ SurfaceLine refLine = this.get( i );
+ if ( refLine != null )
+ {
+ SurfaceLine toTest = other.get( i );
+ if ( toTest != null )
+ {
+
+ for ( int j = 0; j < refLine.getLength(); j++ )
+ {
+ Pixels refPixels = refLine.get( j );
+ if ( refPixels != null )
+ {
+ Pixels pixelsToTest = toTest.get( j );
+ if ( pixelsToTest != null )
+ {
+// return false;
+// }
+ if ( ! refPixels.equals( pixelsToTest ) )
+ {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ }
+ return true;
+ }
+
/**
* Checks if this object shares a majority of {@link Pixels} with an other {@link Surface} object.
@@ -305,8 +340,8 @@ public class Surface
}
Surface other = (Surface ) obj;
{
- System.out.println(overlappingRate( other ));
return overlappingRate( other ) == 1;
+// return isTheSameSurfaceAs( other );
}
}
}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/ConstructionController.java b/src/main/java/fr/pasteur/ida/zellige/gui/ConstructionController.java
new file mode 100644
index 0000000000000000000000000000000000000000..a12299d0b10c9f3ec3294cf68bbb51db3eb8feef
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/ConstructionController.java
@@ -0,0 +1,76 @@
+package fr.pasteur.ida.zellige.gui;
+
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+public class ConstructionController implements Initializable
+{
+ @FXML
+ private ParameterSliderDouble c1;
+
+ @FXML
+ private ParameterSliderDouble c2;
+
+ @FXML
+ private ParameterSliderInteger r1;
+
+ @FXML
+ private ParameterSliderInteger r2;
+
+ @FXML
+ private ParameterSliderDouble st1;
+
+ @FXML
+ private ParameterSliderDouble st2;
+
+ @FXML
+ private ParameterSliderDouble surfaceSize;
+ public ConstructionController()
+ {
+
+ }
+
+ @Override
+ public void initialize( URL url, ResourceBundle resourceBundle )
+ {
+
+ }
+
+ public double getC1()
+ {
+ return c1.getSlider().getValue();
+ }
+
+ public double getC2()
+ {
+ return c2.getSlider().getValue();
+ }
+
+ public int getR1()
+ {
+ return ( int ) r1.getSlider().getValue();
+ }
+
+ public int getR2()
+ {
+ return ( int ) r2.getSlider().getValue();
+ }
+
+ public double getSt1()
+ {
+ return st1.getSlider().getValue();
+ }
+
+ public double getSt2()
+ {
+ return st2.getSlider().getValue();
+ }
+
+ public double getSurfaceSize()
+ {
+ return surfaceSize.getSlider().getValue();
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/DisplayController.java b/src/main/java/fr/pasteur/ida/zellige/gui/DisplayController.java
new file mode 100644
index 0000000000000000000000000000000000000000..782c99c42d0fb8756e896d5ad0c91d43313966f8
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/DisplayController.java
@@ -0,0 +1,33 @@
+package fr.pasteur.ida.zellige.gui;
+
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.CheckBox;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+public class DisplayController implements Initializable
+{
+
+ @FXML
+ private CheckBox extractedSurface;
+
+ @FXML
+ private CheckBox heightMapStack;
+
+ @FXML
+ private CheckBox heightMapStackMask;
+
+ @FXML
+ private CheckBox heightmap;
+
+ @FXML
+ private CheckBox projection;
+
+ @Override
+ public void initialize( URL url, ResourceBundle resourceBundle )
+ {
+
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/FileCombobox.java b/src/main/java/fr/pasteur/ida/zellige/gui/FileCombobox.java
new file mode 100644
index 0000000000000000000000000000000000000000..f427c2b53468d3e80097df5f4b34df4dd95db89d
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/FileCombobox.java
@@ -0,0 +1,38 @@
+package fr.pasteur.ida.zellige.gui;
+
+import javafx.scene.control.ComboBox;
+import net.imagej.Dataset;
+
+public class FileCombobox extends ComboBox< Dataset >
+{
+
+ public void setBehavior()
+ {
+ /* Control of the file comboBox*/
+// setOnMousePressed( event ->
+// setAndDisplayDatasetChoices() );
+//
+// activeDataset.getSelectionModel().selectedItemProperty().addListener( ( observableValue, oldValue, newValue ) ->
+// {
+// LOGGER.debug( "selectedItemProperty : old value = {}, new value = {} " , oldValue, newValue);
+// int index = activeDataset.getSelectionModel().getSelectedIndex();
+// if ( oldValue == null && newValue != null )
+// {
+// LOGGER.debug( "case 1" );
+// Dataset dataset = datasets.get(index);
+// selectAndLoadNewImage( dataset );
+// }
+// else if ( oldValue != null && newValue != null && !oldValue.equals( newValue ))
+// {
+// LOGGER.debug( "case 2" );
+// Dataset dataset = datasets.get(index);
+// selectAndLoadNewImage( dataset );
+// }
+// else if (oldValue == null )
+// {
+// LOGGER.debug("case 3");
+// showError( new NoInputException() );
+// }
+// } );
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/ImageFXDisplay.java b/src/main/java/fr/pasteur/ida/zellige/gui/ImageFXDisplay.java
new file mode 100644
index 0000000000000000000000000000000000000000..fabbfa8e81fc68ba308afd6e9324071eeb49962d
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/ImageFXDisplay.java
@@ -0,0 +1,97 @@
+package fr.pasteur.ida.zellige.gui;
+
+import javafx.scene.image.ImageView;
+import javafx.scene.image.PixelFormat;
+import javafx.scene.image.PixelWriter;
+import javafx.scene.image.WritableImage;
+import net.imglib2.Cursor;
+import net.imglib2.IterableInterval;
+import net.imglib2.type.logic.BitType;
+
+public class ImageFXDisplay
+{
+
+
+ private final IterableInterval< BitType > input;
+ private final ImageView[] imageViews;
+ private final int width;
+ private final int height;
+ private final int depth;
+
+
+ public ImageFXDisplay( IterableInterval< BitType > input )
+ {
+ this.input = input;
+
+ width = ( int ) input.dimension( 0 );
+ height = ( int ) input.dimension( 1 );
+ depth = ( int ) input.dimension( 2 );
+ this.imageViews = new ImageView[ depth ];
+
+ }
+
+ public void set()
+ {
+ int[] data2 = convert2( input );
+ for ( int z = 0; z < depth; z++ )
+ {
+ WritableImage writableImage = new WritableImage( width, height );
+ PixelWriter pixelWriter = writableImage.getPixelWriter();
+ pixelWriter.setPixels( 0, 0, width, height, PixelFormat.getIntArgbInstance(), data2, height * width * z, width );
+ this.imageViews[ z ] = new ImageView( writableImage );
+ setImageViews( this.imageViews[ z ] );
+ }
+
+ }
+
+
+ public int[] convert2( IterableInterval< BitType > input )
+ {
+ int[] data = new int[ height * width * depth ];
+ Cursor< BitType > cursor = input.cursor();
+ int index = 0;
+ while ( cursor.hasNext() )
+ {
+ cursor.fwd();
+ if ( cursor.get().get() )
+ {
+ data[ index++ ] = ( 0xFFFFFFFF );
+ }
+ else
+ {
+ data[ index++ ] = 0xFF000000;
+ }
+
+
+ }
+ return data;
+ }
+
+ public ImageView[] getImageViews()
+ {
+ return this.imageViews;
+ }
+
+ public void setImageViews( ImageView imageView )
+ {
+ imageView.setPreserveRatio( true );
+ setFit( imageView );
+
+ imageView.setSmooth( true );
+ imageView.setCache( true );
+ }
+
+ public void setFit( ImageView imageView )
+ {
+ if ( width >= height )
+ {
+ imageView.setFitWidth( 280 );
+ }
+ else
+ {
+ imageView.setFitHeight( 280 );
+ }
+ }
+
+
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/MainAppFrame.java b/src/main/java/fr/pasteur/ida/zellige/gui/MainAppFrame.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1fb9fcf3f68fada41ec4c51fad46b3232b384c8
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/MainAppFrame.java
@@ -0,0 +1,105 @@
+package fr.pasteur.ida.zellige.gui;
+
+import fr.pasteur.ida.zellige.steps.selection.exception.DataValidationException;
+import javafx.application.Platform;
+import javafx.embed.swing.JFXPanel;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Scene;
+import javafx.scene.layout.AnchorPane;
+import net.imagej.ImageJ;
+import net.imagej.display.ImageDisplayService;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.scijava.log.LogService;
+import org.scijava.plugin.Parameter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.*;
+import java.io.IOException;
+import java.util.ResourceBundle;
+
+public class MainAppFrame extends JFrame
+{
+
+ private final static Logger LOGGER = LoggerFactory.getLogger( MainAppFrame.class );
+ private final ImageJ ij;
+ private final ImageDisplayService image;
+ @Parameter
+ private final LogService logService;
+ private JFXPanel fxPanel;
+ private Scene scene;
+
+ public MainAppFrame( ImageJ ij, ImageDisplayService image, LogService logService )
+ {
+ this.ij = ij;
+ this.image = image;
+ this.logService = logService;
+ }
+
+ /**
+ * Create the JFXPanel that make the link between Swing (IJ) and JavaFX
+ * plugin.
+ */
+ public void init()
+ {
+ this.fxPanel = new JFXPanel();
+ this.add( this.fxPanel );
+ this.setVisible( true );
+ LOGGER.info( "JFRAME" );
+
+ // The call to runLater() avoid a mix between JavaFX thread and Swing
+ // thread.
+ Platform.runLater( this::initFX );
+ }
+
+ public < T extends RealType< T > & NativeType< T > > void initFX()
+ {
+ // Init the root layout
+ try
+ {
+ ResourceBundle bundle = ResourceBundle.getBundle( "gui" );// access to properties f
+ FXMLLoader loader = new FXMLLoader( MainAppFrame.class.getClassLoader().getResource( "fr.pasteur.ida.zellige.gui.view/Main.fxml" ), bundle );
+
+ AnchorPane rootLayout = loader.load();
+
+ // Get the controller and add an ImageJ context to it.
+ MainController< T > controller = loader.getController();
+ controller.setMainApp( this );
+
+
+ // Show the scene containing the root layout.
+ scene = new Scene( rootLayout );
+ this.fxPanel.setScene( scene );
+
+ // Resize the JFrame to the JavaFX scene
+ this.setSize( ( int ) scene.getWidth() + 20, ( int ) scene.getHeight() + 30 );
+ controller.initExtraction();
+ }
+ catch ( IOException | DataValidationException e )
+ {
+ e.printStackTrace();
+ }
+ }
+
+
+ public LogService getLogService()
+ {
+ return logService;
+ }
+
+ public ImageJ getIj()
+ {
+ return ij;
+ }
+
+ public ImageDisplayService getImage()
+ {
+ return image;
+ }
+
+ public Scene getScene()
+ {
+ return scene;
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/MainController.java b/src/main/java/fr/pasteur/ida/zellige/gui/MainController.java
new file mode 100644
index 0000000000000000000000000000000000000000..ee21be338d3334d4c05f5d8f265b49c758a2e8f7
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/MainController.java
@@ -0,0 +1,305 @@
+package fr.pasteur.ida.zellige.gui;
+
+import fr.pasteur.ida.zellige.ReferenceSurfaceExtraction;
+import fr.pasteur.ida.zellige.element.Pixels;
+import fr.pasteur.ida.zellige.element.ReferenceSurface;
+import fr.pasteur.ida.zellige.element.Surface;
+import fr.pasteur.ida.zellige.gui.exception.NoInputException;
+import fr.pasteur.ida.zellige.gui.task.*;
+import fr.pasteur.ida.zellige.steps.construction.exception.NoSurfaceFoundException;
+import fr.pasteur.ida.zellige.steps.projection.NoPossibleDisplayException;
+import fr.pasteur.ida.zellige.steps.selection.exception.DataValidationException;
+import fr.pasteur.ida.zellige.steps.selection.exception.EmptyOutputException;
+import fr.pasteur.ida.zellige.steps.selection.exception.NoClassificationException;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Button;
+import javafx.scene.control.ComboBox;
+import javafx.scene.text.Font;
+import javafx.scene.text.FontWeight;
+import net.imagej.Dataset;
+import net.imagej.ImgPlus;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import net.imglib2.util.Util;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.ResourceBundle;
+
+public class MainController< T extends RealType< T > & NativeType< T > > implements Initializable
+{
+ private final static Logger LOGGER = LoggerFactory.getLogger( MainController.class );
+
+ @FXML
+ ComboBox< Dataset > activeDataset;
+
+ @FXML
+ private Button runButton;
+
+ @FXML
+ private ConstructionController constructionController;
+
+ @FXML
+ private ProjectionController projectionController;
+
+ @FXML
+ private SelectionController< T > selectionController;
+
+ private ReferenceSurfaceExtraction< T > extraction;
+
+ private Dataset currentDataset;
+
+ private MainAppFrame mainAppFrame;
+
+ private Pixels[][] pixels;
+
+
+ @Override
+ public void initialize( URL url, ResourceBundle resourceBundle )
+ {
+ // run button initialization
+ runButton.setOnAction( actionEvent ->
+ {
+ try
+ {
+ run();
+ }
+ catch ( DataValidationException | EmptyOutputException | NoClassificationException | NoSurfaceFoundException | NoPossibleDisplayException e )
+ {
+ showError( e );
+ }
+ } );
+
+ /* Control of the files comboBox*/
+ activeDataset.setStyle( "-fx-font: 13px \"System\";" );
+ activeDataset.setOnMousePressed( event ->
+ setAndDisplayDatasetChoices() );// the list of open Fiji images is updated
+
+ activeDataset.getSelectionModel().selectedItemProperty().addListener( ( observableValue, oldValue, newValue ) ->
+ {
+ LOGGER.debug( "selectedItemProperty : old value = {}, new value = {} ", oldValue, newValue );
+ if ( oldValue == null && newValue != null )
+ {
+ LOGGER.debug( "case 1" );
+ selectAndLoadNewImage( activeDataset.getSelectionModel().getSelectedItem() );
+ }
+ else if ( oldValue != null && newValue != null && ! oldValue.equals( newValue ) )
+ {
+ LOGGER.debug( "case 2" );
+ selectAndLoadNewImage( newValue );
+ }
+ activeDataset.getEditor().setFont( Font.font( "Symbol", FontWeight.EXTRA_BOLD, 9 ) );
+ } );
+
+
+ }
+
+ public void initExtraction() throws DataValidationException
+ {
+ LOGGER.debug( "Init Extraction" );
+ Dataset dataset = mainAppFrame.getImage().getActiveDataset();
+ if ( dataset == null )
+ {
+ showError( new NoInputException() );
+ return;
+ }
+// datasets.add( dataset );
+ activeDataset.getItems().add( dataset );
+ LOGGER.debug( "Init Extraction completed" );
+ }
+
+ public void run() throws DataValidationException, EmptyOutputException, NoClassificationException, NoSurfaceFoundException, NoPossibleDisplayException
+ {
+ long[] dims = new long[ currentDataset.numDimensions() ];
+ currentDataset.dimensions( dims );
+ mainAppFrame.getLogService().info( "Zellige received the image: " + currentDataset.getName() );
+ mainAppFrame.getLogService().info( "Size: " + Util.printInterval( currentDataset ) );
+ mainAppFrame.getLogService().info( "Type: " + currentDataset.firstElement().getClass().toGenericString() );
+ mainAppFrame.getLogService().info( "Dimensionality: " + currentDataset.numDimensions() + "D" );
+ for ( int d = 0; d < currentDataset.numDimensions(); d++ )
+ {
+ mainAppFrame.getLogService().info( " - dimension " + d + ": [" + currentDataset.axis( d ).type() + "], 1 unit = " + currentDataset.averageScale( d ) + " " + currentDataset.axis( d ).unit() );
+ }
+ // Fixed parameters
+ String filter = "GaussianBlur";
+ double filterParameter = 2;
+ // End of fixed parameters
+ int connexity = 4;
+
+ double startingOsSize1 = constructionController.getSt1();
+ int overlap1 = constructionController.getR1();
+ double connexityRate1 = constructionController.getC1();
+ double startingOsSize2 = constructionController.getSt2();
+ int overlap2 = constructionController.getR2();
+ double connexityRate2 = constructionController.getC2();
+ double surfaceMinSizeFactor = constructionController.getSurfaceSize();
+ int delta = projectionController.getDelta();
+ String method = projectionController.getMethod();
+ /* Print parameters.*/
+ mainAppFrame.getLogService().info( "Input : " + currentDataset.getName() );
+ mainAppFrame.getLogService().info( "filter : " + filter );
+ mainAppFrame.getLogService().info( "filterParameter : " + filterParameter );
+ mainAppFrame.getLogService().info( "amplitude : " + getAmplitude() );
+ mainAppFrame.getLogService().info( "threshold : " + getOtsu() );
+ mainAppFrame.getLogService().info( "connexity : " + connexity );
+ mainAppFrame.getLogService().info( "islandSize : " + getIsland() );
+ mainAppFrame.getLogService().info( "sigmaXY : " + getSigmaXY() );
+ mainAppFrame.getLogService().info( "sigmaZ : " + getSigmaZ() );
+ mainAppFrame.getLogService().info( "startingOsSize1 : " + startingOsSize1 );
+ mainAppFrame.getLogService().info( "overlap1 : " + overlap1 );
+ mainAppFrame.getLogService().info( "connexityRate1 : " + connexityRate1 );
+ mainAppFrame.getLogService().info( "startingOsSize2 : " + startingOsSize2 );
+ mainAppFrame.getLogService().info( "overlap2 : " + overlap2 );
+ mainAppFrame.getLogService().info( "connexityRate2 : " + connexityRate2 );
+ mainAppFrame.getLogService().info( "surfaceMinimumSizeFactor : " + surfaceMinSizeFactor );
+ mainAppFrame.getLogService().info( "delta : " + delta + "\n" );
+ /* End of Print parameters.*/
+
+
+ AbstractTask< Pixels[][] > runPostTreatmentTask = new RunPostTreatmentTask<>( extraction, getSigmaXY(), getSigmaZ(), getIsland(), connexity );
+ runPostTreatmentTask.setOnSucceeded( workerStateEvent ->
+ {
+ AbstractTask< ArrayList< Surface > > runFirstConstructionTask = new RunFirstConstructionTask(
+ runPostTreatmentTask.getValue(),
+ startingOsSize1,
+ overlap1,
+ connexityRate1,
+ surfaceMinSizeFactor );
+ runFirstConstructionTask.setOnSucceeded( workerStateEvent2 ->
+ {
+ AbstractTask< ArrayList< Surface > > runSecondConstructionTask = new RunSecondConstructionTask(
+ runFirstConstructionTask.getValue(),
+ startingOsSize2,
+ overlap2,
+ connexityRate2,
+ surfaceMinSizeFactor );
+ runSecondConstructionTask.setOnSucceeded( workerStateEvent3 ->
+ {
+ ImgPlus< T > input = ( ImgPlus< T > ) currentDataset.getImgPlus();
+ AbstractTask< ArrayList< ReferenceSurface< T > > > constructionCompletionTask = new ConstructionCompletionTask<>( input, input.factory(), runSecondConstructionTask.getValue() );
+ constructionCompletionTask.setOnSucceeded( workerStateEvent4 ->
+ {
+ extraction.getReferenceSurfaces().addAll( constructionCompletionTask.getValue() );
+ AbstractTask< Void > projectionTask = new ProjectionTask<>( constructionCompletionTask.getValue(), delta, method,
+ projectionController.getProjection(),
+ projectionController.getRawHeightmap(),
+ projectionController.getExtractedHeightMap(),
+ projectionController.getReduced3DSpace(),
+ projectionController.getSegmentedSurface(),
+ projectionController.getSegmentedSurfaceMask(),
+ projectionController.getDelta2() );
+ projectionTask.start();
+ } );
+ constructionCompletionTask.start();
+ } );
+ runSecondConstructionTask.start();
+
+ } );
+ runFirstConstructionTask.start();
+ } );
+ runPostTreatmentTask.start();
+
+ }
+
+ private void showError( Exception exception )
+ {
+ Alert alert = new Alert( Alert.AlertType.ERROR );
+ alert.setTitle( "Error alert" );
+ alert.setHeaderText( exception.getMessage() );
+ alert.showAndWait();
+ }
+
+ public void setAndDisplayDatasetChoices()
+ {
+ AbstractTask< ArrayList< Dataset > > displayTask = new DisplayDatasetChoicesTask( mainAppFrame.getImage() );
+ displayTask.setOnSucceeded( workerStateEvent ->
+ {
+ LOGGER.debug( "Datasets displayed successfully" );
+ ObservableList< Dataset > list = FXCollections.observableArrayList( displayTask.getValue() );
+ activeDataset.setItems( list );
+ LOGGER.debug( "item selected : list size = " + list.size() );
+ if ( list.isEmpty() )
+ {
+ showError( new NoInputException() );
+ }
+ } );
+ displayTask.start();
+
+ }
+
+ public void selectAndLoadNewImage( Dataset dataset )
+ {
+ AbstractTask< Dataset > setCurrentDatasetTask = new SetCurrentDatasetTask( dataset );
+ setCurrentDatasetTask.setOnSucceeded( workerStateEvent ->
+ {
+ this.currentDataset = setCurrentDatasetTask.getValue();
+ LOGGER.debug( "Dataset setting successful" );
+ if ( currentDataset != null )
+ {
+ selectionController.disableSliders();
+ AbstractTask< ReferenceSurfaceExtraction< T > > startExtraction = new CreateExtractionTask<>( currentDataset, getAmplitude(), getOtsu() );
+ startExtraction.setOnSucceeded( workerStateEvent2 ->
+ {
+ this.extraction = startExtraction.getValue();
+ LOGGER.debug( "Input image loaded" );
+ activeDataset.getSelectionModel().select( currentDataset );
+ selectionController.set( this.extraction );
+ selectionController.displayClassification();
+ selectionController.enableParameters();
+ activeDataset.setDisable( false );
+ } );
+ startExtraction.start();
+ }
+ else
+ {
+ LOGGER.debug( "show error!!!" );
+ showError( new NoInputException() );
+ }
+ } );
+ if ( dataset != currentDataset )
+ {
+ selectionController.disableSliders();
+ activeDataset.setDisable( true );
+ setCurrentDatasetTask.start();
+ }
+ }
+
+ public void setMainApp( MainAppFrame mainAppFrame )
+ {
+ this.mainAppFrame = mainAppFrame;
+ }
+
+ public int getAmplitude()
+ {
+ return ( int ) selectionController.getAmplitude().getSlider().getValue();
+ }
+
+ public int getOtsu()
+ {
+ return ( int ) selectionController.getOtsu().getSlider().getValue();
+ }
+
+ public int getIsland()
+ {
+ return ( int ) selectionController.getIsland().getSlider().getValue();
+ }
+
+ public int getSigmaXY()
+ {
+ return ( int ) selectionController.getXyBlur().getSlider().getValue();
+ }
+
+ public int getSigmaZ()
+ {
+ return ( int ) selectionController.getzBlur().getSlider().getValue();
+ }
+
+
+}
+
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/ParameterSlider.java b/src/main/java/fr/pasteur/ida/zellige/gui/ParameterSlider.java
new file mode 100644
index 0000000000000000000000000000000000000000..a561753c562ad92bd439bfbe86f98597adcce954
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/ParameterSlider.java
@@ -0,0 +1,182 @@
+package fr.pasteur.ida.zellige.gui;
+
+import javafx.beans.NamedArg;
+import javafx.beans.property.StringProperty;
+import javafx.css.PseudoClass;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.control.Label;
+import javafx.scene.control.Slider;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.GridPane;
+
+import java.io.IOException;
+
+public abstract class ParameterSlider extends GridPane
+{
+
+ public static String INTERVAL1 = "[0-9]|[1-4][0-9]|[5][0]";
+ private final String name;
+ private final int minorTickUnit;
+ private final double majorTickUnit, increment, defaultValue, min, max;
+ @FXML
+ private Label label;// Contains the parameter name
+ @FXML
+ private Slider slider;
+ @FXML
+ private TextField textField;
+ private StringProperty userValue;
+ private Number previousValue = 1;
+ private String interval;
+ private PseudoClass errorClass = PseudoClass.getPseudoClass( "error" );
+
+ public ParameterSlider( @NamedArg( "name" ) String name,
+ @NamedArg( "min" ) double min,
+ @NamedArg( "max" ) double max,
+ @NamedArg( "major" ) double majorTickUnit,
+ @NamedArg( "minor" ) int minorTickUnit,
+ @NamedArg( "increment" ) double increment,
+ @NamedArg( "default" ) double defaultValue,
+ @NamedArg( "interval" ) String interval )
+ {
+ this.name = name;
+ this.majorTickUnit = majorTickUnit;
+ this.minorTickUnit = minorTickUnit;
+ this.min = min;
+ this.max = max;
+ this.increment = increment;
+ this.defaultValue = defaultValue;
+ this.interval = interval;
+ FXMLLoader fxmlLoader = new FXMLLoader( ParameterSlider.class.getClassLoader().getResource( "fr.pasteur.ida.zellige.gui.view/ParameterSlider.fxml" ) );
+ fxmlLoader.setRoot( this );
+ fxmlLoader.setController( this );
+ try
+ {
+ fxmlLoader.load();
+ }
+ catch ( IOException e )
+ {
+ e.printStackTrace();
+ }
+ }
+
+
+ @FXML
+ public void initialize()
+ {
+ this.label.setText( name );
+ slider.setMin( min );
+ slider.setMax( max );
+ slider.setBlockIncrement( increment );
+ slider.setValue( defaultValue );
+ slider.setShowTickMarks( true );
+ slider.setShowTickLabels( true );
+ slider.setMajorTickUnit( majorTickUnit );
+ slider.setMinorTickCount( minorTickUnit );
+ slider.setSnapToTicks( false );
+ userValue = textFieldProperty();
+ textField.getStyleClass().add( "error" );
+ bindProperties();
+ listenerSetting();
+ }
+
+
+ /**
+ * Allows the user to be notified if the input value is not in the slider range
+ */
+ public void listenerSetting()
+ {
+ this.userValueProperty().addListener( event ->
+ {
+ System.out.println( "Changed" );
+ this.getTextField().pseudoClassStateChanged(
+ this.getErrorClass(), ! this.getTextField().getText().matches( this.getInterval() )
+ );
+ } );
+ }
+
+ public abstract void bindProperties();
+
+
+ public boolean hasChanged( Number newValue )
+ {
+ if ( ! getSlider().isValueChanging() && previousValue != newValue )
+ {
+ previousValue = newValue;
+ return true;
+ }
+ return false;
+ }
+
+
+ public void enable()
+ {
+ this.getSlider().setDisable( false );
+ this.getTextField().setDisable( false );
+ }
+
+ public void disable()
+ {
+ this.getSlider().setDisable( true );
+ this.getTextField().setDisable( true );
+ }
+
+ public StringProperty textFieldProperty()
+ {
+ return textField.textProperty();
+ }
+
+ public String getLabelText()
+ {
+ return labelProperty().get();
+ }
+
+ public StringProperty labelProperty()
+ {
+ return label.textProperty();
+
+ }
+
+ public PseudoClass getErrorClass()
+ {
+ return errorClass;
+ }
+
+ public TextField getTextField()
+ {
+ return textField;
+ }
+
+ public Slider getSlider()
+ {
+ return slider;
+ }
+
+ public void setSlider( Slider slider )
+ {
+ this.slider = slider;
+ }
+
+ public String getUserValue()
+ {
+ return userValue.get();
+ }
+
+ public void setUserValue( String userValue )
+ {
+ this.userValue.set( userValue );
+ }
+
+ public StringProperty userValueProperty()
+ {
+ return userValue;
+ }
+
+ public String getInterval()
+ {
+ return interval;
+ }
+}
+
+
+
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/ParameterSliderDouble.java b/src/main/java/fr/pasteur/ida/zellige/gui/ParameterSliderDouble.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d1f6ac3061d4fb2eca497bfcefdd676ffa473ae
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/ParameterSliderDouble.java
@@ -0,0 +1,51 @@
+package fr.pasteur.ida.zellige.gui;
+
+import javafx.beans.NamedArg;
+import javafx.beans.binding.Bindings;
+import javafx.util.StringConverter;
+import org.apache.commons.math3.util.Precision;
+
+public class ParameterSliderDouble extends ParameterSlider
+{
+
+
+ public ParameterSliderDouble( @NamedArg( "name" ) String name,
+ @NamedArg( "min" ) double min,
+ @NamedArg( "max" ) double max,
+ @NamedArg( "major" ) double majorTickUnit,
+ @NamedArg( "minor" ) int minorTickUnit,
+ @NamedArg( "increment" ) double increment,
+ @NamedArg( "default" ) double defaultValue,
+ @NamedArg( "interval" ) String interval )
+ {
+ super( name, min, max, majorTickUnit, minorTickUnit, increment, defaultValue, interval );
+ }
+
+ public void bindProperties()
+ {
+ Bindings.bindBidirectional( this.userValueProperty(), this.getSlider().valueProperty(), new StringConverter< Number >()
+ {
+ final double oldValue = getSlider().valueProperty().doubleValue();
+
+ @Override
+ public String toString( Number number )
+ {
+ System.out.println( Precision.round( number.doubleValue(), 1 ) );
+ return String.valueOf( Precision.round( number.doubleValue(), 1 ) );
+ }
+
+ @Override
+ public Number fromString( String s )
+ {
+ try
+ {
+ return Double.parseDouble( s );
+ }
+ catch ( NumberFormatException e )
+ {
+ return oldValue;// set the slider value at the old value
+ }
+ }
+ } );
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/ParameterSliderInteger.java b/src/main/java/fr/pasteur/ida/zellige/gui/ParameterSliderInteger.java
new file mode 100644
index 0000000000000000000000000000000000000000..8674d64ba070898640132767cfb5f2dc0e467035
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/ParameterSliderInteger.java
@@ -0,0 +1,50 @@
+package fr.pasteur.ida.zellige.gui;
+
+import javafx.beans.NamedArg;
+import javafx.beans.binding.Bindings;
+import javafx.util.StringConverter;
+
+public class ParameterSliderInteger extends ParameterSlider
+{
+ public ParameterSliderInteger( @NamedArg( "name" ) String name,
+ @NamedArg( "min" ) double min,
+ @NamedArg( "max" ) double max,
+ @NamedArg( "major" ) double majorTickUnit,
+ @NamedArg( "minor" ) int minorTickUnit,
+ @NamedArg( "increment" ) double increment,
+ @NamedArg( "default" ) double defaultValue,
+ @NamedArg( "interval" ) String interval )
+ {
+ super( name, min, max, majorTickUnit, minorTickUnit, increment, defaultValue, interval );
+ }
+
+
+ public void bindProperties()
+ {
+ Bindings.bindBidirectional( this.userValueProperty(), this.getSlider().valueProperty(), new StringConverter< Number >()
+ {
+ final int oldValue = getSlider().valueProperty().intValue();
+
+ @Override
+ public String toString( Number number )
+ {
+ return String.valueOf( number.intValue() );
+ }
+
+ @Override
+ public Number fromString( String s )
+ {
+ try
+ {
+ return Integer.parseInt( s );
+ }
+ catch ( NumberFormatException e )
+ {
+ return oldValue;// set the slider value at the old value
+ }
+ }
+ } );
+ }
+
+
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/ProjectionController.java b/src/main/java/fr/pasteur/ida/zellige/gui/ProjectionController.java
new file mode 100644
index 0000000000000000000000000000000000000000..a3dbfcbf9793c2aae224927f3a051624006900b6
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/ProjectionController.java
@@ -0,0 +1,105 @@
+package fr.pasteur.ida.zellige.gui;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.CheckBox;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.Spinner;
+import javafx.scene.control.SpinnerValueFactory;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+public class ProjectionController implements Initializable
+{
+
+
+ @FXML
+ private Spinner< Integer > deltaSpinner;
+
+ @FXML
+ private ComboBox< String > methodComboBox;
+
+ @FXML
+ private CheckBox extractedHeightMap;
+
+ @FXML
+ private CheckBox segmentedSurface;
+
+ @FXML
+ private CheckBox reduced3DSpace;
+
+ @FXML
+ private CheckBox segmentedSurfaceMask;
+
+ @FXML
+ private CheckBox projection;
+
+ @FXML
+ private CheckBox rawHeightMap;
+
+ @FXML
+ private Spinner< Integer > delta2;
+
+ @Override
+ public void initialize( URL url, ResourceBundle resourceBundle )
+ {
+ SpinnerValueFactory< Integer > valueFactory =//TODO spinner start at 0
+ new SpinnerValueFactory.IntegerSpinnerValueFactory( 1, 30, 0 );
+ deltaSpinner.setValueFactory( valueFactory );
+ ObservableList< String > list = FXCollections.observableArrayList( "MIP", "Mean" );
+ methodComboBox.setItems( list );
+ methodComboBox.getSelectionModel().selectFirst();
+ SpinnerValueFactory< Integer > valueFactory2 =//TODO spinner start at 0
+ new SpinnerValueFactory.IntegerSpinnerValueFactory( 1, 30, 0 );
+ delta2.setValueFactory( valueFactory2 );
+ }
+
+
+ public String getMethod()
+ {
+ return methodComboBox.getValue();
+ }
+
+ public int getDelta()
+ {
+ return deltaSpinner.getValue();
+ }
+
+ public int getDelta2()
+ {
+ return delta2.getValue();
+ }
+
+ public Boolean getSegmentedSurface()
+ {
+ return segmentedSurface.isSelected();
+ }
+
+ public Boolean getReduced3DSpace()
+ {
+ return reduced3DSpace.isSelected();
+ }
+
+ public Boolean getSegmentedSurfaceMask()
+ {
+ return segmentedSurfaceMask.isSelected();
+ }
+
+ public Boolean getRawHeightmap()
+ {
+ return rawHeightMap.isSelected();
+ }
+
+ public Boolean getProjection()
+ {
+ return projection.isSelected();
+ }
+
+ public Boolean getExtractedHeightMap()
+ {
+ return extractedHeightMap.isSelected();
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/SelectionController.java b/src/main/java/fr/pasteur/ida/zellige/gui/SelectionController.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e3e70805e265c01a834792d6cd280c9c3b3d72a
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/SelectionController.java
@@ -0,0 +1,196 @@
+package fr.pasteur.ida.zellige.gui;
+
+import fr.pasteur.ida.zellige.ReferenceSurfaceExtraction;
+import fr.pasteur.ida.zellige.gui.task.AbstractTask;
+import fr.pasteur.ida.zellige.gui.task.ComputeWithNewAmplitudeValueTask;
+import fr.pasteur.ida.zellige.gui.task.ComputeWithNewOtsuValueTask;
+import fr.pasteur.ida.zellige.gui.task.ImageFXDisplayTask;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.geometry.Pos;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.FlowPane;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+public class SelectionController< T extends RealType< T > & NativeType< T > > implements Initializable
+{
+
+ private final static Logger LOGGER = LoggerFactory.getLogger( SelectionController.class );
+ @FXML
+ private ParameterSliderInteger amplitude;
+
+ @FXML
+ private ParameterSliderInteger island;
+
+ @FXML
+ private ParameterSliderInteger otsu;
+
+ @FXML
+ private FlowPane stack;
+
+ @FXML
+ private ParameterSliderInteger xyBlur;
+
+ @FXML
+ private ParameterSliderInteger zBlur;
+
+ @FXML
+ private ZSlicesSlider zSlices;
+
+
+ private ImageView[] imageViews;
+
+ private ReferenceSurfaceExtraction< T > extraction;
+
+
+ private int width;
+
+ @Override
+ public void initialize( URL url, ResourceBundle resourceBundle )
+ {
+ /* Amplitude slider initialization */
+
+ amplitude.getSlider().valueProperty().addListener( ( observableValue, number, newValue ) ->
+ {
+ if ( amplitude.hasChanged( newValue ) )
+ {
+ computeWithNewAmplitudeValue( newValue.intValue() );
+ }
+ } );
+
+ /* Otsu slider initialization */
+ otsu.getSlider().valueProperty().addListener( ( observableValue, number, newValue ) ->
+ {
+ if ( otsu.hasChanged( newValue ) )
+ {
+ computeWithNewOtsuValue( newValue.intValue() );
+ }
+ } );
+
+
+ stack.setAlignment( Pos.CENTER );
+
+ // section Slider initialization
+
+ zSlices.getSlider().valueProperty().addListener( ( observableValue, number, newValue ) ->
+ {
+ int newZValue = newValue.intValue();
+ if ( zSlices.hasChanged( newZValue ) )
+ {
+ System.out.println( "children n° " + newZValue );
+ refreshDisplayOfSelectedPixels();
+ }
+ } );
+ }
+
+ public void computeWithNewAmplitudeValue( int value )
+ {
+ AbstractTask< Void > compute = new ComputeWithNewAmplitudeValueTask<>( extraction, value );
+ compute.setOnSucceeded( workerStateEvent ->
+ refreshDisplayOfSelectedPixels() );
+ compute.start();
+ }
+
+ public void computeWithNewOtsuValue( int value )
+ {
+ AbstractTask< Void > compute = new ComputeWithNewOtsuValueTask<>( extraction, value );
+ compute.setOnSucceeded( workerStateEvent ->
+ refreshDisplayOfSelectedPixels() );
+ compute.start();
+ }
+
+
+ public void displayClassification()
+ {
+ AbstractTask< ImageView[] > task = new ImageFXDisplayTask( extraction.getSelectionOutput() );
+ task.setOnSucceeded( workerStateEvent ->
+ {
+ stack.getChildren().clear();
+ imageViews = task.getValue();
+ if ( ! stack.getChildren().isEmpty() )
+ {
+ System.out.println( "The stack is not empty" );
+ stack.getChildren().remove( 0 );
+ }
+ ImageView i = imageViews[ 0 ];
+ stack.getChildren().add( i );
+ width = ( int ) i.boundsInParentProperty().get().getWidth();
+ this.zSlices.getSlider().setMaxWidth( width );
+ this.zSlices.getSlider().setVisible( true );
+ } );
+ task.start();
+ }
+
+ /**
+ * Displays the slice of the classified stack according to the value of the Z Slider.
+ */
+ public void refreshDisplayOfSelectedPixels()
+ {
+ AbstractTask< ImageView[] > task = new ImageFXDisplayTask( extraction.getSelectionOutput() );
+ task.setOnSucceeded( workerStateEvent ->
+ {
+ imageViews = task.getValue();
+ this.stack.getChildren().clear();// Removal of previous stack
+ ImageView i = imageViews[ zSlices.userValue ];
+// stack.getChildren().addAll( task.getValue() ); // Addition of new classified stack
+ stack.getChildren().add( i ); // display of selected z slice
+ LOGGER.debug( "Refresh Display successful with " + imageViews.length + " slices" );
+ } );
+ task.start();
+ }
+
+ public void setSliceNumber( int depth )
+ {
+ zSlices.setWidth( depth - 1 );
+ }
+
+ public void set( ReferenceSurfaceExtraction< T > extraction )
+ {
+
+ this.extraction = extraction;
+ this.setSliceNumber( ( int ) extraction.getSelectionOutput().dimension( 2 ) );
+ }
+
+ public void enableParameters()
+ {
+ this.amplitude.enable();
+ this.otsu.enable();
+ }
+
+ public void disableSliders()
+ {
+ this.amplitude.disable();
+ this.otsu.disable();
+ }
+
+ public ParameterSliderInteger getAmplitude()
+ {
+ return amplitude;
+ }
+
+ public ParameterSliderInteger getIsland()
+ {
+ return island;
+ }
+
+ public ParameterSliderInteger getOtsu()
+ {
+ return otsu;
+ }
+
+ public ParameterSliderInteger getXyBlur()
+ {
+ return xyBlur;
+ }
+
+ public ParameterSliderInteger getzBlur()
+ {
+ return zBlur;
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/StepPanel.java b/src/main/java/fr/pasteur/ida/zellige/gui/StepPanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9d8c8387924085f314994d7ef375ae11b37a225
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/StepPanel.java
@@ -0,0 +1,42 @@
+package fr.pasteur.ida.zellige.gui;
+
+import javafx.beans.NamedArg;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.control.Label;
+import javafx.scene.layout.VBox;
+
+import java.io.IOException;
+
+public class StepPanel extends VBox
+{
+
+ private final String name;
+ @FXML
+ Label Label2;
+
+
+ public StepPanel( @NamedArg( "name" ) String name )
+ {
+ this.name = name;
+ FXMLLoader fxmlLoader = new FXMLLoader( StepPanel.class.getClassLoader().getResource(
+ "fr.pasteur.ida.zellige.gui.view/StepPanel.fxml" ) );
+ fxmlLoader.setRoot( this );
+ fxmlLoader.setController( this );
+ try
+ {
+ fxmlLoader.load();
+ }
+ catch ( IOException e )
+ {
+ e.printStackTrace();
+ }
+ }
+
+
+ @FXML
+ public void initialize()
+ {
+ this.Label2.setText( name );
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/ZSlicesSlider.java b/src/main/java/fr/pasteur/ida/zellige/gui/ZSlicesSlider.java
new file mode 100644
index 0000000000000000000000000000000000000000..f2b5beb860c71039ab9f9e74407bacc4bad39725
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/ZSlicesSlider.java
@@ -0,0 +1,72 @@
+package fr.pasteur.ida.zellige.gui;
+
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.control.Slider;
+import javafx.scene.layout.FlowPane;
+
+import java.io.IOException;
+
+public class ZSlicesSlider extends FlowPane
+{
+
+ @FXML
+ Slider slider;
+
+ int userValue;
+
+ public ZSlicesSlider()
+ {
+ FXMLLoader fxmlLoader = new FXMLLoader( ParameterSlider.class.getClassLoader().getResource(
+ "fr.pasteur.ida.zellige.gui.view/ZSlicesSlider.fxml" ) );
+ fxmlLoader.setRoot( this );
+ fxmlLoader.setController( this );
+ try
+ {
+ fxmlLoader.load();
+ }
+ catch ( IOException e )
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @FXML
+ public void initialize()
+ {
+ slider.setMin( 0 );
+ slider.setMax( 30 );
+ slider.setBlockIncrement( 1 );
+ slider.setValue( 0 );
+ slider.setShowTickMarks( true );
+ slider.setShowTickLabels( true );
+ slider.setMajorTickUnit( 5 );
+ slider.setMinorTickCount( 4 );
+ slider.setSnapToTicks( true );
+ }
+
+ public Slider getSlider()
+ {
+ return slider;
+ }
+
+ public boolean hasChanged( int newValue )
+ {
+ if ( userValue != newValue )
+ {
+ userValue = newValue;
+ return true;
+ }
+ return false;
+ }
+
+ public int getUserValue()
+ {
+ return userValue;
+ }
+
+ public void setWidth( int length )
+ {
+ slider.setMax( length );
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/exception/NoA3DStackException.java b/src/main/java/fr/pasteur/ida/zellige/gui/exception/NoA3DStackException.java
new file mode 100644
index 0000000000000000000000000000000000000000..20711ebd3c8b09e6d6554c04c852ae9ff0159ecc
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/exception/NoA3DStackException.java
@@ -0,0 +1,13 @@
+package fr.pasteur.ida.zellige.gui.exception;
+
+public class NoA3DStackException extends Exception
+{
+
+ final String message = "The input image has to be 3D stack ! ";
+
+ @Override
+ public String getMessage()
+ {
+ return message;
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/exception/NoInputException.java b/src/main/java/fr/pasteur/ida/zellige/gui/exception/NoInputException.java
new file mode 100644
index 0000000000000000000000000000000000000000..e491f0135d6df7c99bedfaef759467ebd3bfa5a4
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/exception/NoInputException.java
@@ -0,0 +1,13 @@
+package fr.pasteur.ida.zellige.gui.exception;
+
+public class NoInputException extends Exception
+{
+
+ final String message = "Please load a 3D stack before running Zellige";
+
+ @Override
+ public String getMessage()
+ {
+ return message;
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/exception/NotANumberException.java b/src/main/java/fr/pasteur/ida/zellige/gui/exception/NotANumberException.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e871564c10bc3f1dff0b3f620d1662959ef4564
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/exception/NotANumberException.java
@@ -0,0 +1,14 @@
+package fr.pasteur.ida.zellige.gui.exception;
+
+public class NotANumberException extends Exception
+{
+
+ private final String message = "Please enter a number !";
+
+
+ @Override
+ public String getMessage()
+ {
+ return message;
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/selection/Container.java b/src/main/java/fr/pasteur/ida/zellige/gui/selection/Container.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc5e4970766af30d55d96181cabb76c262ec49e0
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/selection/Container.java
@@ -0,0 +1,17 @@
+package fr.pasteur.ida.zellige.gui.selection;
+
+import javafx.fxml.Initializable;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+public class Container implements Initializable
+{
+
+
+ @Override
+ public void initialize( URL url, ResourceBundle resourceBundle )
+ {
+
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/selection/IslandSearch.fxml b/src/main/java/fr/pasteur/ida/zellige/gui/selection/IslandSearch.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..d39077c4cc052bcd9f6cb205fbebd32c2ca87f49
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/selection/IslandSearch.fxml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+<?import javafx.scene.control.CheckBox?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.control.RadioButton?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.Pane?>
+<AnchorPane xmlns:fx="http://javafx.com/fxml/1" prefHeight="100.0" prefWidth="291.0" xmlns="http://javafx.com/javafx/17"
+ fx:controller="IslandSearchP">
+ <children>
+ <Pane prefHeight="50.0" prefWidth="291.0">
+ <children>
+ <Label layoutX="111.0" layoutY="14.0" text="Island Search"/>
+ </children>
+ </Pane>
+ <HBox alignment="TOP_CENTER" layoutY="56.0" prefHeight="50.0" prefWidth="291.0">
+ <children>
+ <CheckBox mnemonicParsing="false" text="Enable"/>
+ <RadioButton mnemonicParsing="false" text="4-connectivity"/>
+ <RadioButton mnemonicParsing="false" text="8-connectivity"/>
+ </children>
+ </HBox>
+ </children>
+</AnchorPane>
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/selection/IslandSearchP.java b/src/main/java/fr/pasteur/ida/zellige/gui/selection/IslandSearchP.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe2aa273869a9f6fe7dc0642c18040138870eb76
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/selection/IslandSearchP.java
@@ -0,0 +1,18 @@
+package fr.pasteur.ida.zellige.gui.selection;
+
+import javafx.fxml.FXML;
+import javafx.scene.control.CheckBox;
+
+public class IslandSearchP
+{
+ @FXML
+ private CheckBox enableISCheckbox;
+
+
+ private void doSomething()
+ {
+
+ }
+
+
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/AbstractTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/AbstractTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..74b0ee9ee1960d56ad0065bb76a6102b74e9477b
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/AbstractTask.java
@@ -0,0 +1,17 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import javafx.concurrent.Task;
+
+public class AbstractTask< T > extends Task< T >
+{
+ @Override
+ protected T call() throws Exception
+ {
+ return null;
+ }
+
+ public void start()
+ {
+ new Thread( this ).start();
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/CheckParameterValueTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/CheckParameterValueTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c5364f65c98827bc52a667cf7533543e3fb9879
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/CheckParameterValueTask.java
@@ -0,0 +1,62 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import fr.pasteur.ida.zellige.gui.exception.NotANumberException;
+import fr.pasteur.ida.zellige.steps.selection.exception.DataValidationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CheckParameterValueTask extends AbstractTask< Void >
+{
+
+ private final static Logger LOGGER = LoggerFactory.getLogger( CheckParameterValueTask.class );
+ private final String value;
+ private final String parameter;
+
+ public CheckParameterValueTask( String value, String parameter )
+ {
+ this.value = value;
+ this.parameter = parameter;
+ }
+
+ @Override
+ protected Void call() throws Exception
+ {
+
+ try
+ {
+ double v = Double.parseDouble( value );
+ if ( v < 0 )
+ {
+ LOGGER.debug( "The parameter {} is INVALID.", parameter );
+ throw new DataValidationException( "This parameter value has to be superior to zero !" );
+ }
+
+ if ( ( parameter.equals( "Amplitude" ) || parameter.equals( "Otsu" ) ||
+ parameter.equals( "Stating threshold" ) || parameter.equals( "Connexity" ) ) && v > 1 )
+ {
+ LOGGER.debug( "The parameter {} is INVALID.", parameter );
+ throw new DataValidationException( "This parameter value has to be inferior or equals to 1!" );
+ }
+ else if ( parameter.equals( "xy Blur" ) || parameter.equals( "z Blur" ) && v > 10 )
+ {
+ LOGGER.debug( "The parameter {} is INVALID.", parameter );
+ throw new DataValidationException( "This parameter value has to be inferior or equals to 10!" );
+ }
+ else
+ {
+ if ( v > 50 )
+ {
+ LOGGER.debug( "The parameter {} is INVALID.", parameter );
+ throw new DataValidationException( "This parameter value has to be inferior or equals to 50!" );
+ }
+ }
+ }
+ catch ( NumberFormatException e )
+ {
+ LOGGER.debug( "The parameter {} is INVALID.", parameter );
+ throw new NotANumberException();
+ }
+ LOGGER.debug( "The parameter {} is VALID", parameter );
+ return null;
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/ComputeWithNewAmplitudeValueTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/ComputeWithNewAmplitudeValueTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a1596e71310d424edcbf4c5edd98f29ad8dd6a7
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/ComputeWithNewAmplitudeValueTask.java
@@ -0,0 +1,37 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import fr.pasteur.ida.zellige.ReferenceSurfaceExtraction;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ComputeWithNewAmplitudeValueTask< T extends RealType< T > & NativeType< T > > extends AbstractTask< Void >
+{
+
+ private final static Logger LOGGER = LoggerFactory.getLogger( ComputeWithNewAmplitudeValueTask.class );
+ private final ReferenceSurfaceExtraction< T > extraction;
+ private final int newAmplitudeThresholdValue;
+
+ public ComputeWithNewAmplitudeValueTask( ReferenceSurfaceExtraction< T > extraction, int newAmplitudeThresholdValue )
+ {
+ this.extraction = extraction;
+ this.newAmplitudeThresholdValue = newAmplitudeThresholdValue;
+ }
+
+ @Override
+ protected Void call() throws Exception
+ {
+ if ( extraction.getSelectionOutput() == null )
+ {
+ updateMessage( "NoClassificationException" );
+ LOGGER.debug( "No Amplitude classification performed." );
+ this.cancelled();
+
+ }
+ extraction.runAmplitudeClassification( newAmplitudeThresholdValue );
+ extraction.runInterClassification();
+ LOGGER.debug( "Amplitude classification completed." );
+ return null;
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/ComputeWithNewOtsuValueTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/ComputeWithNewOtsuValueTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6f9ed1a13f72183d099316705ad03040a703a85
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/ComputeWithNewOtsuValueTask.java
@@ -0,0 +1,37 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import fr.pasteur.ida.zellige.ReferenceSurfaceExtraction;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ComputeWithNewOtsuValueTask< T extends RealType< T > & NativeType< T > > extends AbstractTask< Void >
+{
+ private final static Logger LOGGER = LoggerFactory.getLogger( ComputeWithNewOtsuValueTask.class );
+
+ private final ReferenceSurfaceExtraction< T > extraction;
+ private final int newAmplitudeThresholdValue;
+
+ public ComputeWithNewOtsuValueTask( ReferenceSurfaceExtraction< T > extraction, int newOtsuThresholdValue )
+ {
+ this.extraction = extraction;
+ this.newAmplitudeThresholdValue = newOtsuThresholdValue;
+ }
+
+ @Override
+ protected Void call() throws Exception
+ {
+ if ( extraction.getSelectionOutput() == null )
+ {
+ updateMessage( "NoClassificationException" );
+ LOGGER.debug( "No Otsu classification performed." );
+ this.cancelled();
+
+ }
+ extraction.runOtsuClassification( newAmplitudeThresholdValue );
+ extraction.runInterClassification();
+ LOGGER.debug( "Otsu classification completed." );
+ return null;
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/ConstructionCompletionTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/ConstructionCompletionTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..ceb55dea8245fb2703d1d5a79637bb15a57a1406
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/ConstructionCompletionTask.java
@@ -0,0 +1,37 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import fr.pasteur.ida.zellige.element.ReferenceSurface;
+import fr.pasteur.ida.zellige.element.Surface;
+import fr.pasteur.ida.zellige.steps.construction.ConstructionCompletion;
+import net.imglib2.RandomAccessibleInterval;
+import net.imglib2.img.ImgFactory;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+
+public class ConstructionCompletionTask< T extends RealType< T > & NativeType< T > > extends AbstractTask< ArrayList< ReferenceSurface< T > > >
+{
+ private final static Logger LOGGER = LoggerFactory.getLogger( ConstructionCompletion.class );
+ private final RandomAccessibleInterval< T > input;
+ private final ImgFactory< T > factory;
+ private final ArrayList< Surface > finalSurfaces;
+
+
+ public ConstructionCompletionTask( RandomAccessibleInterval< T > input, ImgFactory< T > factory, ArrayList< Surface > finalSurfaces )
+ {
+ this.input = input;
+ this.factory = factory;
+ this.finalSurfaces = finalSurfaces;
+ }
+
+ @Override
+ protected ArrayList< ReferenceSurface< T > > call() throws Exception
+ {
+ LOGGER.debug( "Construction completion completed." );
+ return ConstructionCompletion.run( input, factory, finalSurfaces );
+
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/CreateExtractionTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/CreateExtractionTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..7af123d760e9c90af617e9d97774deb50c202755
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/CreateExtractionTask.java
@@ -0,0 +1,47 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import fr.pasteur.ida.zellige.ReferenceSurfaceExtraction;
+import net.imagej.Dataset;
+import net.imagej.ImgPlus;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * This task is performed each time a new input image is selected in the file combobox.
+ *
+ * @param <T> the input image type
+ */
+public class CreateExtractionTask< T extends RealType< T > & NativeType< T > > extends AbstractTask< ReferenceSurfaceExtraction< T > >
+{
+ private final static Logger LOGGER = LoggerFactory.getLogger( CreateExtractionTask.class );
+ private final Dataset dataset;
+ private final int amplitudeThresholdValue;
+ private final int otsuThresholdValue;
+
+ public CreateExtractionTask( Dataset dataset, int amplitudeThresholdValue, int otsuThresholdValue )
+ {
+ this.dataset = dataset;
+
+ this.amplitudeThresholdValue = amplitudeThresholdValue;
+ this.otsuThresholdValue = otsuThresholdValue;
+ }
+
+ @Override
+ protected ReferenceSurfaceExtraction< T > call() throws Exception
+ {
+ ImgPlus< T > input = ( ImgPlus< T > ) dataset.getImgPlus();
+ ReferenceSurfaceExtraction< T > extraction = new ReferenceSurfaceExtraction<>( input, input.factory() );
+ extraction.computeClassificationImages();
+ LOGGER.debug( "Classification images computed" );
+ extraction.runAmplitudeClassification( amplitudeThresholdValue );
+ LOGGER.debug( "Otsu classification completed" );
+ extraction.runOtsuClassification( otsuThresholdValue );
+ LOGGER.debug( "Amplitude classification completed" );
+ extraction.runInterClassification();
+ LOGGER.debug( "Inter classification completed" );
+ return extraction;
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/DisplayDatasetChoicesTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/DisplayDatasetChoicesTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..1993dbcbf33918c79d8b171bf5af894420f9a327
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/DisplayDatasetChoicesTask.java
@@ -0,0 +1,33 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import net.imagej.Dataset;
+import net.imagej.display.ImageDisplay;
+import net.imagej.display.ImageDisplayService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+
+public class DisplayDatasetChoicesTask extends AbstractTask< ArrayList< Dataset > >
+{
+ private final static Logger LOGGER = LoggerFactory.getLogger( DisplayDatasetChoicesTask.class );
+ private final ImageDisplayService imageDisplayService;
+
+ public DisplayDatasetChoicesTask( ImageDisplayService imageDisplayService )
+ {
+ this.imageDisplayService = imageDisplayService;
+ }
+
+ @Override
+ protected ArrayList< Dataset > call() throws Exception
+ {
+ ArrayList< ImageDisplay > imageDisplays = ( ArrayList< ImageDisplay > ) imageDisplayService.getImageDisplays();
+ ArrayList< Dataset > tempDatasets = new ArrayList<>( imageDisplays.size() );
+ for ( ImageDisplay imageDisplay : imageDisplays )
+ {
+ tempDatasets.add( imageDisplayService.getActiveDataset( imageDisplay ) );
+ }
+ LOGGER.debug( "Available datasets updated." );
+ return tempDatasets;
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/ImageFXDisplayTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/ImageFXDisplayTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..a3fc2e9d39248763df8418e5c9fd35fbda744c11
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/ImageFXDisplayTask.java
@@ -0,0 +1,29 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import fr.pasteur.ida.zellige.gui.ImageFXDisplay;
+import javafx.scene.image.ImageView;
+import net.imglib2.IterableInterval;
+import net.imglib2.type.logic.BitType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ImageFXDisplayTask extends AbstractTask< ImageView[] >
+{
+ private final static Logger LOGGER = LoggerFactory.getLogger( ImageFXDisplayTask.class );
+ private final IterableInterval< BitType > input;
+
+ public ImageFXDisplayTask( IterableInterval< BitType > input )
+ {
+ this.input = input;
+ }
+
+
+ @Override
+ protected ImageView[] call() throws Exception
+ {
+ ImageFXDisplay display = new ImageFXDisplay( input );
+ display.set();
+ LOGGER.debug( "Classified image updated." );
+ return display.getImageViews();
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/NewClassificationTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/NewClassificationTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..0fcf8f8b306e41a0a3ef2c0bfa6f4fe6c0696d53
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/NewClassificationTask.java
@@ -0,0 +1,48 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import fr.pasteur.ida.zellige.ReferenceSurfaceExtraction;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NewClassificationTask< T extends RealType< T > & NativeType< T > > extends AbstractTask< Void >
+{
+ private final Logger LOGGER = LoggerFactory.getLogger( NewClassificationTask.class );
+ private final ReferenceSurfaceExtraction< T > extraction;
+
+ private final int amplitude;
+ private final int otsu;
+
+ public NewClassificationTask( ReferenceSurfaceExtraction< T > extraction, int amplitude, int otsu )
+ {
+ this.extraction = extraction;
+ this.amplitude = amplitude;
+ this.otsu = otsu;
+ }
+
+ @Override
+ protected Void call() throws Exception
+ {
+ extraction.computeClassificationImages();
+ LOGGER.debug( "Images computed." );
+ extraction.runAmplitudeClassification( amplitude );
+ LOGGER.debug( "Amplitude classification done." );
+ extraction.runOtsuClassification( otsu );
+ LOGGER.debug( "Otsu classification done." );
+ extraction.runInterClassification();
+ LOGGER.debug( "InterClassification done." );
+ return null;
+ }
+
+
+//
+ @Override
+ protected void succeeded()
+ {
+ super.succeeded();
+ LOGGER.debug( "Task successful." );
+ }
+
+
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/ProjectionTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/ProjectionTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d72d43ab73657a66b204c32f76ecd855b0bd882
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/ProjectionTask.java
@@ -0,0 +1,65 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import fr.pasteur.ida.zellige.element.ReferenceSurface;
+import fr.pasteur.ida.zellige.steps.projection.ReferenceSurfaceProjection;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+
+public class ProjectionTask< T extends RealType< T > & NativeType< T > > extends AbstractTask< Void >
+{
+
+ private final static Logger LOGGER = LoggerFactory.getLogger( ProjectionTask.class );
+ private final ArrayList< ReferenceSurface< T > > referenceSurfaces;
+ private final int delta;
+ private final String projectionType;
+ private final boolean projectionDisplay;// the projection
+ private final boolean rawHeightMapDisplay;// the raw height map extracted by Zellige before projection
+ private final boolean extractedHeightMapDisplay;// the height map after projection
+ private final boolean reduced3DSpaceDisplay; // the volume of surface +- delta
+ private final boolean segmentedSurfaceDisplay; // the surface segmented in the 3D original volume
+ private final boolean segmentedSurfaceMaskDisplay; // the mask of the segmented surface +- delta
+ private final int delta2;
+
+ public ProjectionTask( ArrayList< ReferenceSurface< T > > referenceSurfaces, int delta, String projectionType,
+ boolean projectionDisplay,
+ boolean rawHeightMapDisplay,
+ boolean extractedHeightMapDisplay,
+ boolean reduced3DSpaceDisplay,
+ boolean segmentedSurfaceDisplay,
+ boolean segmentedSurfaceMaskDisplay, int delta2 )
+ {
+ this.referenceSurfaces = referenceSurfaces;
+ this.delta = delta;
+ this.projectionType = projectionType;
+ this.projectionDisplay = projectionDisplay;
+ this.rawHeightMapDisplay = rawHeightMapDisplay;
+ this.extractedHeightMapDisplay = extractedHeightMapDisplay;
+ this.reduced3DSpaceDisplay = reduced3DSpaceDisplay;
+ this.segmentedSurfaceDisplay = segmentedSurfaceDisplay;
+ this.segmentedSurfaceMaskDisplay = segmentedSurfaceMaskDisplay;
+ this.delta2 = delta2;
+ }
+
+
+ @Override
+ protected Void call() throws Exception
+ {
+ for ( ReferenceSurface< T > referenceSurface : referenceSurfaces )
+ {
+ referenceSurface.init();
+ ReferenceSurfaceProjection.run( referenceSurface, delta, projectionType,
+ projectionDisplay,
+ rawHeightMapDisplay,
+ extractedHeightMapDisplay,
+ reduced3DSpaceDisplay,
+ segmentedSurfaceDisplay,
+ segmentedSurfaceMaskDisplay, delta2 );
+ }
+ LOGGER.debug( "Projection completed." );
+ return null;
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/RunFirstConstructionTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/RunFirstConstructionTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..dcbc9023f4657b6022b35c2d6485ad046fe52038
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/RunFirstConstructionTask.java
@@ -0,0 +1,40 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import fr.pasteur.ida.zellige.element.Pixels;
+import fr.pasteur.ida.zellige.element.Surface;
+import fr.pasteur.ida.zellige.steps.construction.rounds.FirstRoundConstruction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+
+public class RunFirstConstructionTask extends AbstractTask< ArrayList< Surface > >
+{
+ private final static Logger LOGGER = LoggerFactory.getLogger( RunFirstConstructionTask.class );
+ private final Pixels[][] selectedPixels;
+ private final double startingOsSize1;
+ private final int overlap1;
+ private final double connexityRate1;
+ private final double surfaceMinSizeFactor;
+
+ public RunFirstConstructionTask( Pixels[][] selectedPixels, double startingOsSize1, int overlap1, double connexityRate1, double surfaceMinSizeFactor )
+ {
+ this.selectedPixels = selectedPixels;
+ this.startingOsSize1 = startingOsSize1;
+ this.overlap1 = overlap1;
+ this.connexityRate1 = connexityRate1;
+ this.surfaceMinSizeFactor = surfaceMinSizeFactor;
+ }
+
+ @Override
+ protected ArrayList< Surface > call() throws Exception
+ {
+ FirstRoundConstruction step1 = new FirstRoundConstruction( selectedPixels, startingOsSize1, overlap1, connexityRate1, surfaceMinSizeFactor );
+ step1.process();
+ LOGGER.debug( "First round task completed." );
+ return step1.getSurfaces();
+
+ }
+
+
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/RunPostTreatmentTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/RunPostTreatmentTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..c36ab37a6e2c0cc3862b8a21b9fa70582db8f128
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/RunPostTreatmentTask.java
@@ -0,0 +1,37 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import fr.pasteur.ida.zellige.ReferenceSurfaceExtraction;
+import fr.pasteur.ida.zellige.element.Pixels;
+import fr.pasteur.ida.zellige.steps.selection.postTreatment.PostTreatment;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RunPostTreatmentTask< T extends RealType< T > & NativeType< T > > extends AbstractTask< Pixels[][] >
+
+{
+ private final static Logger LOGGER = LoggerFactory.getLogger( RunPostTreatmentTask.class );
+ private final ReferenceSurfaceExtraction< T > extraction;
+ private final double sigmaXY;
+ private final double sigmaZ;
+ private final int islandSize;
+ private final int connexity;
+
+ public RunPostTreatmentTask( ReferenceSurfaceExtraction< T > extraction, double sigmaXY, double sigmaZ, int islandSize, int connexity )
+ {
+ this.extraction = extraction;
+ this.sigmaXY = sigmaXY;
+ this.sigmaZ = sigmaZ;
+ this.islandSize = islandSize;
+
+ this.connexity = connexity;
+ }
+
+ @Override
+ protected Pixels[][] call() throws Exception
+ {
+ LOGGER.debug( "Task's start." );
+ return PostTreatment.run( extraction.getSelectionOutput(), sigmaXY, sigmaZ, islandSize, connexity );
+ }
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/RunSecondConstructionTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/RunSecondConstructionTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0062e0c839403304adb008f69794bca5990e389
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/RunSecondConstructionTask.java
@@ -0,0 +1,39 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+import fr.pasteur.ida.zellige.element.Surface;
+import fr.pasteur.ida.zellige.steps.construction.rounds.SecondRoundConstruction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+
+public class RunSecondConstructionTask extends AbstractTask< ArrayList< Surface > >
+{
+ private final static Logger LOGGER = LoggerFactory.getLogger( RunSecondConstructionTask.class );
+ private final ArrayList< Surface > tempSurfaces;
+
+ private final double startingOsSize2;
+ private final int overlap2;
+ private final double connexityRate2;
+ private final double surfaceMinSizeFactor;
+
+ public RunSecondConstructionTask( ArrayList< Surface > tempSurfaces, double startingOsSize2, int overlap2, double connexityRate2, double surfaceMinSizeFactor )
+ {
+ this.tempSurfaces = tempSurfaces;
+ this.startingOsSize2 = startingOsSize2;
+ this.overlap2 = overlap2;
+ this.connexityRate2 = connexityRate2;
+ this.surfaceMinSizeFactor = surfaceMinSizeFactor;
+ }
+
+ @Override
+ protected ArrayList< Surface > call() throws Exception
+ {
+ SecondRoundConstruction step1 = new SecondRoundConstruction( tempSurfaces, startingOsSize2, overlap2, connexityRate2, surfaceMinSizeFactor );
+ step1.process();
+ LOGGER.debug( "Second round task completed." );
+ return step1.getSurfaces();
+ }
+
+
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/gui/task/SetCurrentDatasetTask.java b/src/main/java/fr/pasteur/ida/zellige/gui/task/SetCurrentDatasetTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..1763e6fe3b1c399e75b1b719aab09dc9b2980e30
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/gui/task/SetCurrentDatasetTask.java
@@ -0,0 +1,43 @@
+package fr.pasteur.ida.zellige.gui.task;
+
+
+import net.imagej.Dataset;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SetCurrentDatasetTask extends AbstractTask< Dataset >
+
+{
+ private final Logger LOGGER = LoggerFactory.getLogger( SetCurrentDatasetTask.class );
+ private final Dataset dataset;
+
+
+ public SetCurrentDatasetTask( Dataset dataset )
+ {
+ this.dataset = dataset;
+ LOGGER.debug( " constructor" );
+ }
+
+ @Override
+ protected Dataset call() throws Exception
+ {
+ LOGGER.debug( "Task's start." );
+ if ( dataset.numDimensions() != 3 )
+ {
+ LOGGER.debug( "This input is not a z-stack" );
+ return null;
+ }
+ return dataset;
+ }
+
+
+ //
+ @Override
+ protected void succeeded()
+ {
+ super.succeeded();
+ LOGGER.debug( "Task successful" );
+ }
+
+
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/construction/ConstructionCompletion.java b/src/main/java/fr/pasteur/ida/zellige/steps/construction/ConstructionCompletion.java
index 259d5ea484444cf0ff6cb6c76bf0c29d23300779..d61951dba538debecdf8b1aaba2652415493c6ef 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/construction/ConstructionCompletion.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/construction/ConstructionCompletion.java
@@ -17,6 +17,7 @@ import net.imglib2.util.Util;
import java.util.ArrayList;
+
/**
* This class allows to get a height map from a {@link Surface} by averaging the Z values or discarding them if not possible (gteZmap())
* and by interpolating when possible if there is any missing internal values (processZMap()).
@@ -49,6 +50,7 @@ public class ConstructionCompletion< T extends RealType< T > & NativeType< T > >
for ( Surface surface : finalSurfaces )
{
Img< UnsignedShortType > processedZMap = processedZMap( surface );
+
ReferenceSurface< T > referenceSurface = new ReferenceSurface<>( input, factory, processedZMap, index++ );
referenceSurfaces.add( referenceSurface );
}
@@ -81,6 +83,7 @@ public class ConstructionCompletion< T extends RealType< T > & NativeType< T > >
int z = averageIntZ( pixel );
if ( z != - 1 )
{
+ System.out.println( "only two : " + pixel );
randomAccess.setPosition( i, 1 );
randomAccess.get().set( new UnsignedShortType( z + 1 ) );
}
@@ -92,6 +95,13 @@ public class ConstructionCompletion< T extends RealType< T > & NativeType< T > >
randomAccess.get().set( new UnsignedShortType( z + 1 ) );
}
}
+ else
+ {
+ if ( pixel != null )
+ {
+ System.out.println( "more than two : " + pixel );
+ }
+ }
}
}
}
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/construction/Interpolation.java b/src/main/java/fr/pasteur/ida/zellige/steps/construction/Interpolation.java
index b19ba0c5ce18c75f2668c61128ecde7c07ad065f..3faa344b41ab080e69dd1162c7e4ae0dccc3b4f5 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/construction/Interpolation.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/construction/Interpolation.java
@@ -20,7 +20,6 @@ public class Interpolation
public static Img< UnsignedShortType > run( RandomAccessibleInterval< UnsignedShortType > input )
{
InterpolationOperator operator = new InterpolationOperator( input );
-// ImageJFunctions.show( operator.getOutput() );
return operator.getOutput();
}
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/ConstructionRound.java b/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/ConstructionRound.java
index 8c0131923f5edda6bd527535d77288aee1a32d82..452cdb03e93595020080075b2db2608136924d36 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/ConstructionRound.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/ConstructionRound.java
@@ -36,6 +36,19 @@ public abstract class ConstructionRound
this.surfaceMinSizeFactor = constructionParameters.getSurfaceMinSizeFactor();
}
+ protected ConstructionRound( final double startingSizeThreshold,
+ final int overlap,
+ final double connexityRate,
+ final double surfaceMinSizeFactor )
+ {
+ this.startingSizeThreshold = startingSizeThreshold;
+ this.overlap = overlap;
+ this.connexityRate = connexityRate;
+ this.surfaces = new ArrayList<>();
+ this.surfaceMinSizeFactor = surfaceMinSizeFactor;
+ }
+
+
void finalizeSurface( ArrayList< Surface > surfaces ) throws NoSurfaceFoundException
{
goodSurfacesCount = surfaces.size();
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/FirstRoundConstruction.java b/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/FirstRoundConstruction.java
index caea159bf08b70f919cf8ba1a9f72c485ccc65bd..832b87f4c55fd90209b907c9b12b8764de52a927 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/FirstRoundConstruction.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/FirstRoundConstruction.java
@@ -19,6 +19,15 @@ public class FirstRoundConstruction extends ConstructionRound
this.maximums = maximums;
}
+ public FirstRoundConstruction( Pixels[][] maximums, final double startingSizeThreshold,
+ final int overlap,
+ final double connexityRate,
+ final double surfaceMinSizeFactor )
+ {
+ super( startingSizeThreshold, overlap, connexityRate, surfaceMinSizeFactor );
+ this.maximums = maximums;
+ }
+
public void process() throws NoSurfaceFoundException
{
LOGGER.debug( "Processing..." );
@@ -26,7 +35,7 @@ public class FirstRoundConstruction extends ConstructionRound
long startOseConstructionTime = System.currentTimeMillis();
OSEListArray oseLists = constructOSE( maximums );
long stopOseConstructionTime = System.currentTimeMillis();
- this.setOSConstructionProcessingTime( stopOseConstructionTime - startOseConstructionTime );
+ this.setOSConstructionProcessingTime( stopOseConstructionTime - startOseConstructionTime );
/* Construction of surfaces*/
LOGGER.info( "Starting surface construction..." );
int lineLength = maximums[ 0 ].length;
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/SecondRoundConstruction.java b/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/SecondRoundConstruction.java
index a70e11ff9fd67fdfcef47133e73ff302a347464b..688f2e50f69e8c57e806bd2de6966150a49779ef 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/SecondRoundConstruction.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/construction/rounds/SecondRoundConstruction.java
@@ -22,6 +22,15 @@ public class SecondRoundConstruction extends ConstructionRound
this.tempSurfaces = tempSurfaces;
}
+ public SecondRoundConstruction( final ArrayList< Surface > tempSurfaces, final double startingSizeThreshold,
+ final int overlap,
+ final double connexityRate,
+ final double surfaceMinSizeFactor )
+ {
+ super( startingSizeThreshold, overlap, connexityRate, surfaceMinSizeFactor );
+ this.tempSurfaces = tempSurfaces;
+ }
+
// public static ArrayList< Surface > run( ArrayList< Surface > tempSurfaces, ConstructionParameters constructionParameters ) throws NoSurfaceFoundException
// {
// SecondStepConstruction round = new SecondStepConstruction( tempSurfaces, constructionParameters );
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/projection/DisplayParameters.java b/src/main/java/fr/pasteur/ida/zellige/steps/projection/DisplayParameters.java
index 2b1664e15d6060add1b2a2c3978e9181af444d2a..1134e1356037bf2ea6a101dfc7913392cf542958 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/projection/DisplayParameters.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/projection/DisplayParameters.java
@@ -5,19 +5,21 @@ public class DisplayParameters
private final boolean zMapDisplay;
private final boolean projectionDisplay;
private final boolean projectionHeightMapDisplay;
- private final boolean heightMapSubVolumeMaskDisplay;
+ private final boolean surfaceSubVolumeDisplay;
private final boolean extractedHeightMapSubStackDisplay;
+ private final boolean heightMapSubVolumeMask;
public DisplayParameters( boolean zMapDisplay, boolean extractedHeightMapSubStackDisplay, boolean projectionHeightMapDisplay,
- boolean projectionDisplay, boolean heightMapSubVolumeMaskDisplay )
+ boolean projectionDisplay, boolean surfaceSubVolumeDisplay, boolean heightMapSubVolumeMask )
{
this.zMapDisplay = zMapDisplay;
this.extractedHeightMapSubStackDisplay = extractedHeightMapSubStackDisplay;
this.projectionHeightMapDisplay = projectionHeightMapDisplay;
this.projectionDisplay = projectionDisplay;
- this.heightMapSubVolumeMaskDisplay = heightMapSubVolumeMaskDisplay;
+ this.surfaceSubVolumeDisplay = surfaceSubVolumeDisplay;
+ this.heightMapSubVolumeMask = heightMapSubVolumeMask;
}
public boolean iszMapDisplay()
@@ -40,8 +42,13 @@ public class DisplayParameters
return projectionDisplay;
}
- public boolean isHeightMapSubVolumeMaskDisplay()
+ public boolean isSurfaceSubVolumeDisplay()
{
- return heightMapSubVolumeMaskDisplay;
+ return surfaceSubVolumeDisplay;
+ }
+
+ public boolean isHeightMapSubVolumeMask()
+ {
+ return heightMapSubVolumeMask;
}
}
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/projection/ReferenceSurfaceProjection.java b/src/main/java/fr/pasteur/ida/zellige/steps/projection/ReferenceSurfaceProjection.java
index f8ce6b0dc4412c9662ca2264b642a7a6368898dc..5e5693f37a6555e6f7e3e8401d3aaec5d44eed87 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/projection/ReferenceSurfaceProjection.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/projection/ReferenceSurfaceProjection.java
@@ -1,7 +1,8 @@
package fr.pasteur.ida.zellige.steps.projection;
import fr.pasteur.ida.zellige.element.ReferenceSurface;
-import fr.pasteur.ida.zellige.steps.Utils;
+import net.imglib2.Cursor;
+import net.imglib2.IterableInterval;
import net.imglib2.RandomAccess;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.img.Img;
@@ -9,11 +10,14 @@ import net.imglib2.img.ImgFactory;
import net.imglib2.img.array.ArrayImgFactory;
import net.imglib2.img.display.imagej.ImageJFunctions;
import net.imglib2.type.NativeType;
+import net.imglib2.type.logic.BitType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.numeric.integer.UnsignedShortType;
import java.util.Arrays;
+import static fr.pasteur.ida.zellige.steps.Utils.setPosition;
+
/**
* @author ctrebeau
* Methods to extract the reference surface from a stack with the height map obtained with the program.
@@ -35,6 +39,48 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
referenceSurfaceProjection.display( referenceSurface, projectionParameters, displayParameters );
}
+// public static < T extends RealType< T > & NativeType< T > > void run( ReferenceSurface< T > referenceSurface,
+// int delta, String projectionType,
+// boolean projectionDisplay,
+// boolean rawHeightMapDisplay,
+// boolean extractedHeightMapDisplay,
+// boolean reduced3DSpaceDisplay,
+// boolean segmentedSurfaceDisplay,
+// boolean segmentedSurfaceMaskDisplay ) throws NoPossibleDisplayException
+// {
+// ReferenceSurfaceProjection< T > referenceSurfaceProjection = new ReferenceSurfaceProjection<>();
+// referenceSurfaceProjection.set( referenceSurface, delta, projectionType );
+// referenceSurfaceProjection.display( referenceSurface, delta, projectionType,
+// projectionDisplay,
+// rawHeightMapDisplay,
+// extractedHeightMapDisplay,
+// reduced3DSpaceDisplay,
+// segmentedSurfaceDisplay,
+// segmentedSurfaceMaskDisplay );
+// }
+
+ public static < T extends RealType< T > & NativeType< T > > void run( ReferenceSurface< T > referenceSurface,
+ int delta, String projectionType,
+ boolean projectionDisplay,
+ boolean rawHeightMapDisplay,
+ boolean extractedHeightMapDisplay,
+ boolean reduced3DSpaceDisplay,
+ boolean segmentedSurfaceDisplay,
+ boolean segmentedSurfaceMaskDisplay,
+ int delta2 ) throws NoPossibleDisplayException
+ {
+ ReferenceSurfaceProjection< T > referenceSurfaceProjection = new ReferenceSurfaceProjection<>();
+ referenceSurfaceProjection.set( referenceSurface, delta, projectionType, delta2 );
+ referenceSurfaceProjection.display( referenceSurface, delta, projectionType,
+ projectionDisplay,
+ rawHeightMapDisplay,
+ extractedHeightMapDisplay,
+ reduced3DSpaceDisplay,
+ segmentedSurfaceDisplay,
+ segmentedSurfaceMaskDisplay, delta2 );
+ }
+
+
/**
* @param referenceSurface the considered referenceSurface
* @param method the desired user projection method
@@ -61,13 +107,13 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
for ( int y = 0; y <= input.dimension( 1 ) - 1; y++ )
{
- Utils.setPosition( zMapAccess, x, y );
+ setPosition( zMapAccess, x, y );
int z = zMapAccess.get().getInteger() - 1;
if ( z != - 1 )
{
- Utils.setPosition( stackAccess, x, y, z );
+ setPosition( stackAccess, x, y, z );
int finalZ = findZ( stackAccess, ( int ) input.dimension( 2 ) - 1, delta );
- Utils.setPosition( heightmapAccess, x, y );
+ setPosition( heightmapAccess, x, y );
heightmapAccess.get().set( finalZ + 1 );
}
}
@@ -91,7 +137,7 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
RandomAccessibleInterval< T > input = referenceSurface.getInput();
ImgFactory< T > factory = referenceSurface.getFactory();
RandomAccessibleInterval< UnsignedShortType > zMap = referenceSurface.getzMap();
- //the stack slice number depends of the user "delta" parameter.
+ //the stack slice number depends on the user "delta" parameter.
Img< T > heightMapStack = factory.create( input.dimension( 0 ), input.dimension( 1 ), ( delta * 2L ) + 1 );
RandomAccess< T > stackAccess = input.randomAccess();
RandomAccess< T > heightMapAccess = heightMapStack.randomAccess();
@@ -112,8 +158,8 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
int zHeight = delta;
for ( int z = zMapValue; z >= startIndex; z-- )
{
- Utils.setPosition( heightMapAccess, x, y, zHeight );
- Utils.setPosition( stackAccess, x, y, z );
+ setPosition( heightMapAccess, x, y, zHeight );
+ setPosition( stackAccess, x, y, z );
heightMapAccess.get().set( stackAccess.get() );
zHeight--;
}
@@ -121,8 +167,8 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
zHeight = delta + 1;
for ( int z = zMapValue + 1; z <= stopIndex; z++ )
{
- Utils.setPosition( heightMapAccess, x, y, zHeight );
- Utils.setPosition( stackAccess, x, y, z );
+ setPosition( heightMapAccess, x, y, zHeight );
+ setPosition( stackAccess, x, y, z );
heightMapAccess.get().set( stackAccess.get() );
zHeight++;
}
@@ -131,53 +177,102 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
{
for ( int z = 0; z <= heightMapStack.dimension( 2 ) - 1; z++ )
{
- Utils.setPosition( heightMapAccess, x, y, z );
+ setPosition( heightMapAccess, x, y, z );
heightMapAccess.get().setReal( 0 );
}
}
}
}
-// Utils.saveImage( heightMapStack, "surface n°" + surfaceNumber, "C:\\Users\\Barbier-Trebeau\\Desktop\\ ");
return heightMapStack;
}
- public static < T extends RealType< T > & NativeType< T > > Img< T > getHeightMapSubVolumeStack
- ( ReferenceSurface< T > referenceSurface, int delta )
- {
- RandomAccessibleInterval< T > input = referenceSurface.getInput();
- ImgFactory< T > factory = referenceSurface.getFactory();
- RandomAccessibleInterval< UnsignedShortType > zMap = referenceSurface.getzMap();
- Img< T > heightMapStack = factory.create( input.dimension( 0 ), input.dimension( 1 ), input.dimension( 2 ) );
- RandomAccess< T > stackAccess = input.randomAccess();
- RandomAccess< T > heightmapAccess = heightMapStack.randomAccess();
- RandomAccess< UnsignedShortType > zMapAccess = zMap.randomAccess();
- for ( int x = 0; x <= input.dimension( 0 ) - 1; x++ )
+ public static < T extends RealType< T > & NativeType< T > > Img< BitType > getSegmentedSurfaceMask
+ ( IterableInterval< T > segmentedSurface, int delta )
+ {
+ Img< BitType > segmentedSurfaceMask = new ArrayImgFactory<>( new BitType() ).create( segmentedSurface );
+ Cursor< T > surfaceAccess = segmentedSurface.cursor();
+ RandomAccess< BitType > mapAccess = segmentedSurfaceMask.randomAccess();
+ while ( surfaceAccess.hasNext() )
{
- for ( int y = 0; y <= input.dimension( 1 ) - 1; y++ )
+ surfaceAccess.fwd();
+ if ( surfaceAccess.get().getRealFloat() > 0 )// there is a surface pixel
{
- Utils.setPosition( zMapAccess, x, y );
- int Z = zMapAccess.get().getInteger();
- if ( Z > 0 )
+ int x = surfaceAccess.getIntPosition( 0 );
+ int y = surfaceAccess.getIntPosition( 1 );
+ int z = surfaceAccess.getIntPosition( 2 );
+ int startIndex = Math.max( z - delta, 0 );
+ int stopIndex = Math.min( ( int ) segmentedSurface.dimension( 2 ) - 1, ( z + delta ) );
+ for ( int Z = startIndex; Z <= stopIndex; Z++ )
{
-// Utils.setPosition( stackAccess, x, y, Z - 1 );
- // " - 1" because by convention the z values start at 1, 0 is for unassigned values.
-// heightmapAccess.get().set( stackAccess.get() );
- int startIndex = Math.max( Z - delta, 0 );
- int stopIndex = Math.min( ( int ) input.dimension( 2 ) - 1, ( Z + delta ) );
+ mapAccess.setPosition( surfaceAccess );
+ setPosition( mapAccess, x, y, Z );
+ mapAccess.get().set( true );
+ }
+ }
+ }
+// ImageJFunctions.show( segmentedSurfaceMask, "Mask with " + delta );
+ return segmentedSurfaceMask;
+ }
- for ( int z = startIndex; z <= stopIndex; z++ )
- {
- Utils.setPosition( heightmapAccess, x, y, z );
- Utils.setPosition( stackAccess, x, y, z );
- heightmapAccess.get().set( stackAccess.get() );
- }
- }
+ // public static < T extends RealType< T > & NativeType< T > > Img< T > getSegmentedSurface
+// ( ReferenceSurface< T > referenceSurface, int delta )
+// {
+// RandomAccessibleInterval< T > input = referenceSurface.getInput();
+// ImgFactory< T > factory = referenceSurface.getFactory();
+// RandomAccessibleInterval< UnsignedShortType > zMap = referenceSurface.getzMap();
+// Img< T > heightMapStack = factory.create( input.dimension( 0 ), input.dimension( 1 ), input.dimension( 2 ) );
+// RandomAccess< T > stackAccess = input.randomAccess();
+// RandomAccess< T > heightmapAccess = heightMapStack.randomAccess();
+// RandomAccess< UnsignedShortType > zMapAccess = zMap.randomAccess();
+//
+// for ( int x = 0; x <= input.dimension( 0 ) - 1; x++ )
+// {
+// for ( int y = 0; y <= input.dimension( 1 ) - 1; y++ )
+// {
+// setPosition( zMapAccess, x, y );
+// int Z = zMapAccess.get().getInteger();
+// if ( Z > 0 )
+// {
+// // " - 1" because by convention the z values start at 1, 0 is for unassigned values.
+//// heightmapAccess.get().set( stackAccess.get() );
+// int startIndex = Math.max( Z - delta, 0 );
+// int stopIndex = Math.min( ( int ) input.dimension( 2 ) - 1, ( Z + delta ) );
+//
+//
+// for ( int z = startIndex; z <= stopIndex; z++ )
+// {
+// setPosition( heightmapAccess, x, y, z );
+// setPosition( stackAccess, x, y, z );
+// heightmapAccess.get().set( stackAccess.get() );
+// }
+// }
+// }
+// }
+// return heightMapStack;
+// }
+ public static < T extends RealType< T > & NativeType< T > > Img< T > getSegmentedSurface
+ ( Img< UnsignedShortType > extractedHeightMap, RandomAccessibleInterval< T > originalInput, ImgFactory< T > factory )
+ {
+ Img< T > segmentedSurface = factory.create( originalInput );
+ RandomAccess< T > surfaceAccess = segmentedSurface.randomAccess();
+ RandomAccess< T > inputAccess = originalInput.randomAccess();
+ Cursor< UnsignedShortType > heightMapCursor = extractedHeightMap.cursor();
+ while ( heightMapCursor.hasNext() )
+ {
+ heightMapCursor.fwd();
+ if ( heightMapCursor.get().getInteger() > 0 )
+ {
+ int x = heightMapCursor.getIntPosition( 0 );
+ int y = heightMapCursor.getIntPosition( 1 );
+ setPosition( surfaceAccess, x, y, heightMapCursor.get().getInteger() - 1 );
+ setPosition( inputAccess, x, y, heightMapCursor.get().getInteger() - 1 );
+ surfaceAccess.get().set( inputAccess.get() );
}
}
-// Utils.saveImage( heightMapStack, "surface n°" + surfaceNumber, "C:\\Users\\Barbier-Trebeau\\Desktop\\ ");
- return heightMapStack;
+
+ return segmentedSurface;
}
@@ -194,7 +289,7 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
{
RandomAccessibleInterval< T > input = referenceSurface.getInput();
ImgFactory< T > factory = referenceSurface.getFactory();
- RandomAccessibleInterval< UnsignedShortType > projectionHeightMap = referenceSurface.getProjection().getProjectionHeightMap();
+ RandomAccessibleInterval< UnsignedShortType > projectionHeightMap = referenceSurface.getProjection().getExtractedHeightMap();
if ( projectionType.equals( "MIP" ) )
{
Img< T > projection = factory.create( input.dimension( 0 ), input.dimension( 1 ) );
@@ -207,18 +302,17 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
{
for ( int y = 0; y <= input.dimension( 1 ) - 1; y++ )
{
- Utils.setPosition( heightmapAccess, x, y );
+ setPosition( heightmapAccess, x, y );
final int z = heightmapAccess.get().getInteger();
if ( z == 0 )
-// if ( heightmapAccess.get().compareTo( minus ) == 0 )
{
projectionAccess.get().setReal( 0 );
}
else
{
- Utils.setPosition( stackAccess, x, y, z - 1 );
+ setPosition( stackAccess, x, y, z - 1 );
// " - 1" because by convention the z values start at 1, 0 is for unassigned values.
- Utils.setPosition( projectionAccess, x, y );
+ setPosition( projectionAccess, x, y );
projectionAccess.get().set( stackAccess.get() );
}
}
@@ -239,12 +333,12 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
{
ImgFactory< T > factory = referenceSurface.getFactory();
- RandomAccessibleInterval< T > extractedHeightMapSubStack = referenceSurface.getProjection().getExtractedHeightMapSubStack();
+ RandomAccessibleInterval< T > extractedHeightMapSubStack = referenceSurface.getProjection().getReduced3DSpace();
Img< T > projection = factory.create( extractedHeightMapSubStack.dimension( 0 ), extractedHeightMapSubStack.dimension( 1 ) );
if ( projectionType.equals( "median" ) )// sumSlices, median, standardDeviation
{
medianProjection( extractedHeightMapSubStack, projection );
- return projection; //something something
+ return projection;
}
return null;
}
@@ -274,7 +368,7 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
for ( int z = startIndex; z <= stopIndex; z++ )
{
- Utils.setPosition( stackAccess, xValue, yValue, z );
+ setPosition( stackAccess, xValue, yValue, z );
if ( stackAccess.get().compareTo( max ) >= 0 )
{
max = stackAccess.get().copy();
@@ -301,7 +395,7 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
inputAccess.setPosition( z, 2 );
column[ z ] = inputAccess.get().getRealFloat();
}
- Utils.setPosition( outputAccess, x, y );
+ setPosition( outputAccess, x, y );
outputAccess.get().setReal( median( column ) );
}
}
@@ -328,18 +422,45 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
int delta = projectionParameters.getDelta();
String projectionType = projectionParameters.getProjectionType();
- referenceSurface.getProjection().setHeightMapSubVolumeMask( getHeightMapSubVolumeStack( referenceSurface, delta ) );
+
+
+ if ( projectionType.equals( "MIP" ) ||
+ projectionType.equals( "Minimum Intensity" ) )
+ {
+ referenceSurface.getProjection().setExtractedHeightMap( getProjectionHeightMap( referenceSurface, projectionType, delta ) );
+ referenceSurface.getProjection().setReduced3DSpace( getExtractedHeightMapSubStack( referenceSurface, delta ) );
+ referenceSurface.getProjection().setProjection( projection1( referenceSurface, projectionType ) );
+// referenceSurface.getProjection().setSegmentedSurface( getSegmentedSurface( referenceSurface, delta ) );
+ referenceSurface.getProjection().setSegmentedSurface( getSegmentedSurface( referenceSurface.getProjection().getExtractedHeightMap(),
+ referenceSurface.getInput(),
+ referenceSurface.getFactory() ) );
+ }
+ else
+ {
+ referenceSurface.getProjection().setReduced3DSpace( getExtractedHeightMapSubStack( referenceSurface, delta ) );
+ referenceSurface.getProjection().setProjection( projection2( referenceSurface, projectionType ) );
+ }
+
+ }
+
+ public void set( ReferenceSurface< T > referenceSurface, int delta, String projectionType, int delta2 )
+ {
+
if ( projectionType.equals( "MIP" ) ||
projectionType.equals( "Minimum Intensity" ) )
{
- referenceSurface.getProjection().setProjectionHeightMap( getProjectionHeightMap( referenceSurface, projectionType, delta ) );
- referenceSurface.getProjection().setExtractedHeightMapSubStack( getExtractedHeightMapSubStack( referenceSurface, delta ) );
+ referenceSurface.getProjection().setExtractedHeightMap( getProjectionHeightMap( referenceSurface, projectionType, delta ) );
+ referenceSurface.getProjection().setReduced3DSpace( getExtractedHeightMapSubStack( referenceSurface, delta ) );
referenceSurface.getProjection().setProjection( projection1( referenceSurface, projectionType ) );
+ referenceSurface.getProjection().setSegmentedSurface( getSegmentedSurface( referenceSurface.getProjection().getExtractedHeightMap(),
+ referenceSurface.getInput(),
+ referenceSurface.getFactory() ) );
+ referenceSurface.getProjection().setSegmentedSurfaceMask( getSegmentedSurfaceMask( referenceSurface.getProjection().getSegmentedSurface(), delta2 ) );
}
else
{
- referenceSurface.getProjection().setExtractedHeightMapSubStack( getExtractedHeightMapSubStack( referenceSurface, delta ) );
+ referenceSurface.getProjection().setReduced3DSpace( getExtractedHeightMapSubStack( referenceSurface, delta ) );
referenceSurface.getProjection().setProjection( projection2( referenceSurface, projectionType ) );
}
@@ -353,46 +474,49 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
{
if ( displayParameters.isProjectionDisplay() )
{
-
ImageJFunctions.show( referenceSurface.getProjection().get(),
"Projection with " + projectionType + " RS n°" + referenceSurface.getIndex() );
}
if ( displayParameters.iszMapDisplay() )
{
- ImageJFunctions.show( referenceSurface.getzMap(), "Zellige generated height map" + "RS n°" + referenceSurface.getIndex() );
+ ImageJFunctions.show( referenceSurface.getzMap(), "Raw height map" + "RS n°" + referenceSurface.getIndex() );
}
-
if ( displayParameters.isExtractedHeightMapSubStackDisplay() )
{
- if ( delta != 0 )
+ if ( delta >= 0 )
{
- ImageJFunctions.show( referenceSurface.getProjection().getExtractedHeightMapSubStack(),
- "Extracted height map subStack (delta = " + delta + ")" + "RS n°" + referenceSurface.getIndex() );
+ ImageJFunctions.show( referenceSurface.getProjection().getReduced3DSpace(),
+ "Extracted surface subStack (delta = " + delta + ")" + "RS n°" + referenceSurface.getIndex() );
}
else
{
throw new NoPossibleDisplayException( "The value of parameter delta equals 0 !" );
}
}
- if ( displayParameters.isHeightMapSubVolumeMaskDisplay() )
+ if ( displayParameters.isSurfaceSubVolumeDisplay() )
{
- if ( delta != 0 )
+ if ( delta > 0 )
{
- ImageJFunctions.show( referenceSurface.getProjection().getHeightMapSubVolumeMask(),
- "Height map subVolume mask (delta = " + delta + ")" + "RS n°" + referenceSurface.getIndex() );
+ ImageJFunctions.show( referenceSurface.getProjection().getSegmentedSurface(),
+ "RS n°" + referenceSurface.getIndex() + ": segmented surface (delta = " + delta + ")" + "RS n°" + referenceSurface.getIndex() );
}
else
{
throw new NoPossibleDisplayException( "The value of parameter delta equals 0 !" );
}
}
+ if ( displayParameters.isHeightMapSubVolumeMask() )
+ {
+ ImageJFunctions.show( referenceSurface.getProjection().getSegmentedSurfaceMask(),
+ "RS n° " + referenceSurface.getIndex() + " : segmented surface mask mask (delta = " + delta );
+ }
if ( ( projectionType.equals( "MIP" ) || projectionType.equals( "Min" ) ) && displayParameters.isProjectionHeightMapDisplay() )
{
- if ( delta != 0 )
+ if ( delta >= 0 )
{
- ImageJFunctions.show( referenceSurface.getProjection().getProjectionHeightMap(), "Projection height Map with " +
+ ImageJFunctions.show( referenceSurface.getProjection().getExtractedHeightMap(), "Extracted height Map with " +
projectionType + " RS n°" + referenceSurface.getIndex() );
}
else
@@ -401,7 +525,144 @@ public class ReferenceSurfaceProjection< T extends RealType< T > & NativeType< T
}
}
+
+ }
+ }
+
+ public void display( ReferenceSurface< T > referenceSurface, int delta, String projectionType,
+ boolean projectionDisplay,
+ boolean rawHeightMapDisplay,
+ boolean extractedHeightMapDisplay,
+ boolean reduced3DSpaceDisplay,
+ boolean segmentedSurfaceDisplay,
+ boolean segmentedSurfaceMaskDisplay ) throws NoPossibleDisplayException
+ {
+
+ if ( referenceSurface.getProjection() != null )
+ {
+ if ( projectionDisplay )// the projection
+ {
+ ImageJFunctions.show( referenceSurface.getProjection().get(),
+ "Projection with " + projectionType + " RS n°" + referenceSurface.getIndex() );
+ }
+ if ( rawHeightMapDisplay )// the raw height map
+ {
+ ImageJFunctions.show( referenceSurface.getzMap(), "Zellige generated height map" + "RS n°" + referenceSurface.getIndex() );
+ }
+
+ if ( reduced3DSpaceDisplay )
+ {
+ if ( delta != 0 )
+ {
+ ImageJFunctions.show( referenceSurface.getProjection().getReduced3DSpace(),
+ "Reduced 3D space (delta = " + delta + ")" + "RS n°" + referenceSurface.getIndex() );
+ }
+ else
+ {
+ throw new NoPossibleDisplayException( "The value of parameter delta equals 0 !" );
+ }
+ }
+
+ if ( ( projectionType.equals( "MIP" ) || projectionType.equals( "Min" ) ) && extractedHeightMapDisplay ) // the extracted height map
+ {
+ if ( delta != 0 )
+ {
+ ImageJFunctions.show( referenceSurface.getProjection().getExtractedHeightMap(), "Extracted height Map with " +
+ projectionType + " RS n°" + referenceSurface.getIndex() );
+ }
+ else
+ {
+ throw new NoPossibleDisplayException( "This method does not produce a extracted height map !" );
+ }
+ }
+ if ( segmentedSurfaceDisplay )
+ {
+ if ( delta != 0 )
+ {
+ ImageJFunctions.show( referenceSurface.getProjection().getSegmentedSurface(),
+ "Height map subVolume mask (delta = " + delta + ")" + "RS n°" + referenceSurface.getIndex() );
+ }
+ else
+ {
+ throw new NoPossibleDisplayException( "The value of parameter delta equals 0 !" );
+ }
+ }
+ if ( segmentedSurfaceMaskDisplay ) // the segmented surface mask
+ {
+ ImageJFunctions.show( referenceSurface.getProjection().getSegmentedSurfaceMask(),
+ "RS n° " + referenceSurface.getIndex() + " : SubVolume mask (delta = " + delta );
+ }
}
+
}
+ public void display( ReferenceSurface< T > referenceSurface, int delta, String projectionType,
+ boolean projectionDisplay,
+ boolean rawHeightMapDisplay,
+ boolean extractedHeightMapDisplay,
+ boolean reduced3DSpaceDisplay,
+ boolean segmentedSurfaceDisplay,
+ boolean segmentedSurfaceMaskDisplay,
+ int delta2 ) throws NoPossibleDisplayException
+ {
+ if ( referenceSurface.getProjection() != null )
+ {
+ if ( projectionDisplay )// the projection
+ {
+ ImageJFunctions.show( referenceSurface.getProjection().get(),
+ "Projection with " + projectionType + " RS n°" + referenceSurface.getIndex() );
+ }
+ if ( rawHeightMapDisplay )// the raw height map
+ {
+ ImageJFunctions.show( referenceSurface.getzMap(), "Raw Height Map" + "RS n°" + referenceSurface.getIndex() );
+ }
+
+ if ( reduced3DSpaceDisplay )// the reduced 3D stack of size (X, Y, delta*2 +1)
+ {
+ if ( delta != 0 )
+ {
+ ImageJFunctions.show( referenceSurface.getProjection().getReduced3DSpace(),
+ "Reduced 3D space (delta = " + delta + ")" + "RS n°" + referenceSurface.getIndex() );
+ }
+ else
+ {
+ throw new NoPossibleDisplayException( "The value of parameter delta equals 0 !" );
+ }
+ }
+
+ if ( ( projectionType.equals( "MIP" ) || projectionType.equals( "Min" ) ) && extractedHeightMapDisplay ) // the extracted height map
+ {
+ if ( delta != 0 )
+ {
+ ImageJFunctions.show( referenceSurface.getProjection().getExtractedHeightMap(), "Extracted height Map with " +
+ projectionType + " RS n°" + referenceSurface.getIndex() );
+ }
+ else
+ {
+ throw new NoPossibleDisplayException( "This method does not produce a extracted height map !" );
+ }
+ }
+ if ( segmentedSurfaceDisplay )
+ {
+ if ( delta > 0 )
+ {
+ ImageJFunctions.show( referenceSurface.getProjection().getSegmentedSurface(),
+ "Segmented surface (delta = " + delta + ")" + "RS n°" + referenceSurface.getIndex() );
+ }
+ else
+ {
+ throw new NoPossibleDisplayException( "The value of parameter delta equals 0 !" );
+ }
+ }
+ if ( segmentedSurfaceMaskDisplay ) // the segmented surface mask
+ {
+ ImageJFunctions.show( referenceSurface.getProjection().getSegmentedSurfaceMask(),
+ "RS n° " + referenceSurface.getIndex() + " : Segmented surface mask (delta = " + delta2 );
+ }
+ }
+
+ }
}
+
+
+
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/selection/Selection.java b/src/main/java/fr/pasteur/ida/zellige/steps/selection/Selection.java
index 8c4ab7275bcf8cf6d54afd165f117dc70ee2ccf8..50d92f1d4c8c29be24e35565085e084d7b81cfad 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/selection/Selection.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/selection/Selection.java
@@ -29,7 +29,7 @@ public class Selection< T extends RealType< T > & NativeType< T > >
{
private final static Logger LOGGER = LoggerFactory.getLogger( Selection.class );
- private final PretreatmentParameters pretreatmentParameters;
+ private final double radius;
private final ClassificationParameters classificationParameters;
private final PostTreatmentParameters postTreatmentParameters;
private final RandomAccessibleInterval< T > input;
@@ -42,7 +42,7 @@ public class Selection< T extends RealType< T > & NativeType< T > >
public Selection( PretreatmentParameters pretreatmentParameters, ClassificationParameters classificationParameters, PostTreatmentParameters postTreatmentParameters,
RandomAccessibleInterval< T > input )
{
- this.pretreatmentParameters = pretreatmentParameters;
+ this.radius = pretreatmentParameters.getParameter();
this.classificationParameters = classificationParameters;
this.postTreatmentParameters = postTreatmentParameters;
this.input = input;
@@ -55,21 +55,15 @@ public class Selection< T extends RealType< T > & NativeType< T > >
Selection< T > selection = new Selection<>( pretreatmentParameters, classificationParameters, postTreatmentParameters, input );
selection.run();
LOGGER.info( "Process complete." );
-
-
return selection.output;
}
+
public static Logger getLOGGER()
{
return LOGGER;
}
- public Pixels[][] getOutput()
- {
- return output;
- }
-
public static long getAmplitudePT()
{
return amplitudePT;
@@ -93,16 +87,18 @@ public class Selection< T extends RealType< T > & NativeType< T > >
public void run() throws EmptyOutputException, NoClassificationException, DataValidationException
{
/* Pretreatment of the image.*/
- Img< FloatType > pretreatedImage = Pretreatment.run( input, pretreatmentParameters );
-// ImageJFunctions.show( pretreatedImage, " pretreatedImage" );
+ Img< FloatType > pretreatedImage = Pretreatment.run( input, radius );
/* Classification. */
Img< BitType > classifiedPixel = Classification.run( pretreatedImage, pretreatedImage.factory(), classificationParameters );
amplitudePT = AmplitudeClassification.getProcessingTime();
otsuPT = OtsuClassification.getProcessingTime();
-// ImageJFunctions.show( classifiedPixel );
/* PostTreatment and output*/
output = PostTreatment.run( classifiedPixel, postTreatmentParameters );
islandSearchPT = IslandSearch.getProcessingTime();
-// displayMaximums( maximums );
+ }
+
+ public Pixels[][] getOutput()
+ {
+ return output;
}
}
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/AmplitudeClassification.java b/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/AmplitudeClassification.java
index 0de333ce17b77cff726e2d3bcd2fa1973568736b..b5d2ca8adcf1ba9bdd14b272c6f53004e37e294c 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/AmplitudeClassification.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/AmplitudeClassification.java
@@ -26,24 +26,23 @@ public class AmplitudeClassification< T extends RealType< T > & NativeType< T >
private final RandomAccessibleInterval< T > input;
private final ImgFactory< T > factory;
- private final double userThreshold;
+ private double userThreshold;
private Img< BitType > output;
private static long processingTime;
+ private static double firstMaxValue;
private final static Logger LOGGER = LoggerFactory.getLogger( AmplitudeClassification.class );
+
public AmplitudeClassification( RandomAccessibleInterval< T > input,
- ImgFactory< T > factory, Img< BitType > amplitude,
- double userThreshold )
+ ImgFactory< T > factory )
{
this.input = input;
this.factory = factory;
- this.output = amplitude;
- this.userThreshold = userThreshold;
- LOGGER.info( "User input = {}", userThreshold );
LOGGER.info( "Derivative method used : {}", ReferenceSurfaceExtraction.getDerivativeMethod() );
}
+
/**
* @param <T> - the type of the input
* @param input - the input image as a {@link RandomAccessibleInterval}
@@ -65,12 +64,52 @@ public class AmplitudeClassification< T extends RealType< T > & NativeType< T >
return classification.getOutput();
}
+ public static < T extends RealType< T > & NativeType< T > > Img< BitType >
+ applyThreshold( Img< T > input, T value, double userThreshold )
+ {
+ value.mul( userThreshold );
+ return Thresholder.threshold( input, value, true, 5 );
+ }
+
+ public static < T extends RealType< T > & NativeType< T > > Img< BitType >
+ applyThreshold( Img< T > input, int userThreshold )
+ {
+ T value = input.firstElement().createVariable();
+ value.setReal( ( float ) userThreshold );
+ return Thresholder.threshold( input, value, true, 5 );
+ }
+
+ public AmplitudeClassification( RandomAccessibleInterval< T > input,
+ ImgFactory< T > factory, Img< BitType > amplitude,
+ double userThreshold )
+ {
+ this.input = input;
+ this.factory = factory;
+ this.output = amplitude;
+ this.userThreshold = userThreshold;
+ LOGGER.info( "Derivative method used : {}", ReferenceSurfaceExtraction.getDerivativeMethod() );
+ }
+
+ /**
+ * @param <T> - the type of the input
+ * @param input - the input image as a {@link RandomAccessibleInterval}
+ * @param factory the input image {@link ImgFactory}
+ * @return a binary image of background foreground classification based on contrast
+ * @throws DataValidationException if the value of parameter amplitudeThreshold is not valid.
+ */
+ public static < T extends RealType< T > & NativeType< T > > Img< T > computeAmplitudeImage( final RandomAccessibleInterval< T > input,
+ final ImgFactory< T > factory ) throws DataValidationException
+ {
+ AmplitudeClassification< T > classification =
+ new AmplitudeClassification<>( input, factory );
+ return classification.getAmplitudeImg();
+ }
/**
* @param max the image containing only the values of local maximums
* @param min the image containing only the values of local minimums
* @return an image containing the value of the maximums amplitude
*/
- private Img< T > getAmplitude(
+ private Img< T > getAmplitude(
RandomAccessibleInterval< T > max, ImgFactory< T > factory, RandomAccessibleInterval< T > min )
{
Img< T > amp = factory.create( max );
@@ -161,17 +200,21 @@ public class AmplitudeClassification< T extends RealType< T > & NativeType< T >
return maxValue;
}
+ public static double getFirstMaxValue()
+ {
+ return firstMaxValue;
+ }
+
//
public void run() throws DataValidationException
{
Img< T > maximums = ExtremaDetection.findMaxima( input, factory );
Img< T > minimums = ExtremaDetection.findMinima( input, factory );
Img< T > amp = getAmplitude( maximums, factory, minimums );
- T TMax = Threshold.getFirstMaxValue( maximums, false );
- LOGGER.debug( "threshold value before user = {} ", TMax );
- TMax.mul( userThreshold );
- LOGGER.debug( "Threshold value after user = {}", TMax );
- output = Thresholder.threshold( amp, TMax, true, 5 );
+ T threshold = maximums.firstElement().createVariable();
+ threshold.setReal( userThreshold );
+ LOGGER.info( "Amplitude Threshold applied = {}", threshold );
+ output = Thresholder.threshold( amp, threshold, true, 5 );
}
@@ -180,6 +223,13 @@ public class AmplitudeClassification< T extends RealType< T > & NativeType< T >
return output;
}
+ public Img< T > getAmplitudeImg() throws DataValidationException
+ {
+ Img< T > maximums = ExtremaDetection.findMaxima( input, factory );
+ Img< T > minimums = ExtremaDetection.findMinima( input, factory );
+ return getAmplitude( maximums, factory, minimums );
+ }
+
public static long getProcessingTime()
{
return processingTime;
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/Classification.java b/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/Classification.java
index 4e757a786537169f84cde08e007f2ea5b8682eaf..d199728cb4916f6f5f4c53add34baf4b9b4df85c 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/Classification.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/Classification.java
@@ -27,13 +27,18 @@ public class Classification< T extends RealType< T > & NativeType< T > >
public static final int ZERO = 0;
private final static Logger LOGGER = LoggerFactory.getLogger( Classification.class );
private final RandomAccessibleInterval< T > input;
+ private final ImgFactory< T > factory;
private Img< BitType > output;
- private Classification( RandomAccessibleInterval< T > input )
+
+ private Classification( RandomAccessibleInterval< T > input, ImgFactory< T > factory )
{
this.input = input;
+ this.factory = factory;
}
+
+
/**
* Static method to provide a 2-part classification on a 3D image
*
@@ -48,9 +53,8 @@ public class Classification< T extends RealType< T > & NativeType< T > >
public static < T extends RealType< T > & NativeType< T > > Img< BitType >
run( RandomAccessibleInterval< T > input, ImgFactory< T > factory, ClassificationParameters parameters ) throws NoClassificationException, DataValidationException
{
- Classification< T > classification = new Classification<>( input );
+ Classification< T > classification = new Classification<>( input, factory );
classification.process( factory, parameters );
-// ImageJFunctions.show( classification.output, "classification" );
return classification.output;
}
@@ -63,8 +67,8 @@ public class Classification< T extends RealType< T > & NativeType< T > >
void process( ImgFactory< T > factory, ClassificationParameters parameters ) throws NoClassificationException, DataValidationException
{
LOGGER.info( "Starting classification..." );
- double amplitudeThreshold = parameters.getAmplitudeThreshold();
- double otsuThreshold = parameters.getOtsuThreshold();
+ int amplitudeThreshold = parameters.getAmplitudeThreshold();
+ int otsuThreshold = parameters.getOtsuThreshold();
if ( amplitudeThreshold != ZERO && otsuThreshold != ZERO )
{
processBothClassification( factory, amplitudeThreshold, otsuThreshold );
@@ -85,19 +89,19 @@ public class Classification< T extends RealType< T > & NativeType< T > >
}
- void processAmplitudeClassification( ImgFactory< T > factory, double amplitudeThreshold ) throws DataValidationException
+ void processAmplitudeClassification( ImgFactory< T > factory, int amplitudeThreshold ) throws DataValidationException
{
/* Classification according to maximum amplitude */
output = AmplitudeClassification.run( input, factory, amplitudeThreshold );
}
- void processOtsuClassification( ImgFactory< T > factory, double otsuThreshold )
+ void processOtsuClassification( ImgFactory< T > factory, int otsuThreshold )
{
/* Classification according to local intensity*/
output = OtsuClassification.run( input, factory, otsuThreshold );
}
- void processBothClassification( ImgFactory< T > factory, double amplitudeThreshold, double otsuThreshold ) throws DataValidationException
+ void processBothClassification( ImgFactory< T > factory, int amplitudeThreshold, int otsuThreshold ) throws DataValidationException
{
/* Classification according to maximum amplitude */
Img< BitType > amplitudeImg = AmplitudeClassification.run( input, factory, amplitudeThreshold );
@@ -114,9 +118,41 @@ public class Classification< T extends RealType< T > & NativeType< T > >
* @param thresholds another {@link BitType}{@link Img}
* @return the intersection of both image
*/
- private Img< BitType > interClassification( IterableInterval< BitType > amplitude,
- ImgFactory< BitType > factory,
- RandomAccessibleInterval< BitType > thresholds )
+ public static Img< BitType > interClassification( IterableInterval< BitType > amplitude,
+ ImgFactory< BitType > factory,
+ RandomAccessibleInterval< BitType > thresholds )
+ {
+ Img< BitType > output = factory.create( thresholds );
+ Cursor< BitType > amplitudeCursor = amplitude.localizingCursor();
+ RandomAccess< BitType > thresholdAccess
+ = thresholds.randomAccess();
+ RandomAccess< BitType > outputAccess = output.randomAccess();
+ while ( amplitudeCursor.hasNext() )
+ {
+ amplitudeCursor.fwd();
+ if ( amplitudeCursor.get().getRealDouble() != 0 )
+ {
+ thresholdAccess.setPosition( amplitudeCursor );
+ if ( thresholdAccess.get().get() )
+ {
+ outputAccess.setPosition( amplitudeCursor );
+ outputAccess.get().setOne();
+ }
+ }
+ }
+ return output;
+ }
+
+
+ /**
+ * @param amplitude an {@link BitType}{@link Img}
+ * @param factory the same {@link BitType} {@link ImgFactory} as amplitude
+ * @param thresholds another {@link BitType}{@link Img}
+ * @return the intersection of both image
+ */
+ public static Img< BitType > runInterClassification( IterableInterval< BitType > amplitude,
+ ImgFactory< BitType > factory,
+ RandomAccessibleInterval< BitType > thresholds )
{
Img< BitType > output = factory.create( thresholds );
Cursor< BitType > amplitudeCursor = amplitude.localizingCursor();
@@ -138,4 +174,6 @@ public class Classification< T extends RealType< T > & NativeType< T > >
}
return output;
}
+
+
}
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/ClassificationParameters.java b/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/ClassificationParameters.java
index c1ac9ed2541a91eb6d1fb45f8372cac231d046c7..1147477ccfe7ed9e7fd824596a516e00c5fc6b35 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/ClassificationParameters.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/ClassificationParameters.java
@@ -8,50 +8,56 @@ public class ClassificationParameters
{
private final static Logger LOGGER = LoggerFactory.getLogger( ClassificationParameters.class );
- private final double amplitudeThreshold, otsuThreshold;
+ private final int amplitudeThreshold, otsuThreshold;
- public ClassificationParameters( double amplitudeThreshold, double otsuThreshold ) throws DataValidationException
+ public ClassificationParameters( int amplitudeThreshold, int otsuThreshold ) throws DataValidationException
{
classificationParametersValidationCheck( amplitudeThreshold, otsuThreshold );
this.amplitudeThreshold = amplitudeThreshold;
this.otsuThreshold = otsuThreshold;
+ LOGGER.info( "Classification parameters are valid" );
}
/**
- *
- * @param name the parameter name to display in the error message.
+ * @param name the parameter name to display in the error message.
* @param value the value of the parameter tested.
* @throws DataValidationException if the value is inferior to zero.
*/
- private void valueValidationCheck( String name, double value ) throws DataValidationException
+ public static void valueValidationCheck( String name, int value ) throws DataValidationException
{
if ( value < 0 )
{
throw new DataValidationException( "The value of parameter " + name + " has to be superior to zero !" );
}
+ if ( value > 255 )
+ {
+ throw new DataValidationException( "The value of parameter " + name + " has to be inferior or equals to 50!" );
+ }
+
}
/**
* Checks the four parameters validity.
+ *
* @param amplitudeThreshold - the value choose as amplitude threshold.
- * @param otsuThreshold - the value choose as otsu threshold.
+ * @param otsuThreshold - the value choose as otsu threshold.
* @throws DataValidationException if at least one parameter is not valid.
*/
- public void classificationParametersValidationCheck( double amplitudeThreshold, double otsuThreshold) throws DataValidationException
+ public void classificationParametersValidationCheck( int amplitudeThreshold, int otsuThreshold ) throws DataValidationException
{
valueValidationCheck( "Amplitude Threshold", amplitudeThreshold );
valueValidationCheck( "Otsu Threshold", otsuThreshold );
}
- public double getAmplitudeThreshold()
+ public int getAmplitudeThreshold()
{
return amplitudeThreshold;
}
- public double getOtsuThreshold()
+ public int getOtsuThreshold()
{
return otsuThreshold;
}
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/OtsuClassification.java b/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/OtsuClassification.java
index 970b2c7f86f7017df27b3fcb0becd37c4682db74..a59eab2becd92b67cb804086a75773c85870a42a 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/OtsuClassification.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/OtsuClassification.java
@@ -18,20 +18,20 @@ import java.util.List;
public class OtsuClassification< T extends RealType< T > & NativeType< T > >
{
- private final RandomAccessibleInterval< T > input;
- private final RandomAccessibleInterval< T > grid;
- private final Img< BitType > output;
- private final double userThreshold;
- private static long processingTime;
-
private final static Logger LOGGER = LoggerFactory.getLogger( OtsuClassification.class );
+ private static long processingTime;
+ private final RandomAccessibleInterval< T > input;
+ private final Img< T > grid;
+ private Img< BitType > output;
+ private int userThreshold;
/**
- * @param input the input {@link Img}
+ * @param input the input image as a {@link RandomAccessibleInterval}
+ * @param factory the input factory
* @param output the resulting binary image as a {@link Img<BitType> }
- * @param userThreshold the percentage of global otsu value
+ * @param userThreshold the the user's intensity threshold
*/
- private OtsuClassification( final RandomAccessibleInterval< T > input, final ImgFactory< T > factory, final Img< BitType > output, double userThreshold )
+ private OtsuClassification( final RandomAccessibleInterval< T > input, final ImgFactory< T > factory, final Img< BitType > output, int userThreshold )
{
this.input = input;
this.output = output;
@@ -40,24 +40,35 @@ public class OtsuClassification< T extends RealType< T > & NativeType< T > >
}
/**
- * @param input the input {@link Img}
- * @param factory the {@link ImgFactory} of the input image
- * @param percent the percentage of global otsu value
- * @param <T> the type on the input
+ * @param input the input image as a {@link RandomAccessibleInterval}
+ * @param factory the input factory
+ */
+ private OtsuClassification( final RandomAccessibleInterval< T > input, final ImgFactory< T > factory )
+ {
+ this.input = input;
+ this.grid = factory.create( input );
+ }
+
+ /**
+ * @param input the input image as a {@link RandomAccessibleInterval}
+ * @param factory the {@link ImgFactory} of the input image
+ * @param userThreshold the percentage of global otsu value
+ * @param <T> the type on the input
* @return a 3D binary image
*/
- public static < T extends RealType< T > & NativeType< T > > Img< BitType > run( final RandomAccessibleInterval< T > input, ImgFactory< T > factory, double percent )
+ public static < T extends RealType< T > & NativeType< T > > Img< BitType > run( final RandomAccessibleInterval< T > input, ImgFactory< T > factory, int userThreshold )
{
- if ( percent > 0 )
+ if ( userThreshold > 0 )
{
- // Prepare output.
long start = System.currentTimeMillis();
+ // Prepare output.
final ImgFactory< BitType > bitTypeImgFactory = net.imglib2.util.Util.getArrayOrCellImgFactory( input, new BitType() );
Img< BitType > binary = bitTypeImgFactory.create( input );
- OtsuClassification< T > classification = new OtsuClassification<>( input, factory, binary, percent );
+ OtsuClassification< T > classification = new OtsuClassification<>( input, factory, binary, userThreshold );
classification.run();
long stop = System.currentTimeMillis();
- classification.setProcessingTime( stop - start );
+ LOGGER.debug( "Otsu classification done in {} s", ( ( stop - start ) / 1000.0 ) );
+ classification.setProcessingTime( ( stop - start ) );
return classification.getOutput();
}
else
@@ -67,16 +78,32 @@ public class OtsuClassification< T extends RealType< T > & NativeType< T > >
}
/**
- * @param input the input image as an {@link IterableInterval}
- * @param grid the image containing the grid of local thresholds as an {@link IterableInterval}
- * @param output the resulting output image as a {@link RandomAccessibleInterval<BitType> }
- * @param percent the percentage of global otsu value
- * @param <T> the input type
+ * @param input
+ * @param factory
+ * @param <T>
+ * @return
+ */
+ public static < T extends RealType< T > & NativeType< T > > Img< T > computeOtsuImage( final RandomAccessibleInterval< T > input, ImgFactory< T > factory )
+ {
+ OtsuClassification< T > classification = new OtsuClassification<>( input, factory );
+ classification.computeLocalThreshold( input, classification.grid );
+ return classification.getGrid();
+ }
+
+
+ /**
+ * @param input
+ * @param grid
+ * @param userThreshold
+ * @param <T>
+ * @return
*/
- private static < T extends RealType< T > & NativeType< T > > void
- applyLocalThreshold( IterableInterval< T > input, IterableInterval< T > grid, RandomAccessibleInterval< BitType > output, double percent )
+ public static < T extends RealType< T > & NativeType< T > > Img< BitType >
+ applyLocalThreshold( IterableInterval< T > input, IterableInterval< T > grid, int userThreshold )
{
- double threshold = Threshold.getThreshold( input, percent ).getRealDouble();
+ long start = System.currentTimeMillis();
+ final ImgFactory< BitType > bitTypeImgFactory = net.imglib2.util.Util.getArrayOrCellImgFactory( input, new BitType() );
+ Img< BitType > output = bitTypeImgFactory.create( input );
Cursor< T > sourceCursor = input.localizingCursor();
Cursor< T > gridCursor = grid.cursor();
RandomAccess< BitType > randomAccess = output.randomAccess();
@@ -84,19 +111,22 @@ public class OtsuClassification< T extends RealType< T > & NativeType< T > >
{
sourceCursor.fwd();
gridCursor.fwd();
- final double s = sourceCursor.get().getRealDouble();
- final double o = gridCursor.get().getRealDouble();
+ final double intensityValue = sourceCursor.get().getRealDouble();
+ final double localThreshold = gridCursor.get().getRealDouble();
{
- if ( s >= Math.max( o, threshold ) )// background subtraction
+ if ( intensityValue >= Math.max( localThreshold, userThreshold ) )// background subtraction
{
randomAccess.setPosition( sourceCursor );
randomAccess.get().set( true );
}
}
}
- LOGGER.debug( "Local thresholds applied." );
+ long stop = System.currentTimeMillis();
+ LOGGER.debug( "Threshold applied in {} s.", ( ( stop - start ) / 1000.0 ) );
+ return output;
}
+
/**
* @param input the input {@link Img}
* @param grid the image containing the grid of local thresholds
@@ -104,21 +134,31 @@ public class OtsuClassification< T extends RealType< T > & NativeType< T > >
private void
computeLocalThreshold( RandomAccessibleInterval< T > input, RandomAccessibleInterval< T > grid )
{
+ long start = System.currentTimeMillis();
long width = input.dimension( 0 );
long height = input.dimension( 1 );
long depth = input.dimension( 2 );
List< Interval > intervals = Grids.collectAllContainedIntervals( new long[]{ width, height, depth },
- new int[]{ 40, 40, 3 } );//TODO Size of a grid cube ?
+ new int[]{ 40, 40, 3 } );
for ( Interval interval : intervals )
{
computeLocalThreshold( input, grid, interval );
}
Utils.gaussianConvolution( grid, grid, new double[]{ 5, 5, 1 } );
-// ImageJFunctions.show(grid, "grid ");
- LOGGER.info( "Local thresholds computed with user value = {}.", this.userThreshold );
+ long stop = System.currentTimeMillis();
+ LOGGER.info( "Local thresholds computed in {} s.", ( ( stop - start ) / 1000.0 ) );
+
}
+ /**
+ * This method applies an Otsu threshold on a specified interval on a given image.
+ *
+ * @param input the input image as a {@link RandomAccessibleInterval}
+ * @param grid the local thresholds image as a {@link RandomAccessibleInterval}
+ * @param interval the considered interval of the image as a {@link Interval}
+ */
+
private void
computeLocalThreshold( RandomAccessibleInterval< T > input, RandomAccessibleInterval< T > grid, Interval interval )
{
@@ -126,7 +166,6 @@ public class OtsuClassification< T extends RealType< T > & NativeType< T > >
IntervalView< T > viewGrid = Views.offsetInterval( grid, interval );
T threshold = Otsu.getThreshold( viewSource );
viewGrid.forEach( pixel -> pixel.set( threshold ) );
-
}
/**
@@ -135,7 +174,10 @@ public class OtsuClassification< T extends RealType< T > & NativeType< T > >
private void run()
{
computeLocalThreshold( input, grid );
- applyLocalThreshold( Views.iterable( input ), Views.iterable( grid ), output, userThreshold );
+
+ output = applyLocalThreshold( Views.iterable( input ), Views.iterable( grid ), userThreshold );
+ LOGGER.info( "Local thresholds computed with user value = {}.", this.userThreshold );
+
}
/**
@@ -146,6 +188,12 @@ public class OtsuClassification< T extends RealType< T > & NativeType< T > >
return output;
}
+ private Img< T > getGrid()
+ {
+ return grid;
+ }
+
+
public static long getProcessingTime()
{
return processingTime;
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/Threshold.java b/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/Threshold.java
index 474d0f2b21e8cd45ccdc18c0b1764d022a26ccd0..10ddd6f7c1e6692f837c72b6c9b403a283e66dcb 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/Threshold.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/selection/classification/Threshold.java
@@ -170,6 +170,15 @@ public class Threshold
}
+ public static < T extends RealType< T > & NativeType< T > > T getThreshold( IterableInterval< T > input )
+ {
+ T max = Threshold.findMax( input );
+ T min = Threshold.findMin( input );
+ int[] histogram = getHistogram( input, min, max, 256 );
+ return getThreshold( min, max, histogram );
+ }
+
+
public static < T extends RealType< T > & NativeType< T > > T getThreshold( IterableInterval< T > input, double percent )
{
T max = Threshold.findMax( input );
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/PostTreatment.java b/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/PostTreatment.java
index 665344617e3adae51444123d7c23372ad80b8d15..492b5a19db47984a45a937bc2c222c9913cc4aa9 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/PostTreatment.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/PostTreatment.java
@@ -27,6 +27,7 @@ public class PostTreatment
private Pixels[][] output;
private final Img< BitType > input;
+
public PostTreatment( Img< BitType > input )
{
this.input = input;
@@ -39,6 +40,13 @@ public class PostTreatment
return postTreatment.getOutput();
}
+ public static Pixels[][] run( Img< BitType > input, double sigmaXY, double sigmaZ, int islandSize, int connexity ) throws DataValidationException
+ {
+ PostTreatment postTreatment = new PostTreatment( input );
+ postTreatment.process( sigmaXY, sigmaZ, islandSize, connexity );
+ return postTreatment.getOutput();
+ }
+
/**
* @param image - the source image as a float type {@link IterableInterval}
* @return the source image converted into float type Img object
@@ -68,10 +76,10 @@ public class PostTreatment
Img< BitType > runIslandSearch(Img< BitType > input , int islandSize, int connexity)
{
- return IslandSearch.run( input, islandSize, connexity );
+ return IslandSearch.run( input, islandSize, connexity );
}
- void runDilatation( Img<FloatType> input, PostTreatmentParameters parameters )
+ void runDilatation( Img< FloatType > input, PostTreatmentParameters parameters )
{
double sigmaXY = parameters.getSigmaXY();
double sigmaZ = parameters.getSigmaZ();
@@ -79,13 +87,18 @@ public class PostTreatment
Utils.gaussianConvolution( input.copy(), input, new double[]{ sigmaXY, sigmaXY, sigmaZ } );
}
+ void runDilatation( Img< FloatType > input, double sigmaXY, double sigmaZ )
+ {
+ LOGGER.info( "Running dilatation with sigma XY = {} and sigma Z = {}", sigmaXY, sigmaZ );
+ Utils.gaussianConvolution( input.copy(), input, new double[]{ sigmaXY, sigmaXY, sigmaZ } );
+ }
+
/**
- *
* @param stack an image as a {@link RandomAccessibleInterval}
- * @param <T> the image type
+ * @param <T> the image type
* @return the image as a 2D {@link Pixels} array.
*/
- public < T extends RealType< T > & NativeType< T > > Pixels[][] buildPixelArray(
+ public < T extends RealType< T > & NativeType< T > > Pixels[][] buildPixelArray(
final RandomAccessibleInterval< T > stack )
{
RandomAccess< T > access = stack.randomAccess();
@@ -138,6 +151,28 @@ public class PostTreatment
LOGGER.info( "Post treatment complete" );
}
+ public void process( double sigmaXY, double sigmaZ, int islandSize, int connexity ) throws DataValidationException
+ {
+ LOGGER.info( "Starting post treatment." );
+ /* Isolated Pixel removal */
+ Img< BitType > temp = input;
+ if ( islandSize != 0 )
+ {
+ temp = runIslandSearch( input, islandSize, connexity );
+ }
+ /* Conversion into FloatType before dilatation */
+ Img< FloatType > converted = convertBitTypeIntoFloatType( temp );
+ // Use of Converter.convert() not possible because classifiedPixel type do not extends RealType
+
+ /* Dilatation of the resulting image*/
+ runDilatation( converted, sigmaXY, sigmaZ );
+
+ /* Final local maximum detection */
+ converted = ExtremaDetection.findMaxima( converted.copy(), converted.factory() );
+ output = buildPixelArray( converted );
+ LOGGER.info( "Post treatment complete" );
+ }
+
public Pixels[][] getOutput()
{
return output;
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/PostTreatmentParameters.java b/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/PostTreatmentParameters.java
index aeb4bae45ab507fd2d73eb0f9e3f1567d515b9f5..9ec464eef190b5d34c1261846512e5c4c540bcd3 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/PostTreatmentParameters.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/PostTreatmentParameters.java
@@ -31,24 +31,23 @@ public class PostTreatmentParameters
* @param islandSize the minimum size of the island search
* @throws DataValidationException if at least one parameter is not valid.
*/
- public void postTreatmentParametersValidationCheck( double sigmaXY, double sigmaZ, int islandSize) throws DataValidationException
+ public static void postTreatmentParametersValidationCheck( double sigmaXY, double sigmaZ, int islandSize ) throws DataValidationException
{
valueValidationCheck( SIGMA_XY, sigmaXY );
- valueValidationCheck( SIGMA_Z, sigmaZ);
- valueValidationCheck( ISLAND_SIZE , islandSize);
+ valueValidationCheck( SIGMA_Z, sigmaZ );
+ valueValidationCheck( ISLAND_SIZE, islandSize );
}
/**
- *
- * @param name the parameter name to display in the error message.
+ * @param name the parameter name to display in the error message.
* @param value the value of the parameter tested.
* @throws DataValidationException if the value is inferior to zero.
*/
- private void valueValidationCheck( String name, double value ) throws DataValidationException
+ private static void valueValidationCheck( String name, double value ) throws DataValidationException
{
- if (name.equals( CONNEXITY ))
+ if ( name.equals( CONNEXITY ) )
{
- if (value!= 4 && value!= 8)
+ if ( value != 4 && value != 8 )
{
throw new DataValidationException( "The value of parameter " + name + " has to be 4 or 8 !" );
}
@@ -59,6 +58,7 @@ public class PostTreatmentParameters
{
throw new DataValidationException( "The value of parameter " + name + " has to be superior to zero !" );
}
+
}
}
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/islandSearch/IslandSearch.java b/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/islandSearch/IslandSearch.java
index 9d95e65aa875758df9fc2fcf0ec42770dc912885..203db928678b0f85b97652f30fe7fff88471ac69 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/islandSearch/IslandSearch.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/selection/postTreatment/islandSearch/IslandSearch.java
@@ -84,6 +84,7 @@ public class IslandSearch
*/
private World convertImgIntoWorld()
{
+ inputCount = 0;
int width = ( int ) classifiedImage.dimension( 0 );
int height = ( int ) classifiedImage.dimension( 1 );
int depth = ( int ) classifiedImage.dimension( 2 );
@@ -114,6 +115,7 @@ public class IslandSearch
*/
private void convertWorldIntoImg( World world, Img< BitType > image )
{
+ pixelRemovedCount = 0;
RandomAccess< BitType > access = image.randomAccess();
for ( int z = 0; z < world.getDepth(); z++ )
{
diff --git a/src/main/java/fr/pasteur/ida/zellige/steps/selection/pretreatment/Pretreatment.java b/src/main/java/fr/pasteur/ida/zellige/steps/selection/pretreatment/Pretreatment.java
index 551eabd26e856b0e70a75c13ffcae4872bd70804..b3873e153572416ea93877df5e92ef0702fbabaf 100644
--- a/src/main/java/fr/pasteur/ida/zellige/steps/selection/pretreatment/Pretreatment.java
+++ b/src/main/java/fr/pasteur/ida/zellige/steps/selection/pretreatment/Pretreatment.java
@@ -22,22 +22,23 @@ public class Pretreatment< T extends RealType< T > & NativeType< T > >
private final static Logger LOGGER = LoggerFactory.getLogger( Pretreatment.class );
private final RandomAccessibleInterval< T > input;
- private final PretreatmentParameters pretreatmentParameters;
+ // private final PretreatmentParameters pretreatmentParameters;
+ private final double radius;
private Img< FloatType > output;
- Pretreatment( RandomAccessibleInterval< T > input, PretreatmentParameters pretreatmentParameters )
+ Pretreatment( RandomAccessibleInterval< T > input, double radius )
{
this.input = input;
- this.pretreatmentParameters = pretreatmentParameters;
+ this.radius = radius;
}
public static < T extends RealType< T > & NativeType< T > > Img< FloatType >
- run( RandomAccessibleInterval< T > input, PretreatmentParameters pretreatmentParameters )
+ run( RandomAccessibleInterval< T > input, double radius )
{
LOGGER.debug( "Starting process..." );
- Pretreatment< T > pretreatment = new Pretreatment<>( input, pretreatmentParameters );
+ Pretreatment< T > pretreatment = new Pretreatment<>( input, radius );
pretreatment.run();
LOGGER.info( "Process complete." );
return pretreatment.getOutput();
@@ -46,12 +47,13 @@ public class Pretreatment< T extends RealType< T > & NativeType< T > >
/**
* Normalizes the pixel values of an Img between 0 and 255.
*
- * @param image - the input Img.
- * @param <T> - the type of the input Img.
+ * @param <T> - the type of the input Img.
+ * @param image - the input Img.
+ * @param factory
* @return a new Img with normalize pixel intensity values.
*/
private static < T extends RealType< T > & NativeType< T > > Img< T > normalizeImage(
- RandomAccessibleInterval< T > image, ImgFactory< T > factory )
+ Img< T > image, ImgFactory< T > factory )
{
Img< T > normalizedImage = factory.create( image );
ImgUtil.copy( image, normalizedImage );
@@ -97,7 +99,6 @@ public class Pretreatment< T extends RealType< T > & NativeType< T > >
void run()
{
-
// The input is converted into FloatType
RandomAccessibleInterval< FloatType > converted = Converters.convert( input, new RealFloatSamplerConverter<>() );
LOGGER.debug( "Input converted." );
@@ -118,8 +119,7 @@ public class Pretreatment< T extends RealType< T > & NativeType< T > >
Img< FloatType > gaussianBlurFilterDenoising( RandomAccessibleInterval< FloatType > input )
{
ImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() );
- double parameters = pretreatmentParameters.getParameter();
- return gaussianConvolution( input, factory, new double[]{ parameters, parameters, 1 } );
+ return gaussianConvolution( input, factory, new double[]{ radius, radius, 1 } );
}
public RandomAccessibleInterval< T > getInput()
diff --git a/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/HMvsGT_Display.java b/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/HMvsGT_Display.java
index 72b06b6739b2e9ef4f1a0071d95624251bc381de..74ea63d827204c1ee8e6db4bd5ddefe1ab52dbbf 100644
--- a/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/HMvsGT_Display.java
+++ b/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/HMvsGT_Display.java
@@ -61,8 +61,8 @@ public class HMvsGT_Display< T extends RealType< T > & NativeType< T >, R extend
public static void main( String[] args )
{
- String pathGT = "C:\\Users\\ctrebeau\\Desktop\\Covid Zellige\\C2-MucilairB spike zo1 J4 Sars-3_Ground truth Height map.tif";
- String pathHM = "C:\\Users\\ctrebeau\\Desktop\\Covid Zellige\\C2-MucilairB spike zo1 J4 Sars-3_HM.tif";
+ String pathGT = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\files\\Organoid\\Organoid_GT_HM2.tif";
+ String pathHM = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\Paper_012022\\Organoid\\Organoid_HM_0.tif";
final SCIFIOImgPlus< ? > imgPlusRef = IO.openImgs( pathGT ).get( 0 );
Img< FloatType > GT = ( Img< FloatType > ) imgPlusRef.getImg();
diff --git a/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/HeightMapArrayWriter.java b/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/HeightMapArrayWriter.java
new file mode 100644
index 0000000000000000000000000000000000000000..0808a25536d8fae62e6168eb3af3cd60e63904d8
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/HeightMapArrayWriter.java
@@ -0,0 +1,87 @@
+package fr.pasteur.ida.zellige.utils.jzy3D;
+
+import fr.pasteur.ida.zellige.element.Surface;
+import fr.pasteur.ida.zellige.utils.test.CSVWriter;
+import io.scif.img.IO;
+import io.scif.img.SCIFIOImgPlus;
+import net.imglib2.Cursor;
+import net.imglib2.img.Img;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import org.jzy3d.analysis.AbstractAnalysis;
+
+import java.io.IOException;
+
+public class HeightMapArrayWriter< T extends RealType< T > & NativeType< T > > extends AbstractAnalysis
+{
+
+ private final Img< T > surface;
+ private final String originalInput;
+ private final int surfaceNumber;
+
+ public HeightMapArrayWriter( Img< T > surface, String originalInput, int surfaceNumber ) throws IOException
+ {
+
+ this.surface = surface;
+ this.originalInput = originalInput;
+ this.surfaceNumber = surfaceNumber;
+ init();
+ }
+
+ /**
+ * Displays the local maximums found using jzy3D package.
+ *
+ * @param surface the {@link Surface} to display
+ */
+ public static < T extends RealType< T > & NativeType< T > > void writeHeightMap( Img< T > surface, String originalInput, int surfaceNumber )
+ {
+ try
+ {
+ new HeightMapArrayWriter( surface, originalInput, surfaceNumber );
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public static < T extends RealType< T > & NativeType< T > > void main( String[] args )
+ {
+ final String imagePath = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\Paper_012022\\Organoid\\Organoid_GT_HM1.tif"; /* The image path goes here !!!! */
+ System.out.println( imagePath );
+ /* JY version for opening files. */
+ final SCIFIOImgPlus< ? > imgPlus = IO.openImgs( imagePath ).get( 0 );
+ final Img< T > heightMap = ( Img< T > ) imgPlus.getImg();
+ writeHeightMap( heightMap, imgPlus.getName(), 2 );
+ System.out.println( "END" );
+
+ }
+
+ @Override
+ public void init() throws IOException
+ {
+ if ( surface != null )
+ {
+ CSVWriter csvWriter =
+ new CSVWriter( originalInput + "_" + "surface" );
+ Cursor< T > cursor = surface.cursor();
+ csvWriter.writeToFile( new String[]{ "x", "y", "z" } );
+ while ( cursor.hasNext() )
+ {
+ cursor.fwd();
+ {
+ if ( cursor.get().getRealFloat() != 0 )
+ {
+ csvWriter.writeToFile(
+ new String[]{ String.valueOf( cursor.getIntPosition( 0 ) ),
+ String.valueOf( cursor.getIntPosition( 1 ) ),
+ String.valueOf( cursor.get().getRealFloat() ) } );
+ }
+ }
+ }
+
+ }
+ }
+
+
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/LocalMaximumsDisplay.java b/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/LocalMaximumsDisplay.java
index fbe4482612410fc3f368d1d544e1943eee287f1e..9982250744a686f9fbae5995bb4d6793a1f4360e 100644
--- a/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/LocalMaximumsDisplay.java
+++ b/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/LocalMaximumsDisplay.java
@@ -100,7 +100,7 @@ public class LocalMaximumsDisplay extends AbstractAnalysis
}
Scatter scatter = new Scatter( points, colors );
- scatter.setWidth( 1 );
+ scatter.setWidth( 2 );
chart = AWTChartComponentFactory.chart( Quality.Advanced, "awt" );
chart.getScene().add( scatter );
}
diff --git a/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/SelectedPixelsArrayWriter.java b/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/SelectedPixelsArrayWriter.java
new file mode 100644
index 0000000000000000000000000000000000000000..25a4ad900c7688dfdf31f5ffbe1d3213612d87f8
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/utils/jzy3D/SelectedPixelsArrayWriter.java
@@ -0,0 +1,68 @@
+package fr.pasteur.ida.zellige.utils.jzy3D;
+
+import fr.pasteur.ida.zellige.element.Pixels;
+import fr.pasteur.ida.zellige.element.Surface;
+import fr.pasteur.ida.zellige.utils.test.CSVWriter;
+import org.jzy3d.analysis.AbstractAnalysis;
+
+import java.io.IOException;
+
+public class SelectedPixelsArrayWriter extends AbstractAnalysis
+{
+
+ private final Pixels[][] selectedPixels;
+ private final String originalInput;
+
+ public SelectedPixelsArrayWriter( Pixels[][] selectedPixels, String originalInput ) throws IOException
+ {
+
+ this.selectedPixels = selectedPixels;
+ this.originalInput = originalInput;
+ init();
+ }
+
+ /**
+ * Displays the local maximums found using jzy3D package.
+ *
+ * @param selectedPixels the {@link Surface} to display
+ */
+ public static void writeSelectedPixels( Pixels[][] selectedPixels, String originalInput )
+ {
+ try
+ {
+ new SelectedPixelsArrayWriter( selectedPixels, originalInput );
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void init() throws IOException
+ {
+ if ( selectedPixels != null )
+ {
+
+ CSVWriter csvWriter =
+ new CSVWriter( originalInput + "_selectedPixels" );
+ csvWriter.writeToFile( new String[]{ "x", "y", "z" } );
+ for ( int x = 0; x < selectedPixels.length; x++ )
+ {
+ for ( int y = 0; y < selectedPixels[ 0 ].length; y++ )
+ {
+ for ( int z = 0; z < selectedPixels[ y ][ x ].size(); z++ )
+ {
+ Pixels pixel = selectedPixels[ y ][ x ];
+ csvWriter.writeToFile(
+ new String[]{ String.valueOf( x ),
+ String.valueOf( y ),
+ String.valueOf( pixel.get( z ).getZ() ) } );
+ }
+ }
+ }
+ }
+ }
+
+
+}
diff --git a/src/main/java/fr/pasteur/ida/zellige/utils/test/DistanceImageWriter.java b/src/main/java/fr/pasteur/ida/zellige/utils/test/DistanceImageWriter.java
index 654aab90c7c57faa896ee30be55ee0326df3306f..d5095dea73cb24daf9a498fc4ed832a8e9c0f3b1 100644
--- a/src/main/java/fr/pasteur/ida/zellige/utils/test/DistanceImageWriter.java
+++ b/src/main/java/fr/pasteur/ida/zellige/utils/test/DistanceImageWriter.java
@@ -45,8 +45,8 @@ public class DistanceImageWriter< T extends RealType< T > & NativeType< T >, R e
public static void main( String[] args ) throws IOException
{
- String pathGT = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\files\\SNR\\snr_010\\multiSurface\\phantoms_snrtest_zmap3_gt.tif";
- String pathHM = "C:\\Users\\ctrebeau\\Downloads\\MinCostZSurface\\CostFunctionVar\\H2_mind6_maxd50_maxdz1.tif";
+ String pathGT = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\files\\Mouche_c01_f0001_p013\\GT\\Ground truth Height map_4_crop.tif";
+ String pathHM = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\Paper_012022\\Mouche\\Mouche_HM_3.tif";
final SCIFIOImgPlus< ? > imgPlusRef = IO.openImgs( pathGT ).get( 0 );
Img< FloatType > GT = ( Img< FloatType > ) imgPlusRef.getImg();
new ImageJ();
@@ -55,8 +55,7 @@ public class DistanceImageWriter< T extends RealType< T > & NativeType< T >, R e
final SCIFIOImgPlus< ? > imgPlus = IO.openImgs( pathHM ).get( 0 );
Img< FloatType > HM = ( Img< FloatType > ) imgPlus.getImg();
ImageJFunctions.show( HM );
- DistanceImageWriter.create( GT, HM, "Min cost Z_distance_surface 1_H1_mind6_maxd50_maxdz2" );
-
+ DistanceImageWriter.create( GT, HM, "Mouche_distance4_crop" );
}
public void run() throws IOException
diff --git a/src/main/java/fr/pasteur/ida/zellige/utils/test/RMSEAndCoverageComputation.java b/src/main/java/fr/pasteur/ida/zellige/utils/test/RMSEAndCoverageComputation.java
index 7bfd105b9306699f84ea325a1cdb0fe8e3154782..49a4e267f7b4e2713795e46dcb06acf00f303b79 100644
--- a/src/main/java/fr/pasteur/ida/zellige/utils/test/RMSEAndCoverageComputation.java
+++ b/src/main/java/fr/pasteur/ida/zellige/utils/test/RMSEAndCoverageComputation.java
@@ -176,8 +176,8 @@ public class RMSEAndCoverageComputation< T extends RealType< T > & NativeType< T
public static void main( String[] args ) throws NotAnHeightMapException, DifferentReferenceTestedSizeException
{
- String pathGT = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\files\\SNR\\snr_010\\multiSurface\\phantoms_snrtest_zmap1_gt.tif";
- String pathHM = "C:\\Users\\ctrebeau\\Downloads\\MinCostZSurface\\CostFunctionInt\\H1_mind5_maxd17_maxdz1.tif";
+ String pathGT = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\files\\Covid Zellige\\C2-MucilairB spike zo1 J4 Sars-3_Ground truth Height map.tif";
+ String pathHM = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\files\\Covid Zellige\\Covid_0.5_0.1_5.tif";
final SCIFIOImgPlus< ? > imgPlusRef = IO.openImgs( pathGT ).get( 0 );
Img< FloatType > GT = ( Img< FloatType > ) imgPlusRef.getImg();
new ImageJ();
diff --git a/src/main/java/fr/pasteur/ida/zellige/utils/test/ZParameters.java b/src/main/java/fr/pasteur/ida/zellige/utils/test/ZParameters.java
index 702c1a3d2b5ad959165a2b8f6d2172c7648862a1..ff670809cf94a1952ea19ab298cf2a77c6883563 100644
--- a/src/main/java/fr/pasteur/ida/zellige/utils/test/ZParameters.java
+++ b/src/main/java/fr/pasteur/ida/zellige/utils/test/ZParameters.java
@@ -20,7 +20,7 @@ public class ZParameters
public ZParameters( String filter, int filterParameter,
- double amplitudeThreshold, double otsuThreshold,
+ int amplitudeThreshold, int otsuThreshold,
int ISConnexity, int ISSize,
double XYSmoothing, double ZSmoothing,
double startingThreshold1, int overlap1, double connexityRate1,
diff --git a/src/main/java/fr/pasteur/ida/zellige/utils/test/ZelligePipelineAnalyse.java b/src/main/java/fr/pasteur/ida/zellige/utils/test/ZelligePipelineAnalyse.java
index 81f98f3b2e4f8a989afd378c3afb629f58e3b345..3bf7ba8f94042f00a9fb919330540380c15fade1 100644
--- a/src/main/java/fr/pasteur/ida/zellige/utils/test/ZelligePipelineAnalyse.java
+++ b/src/main/java/fr/pasteur/ida/zellige/utils/test/ZelligePipelineAnalyse.java
@@ -192,6 +192,7 @@ public class ZelligePipelineAnalyse< T extends RealType< T > & NativeType< T >,
}
else
{
+
return new String[]{
String.valueOf( error.getIndex() ),
String.valueOf( getSelectedPixelNumber() ),
@@ -217,6 +218,7 @@ public class ZelligePipelineAnalyse< T extends RealType< T > & NativeType< T >,
String.valueOf( extraction.getSS_goodSurfaces() ),
String.valueOf( extraction.getSS_smallSurfaces() ),
String.valueOf( extraction.getReferenceSurfaces().size() ) };
+
}
}
return null;
diff --git a/src/main/resources/fr.pasteur.ida.zellige.gui.view/Construction.fxml b/src/main/resources/fr.pasteur.ida.zellige.gui.view/Construction.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..8fbf673e2986726fc4642edcc40b5a66a8479b9a
--- /dev/null
+++ b/src/main/resources/fr.pasteur.ida.zellige.gui.view/Construction.fxml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import fr.pasteur.ida.zellige.gui.*?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.layout.*?>
+<StepPanel xmlns:fx="http://javafx.com/fxml/1" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
+ minWidth="-Infinity" name="Construction" prefHeight="342.0" prefWidth="390.0"
+ xmlns="http://javafx.com/javafx/17" fx:controller="fr.pasteur.ida.zellige.gui.ConstructionController">
+ <children>
+ <GridPane alignment="CENTER" minWidth="-Infinity" prefHeight="307.0" prefWidth="390.0" vgap="15.0">
+ <columnConstraints>
+ <ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="10.0"
+ prefWidth="44.0"/>
+ <ColumnConstraints hgrow="SOMETIMES" maxWidth="469.599951171875" minWidth="10.0"
+ prefWidth="346.40001220703124"/>
+ </columnConstraints>
+ <rowConstraints>
+ <RowConstraints maxHeight="170.9999984741211" minHeight="10.0" prefHeight="128.0" valignment="CENTER"
+ vgrow="SOMETIMES"/>
+ <RowConstraints maxHeight="218.9999755859375" minHeight="10.0" prefHeight="128.0" vgrow="SOMETIMES"/>
+ <RowConstraints maxHeight="110.00003662109378" minHeight="10.0" prefHeight="70.39997253417965"
+ vgrow="SOMETIMES"/>
+ </rowConstraints>
+ <children>
+ <VBox alignment="CENTER" GridPane.columnIndex="1">
+ <children>
+ <GridPane alignment="CENTER" prefHeight="147.0" prefWidth="599.0">
+ <columnConstraints>
+ <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
+ </columnConstraints>
+ <rowConstraints>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ </rowConstraints>
+ <children>
+ <ParameterSliderDouble fx:id="st1" alignment="CENTER" default="0.7" increment="0.1"
+ interval="%INTERVAL3" major="0.2" max="1" min="0" minor="1"
+ name="Starting threshold"/>
+ <ParameterSliderDouble fx:id="c1" alignment="CENTER" default="0.8" increment="0.1"
+ interval="%INTERVAL3" major="0.2" max="1" min="0" minor="1"
+ name="Connexity" GridPane.rowIndex="1"/>
+ <ParameterSliderInteger fx:id="r1" default="5" increment="0.1" interval="%INTERVAL1"
+ major="10" max="50" min="0" minor="4" name="Overlap"
+ GridPane.rowIndex="2"/>
+ </children>
+ </GridPane>
+ </children>
+ </VBox>
+ <VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" GridPane.columnIndex="1"
+ GridPane.rowIndex="1">
+ <children>
+ <GridPane prefHeight="147.0" prefWidth="599.0">
+ <columnConstraints>
+ <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
+ </columnConstraints>
+ <rowConstraints>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ </rowConstraints>
+ <children>
+ <ParameterSliderDouble fx:id="st2" default="0.7" increment="0.1" interval="%INTERVAL3"
+ major="0.2" max="1" min="0" minor="1" name="Starting threshold"/>
+ <ParameterSliderDouble fx:id="c2" default="0.8" increment="0.1" interval="%INTERVAL3"
+ major="0.2" max="1" min="0" minor="1" name="Connexity"
+ GridPane.rowIndex="1"/>
+ <ParameterSliderInteger fx:id="r2" default="5" increment="0.1" interval="%INTERVAL1"
+ major="10" max="50" min="0" minor="1" name="Overlap"
+ GridPane.rowIndex="2"/>
+ </children>
+ </GridPane>
+ </children>
+ </VBox>
+ <VBox alignment="CENTER" prefHeight="36.0" prefWidth="340.0" GridPane.columnIndex="1"
+ GridPane.rowIndex="2">
+ <children>
+ <GridPane>
+ <columnConstraints>
+ <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"/>
+ </columnConstraints>
+ <rowConstraints>
+ <RowConstraints minHeight="10.0" vgrow="SOMETIMES"/>
+ </rowConstraints>
+ <children>
+ <ParameterSliderDouble fx:id="surfaceSize" default="0.7" increment="0.05"
+ interval="%INTERVAL3" major="0.2" max="1" min="0" minor="4"
+ name="Surface min size"/>
+ </children>
+ </GridPane>
+ </children>
+ </VBox>
+ <Label alignment="CENTER" minWidth="-Infinity" prefHeight="14.0" prefWidth="100.0" rotate="-90.0"
+ text="FIRST ROUND"/>
+ <Label alignment="CENTER" minWidth="-Infinity" prefWidth="100.0" rotate="-90.0" text="SECOND ROUND"
+ GridPane.rowIndex="1"/>
+ </children>
+ </GridPane>
+ </children>
+</StepPanel>
diff --git a/src/main/resources/fr.pasteur.ida.zellige.gui.view/Display.fxml b/src/main/resources/fr.pasteur.ida.zellige.gui.view/Display.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..d0c7e15b204dafe46f41c367ce48460ee62971b4
--- /dev/null
+++ b/src/main/resources/fr.pasteur.ida.zellige.gui.view/Display.fxml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<?import java.lang.String?>
+<BorderPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/17">
+ <center>
+ <VBox alignment="CENTER_LEFT" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
+ minWidth="-Infinity" prefHeight="186.0" prefWidth="286.0" spacing="10.0"
+ BorderPane.alignment="CENTER_RIGHT">
+ <children>
+ <CheckBox fx:id="projection" mnemonicParsing="false" text="2D selectedPixels projection"/>
+ <CheckBox fx:id="heightmap" mnemonicParsing="false" text="Height map"/>
+ <CheckBox fx:id="extractedSurface" mnemonicParsing="false" text="3D extracted selectedPixels"/>
+ <CheckBox fx:id="heightMapStack" mnemonicParsing="false" text="Height map stack(± delta)"/>
+ <CheckBox fx:id="heightMapStackMask" mnemonicParsing="false"
+ text="Height map sub-volume mask (± delta)"/>
+ </children>
+ <padding>
+ <Insets left="40.0" top="5.0"/>
+ </padding>
+ <opaqueInsets>
+ <Insets/>
+ </opaqueInsets>
+ </VBox>
+ </center>
+ <top>
+ <Label alignment="TOP_LEFT" styleClass="step-title" text="Output display" BorderPane.alignment="TOP_LEFT">
+ <BorderPane.margin>
+ <Insets/>
+ </BorderPane.margin>
+ <padding>
+ <Insets left="20.0"/>
+ </padding>
+ </Label>
+ </top>
+ <styleClass>
+ <String fx:value="step_border"/>
+ <String fx:value="step-title"/>
+ </styleClass>
+</BorderPane>
diff --git a/src/main/resources/fr.pasteur.ida.zellige.gui.view/Main.fxml b/src/main/resources/fr.pasteur.ida.zellige.gui.view/Main.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..d558902c17346586eb3bb6b4db8c9bebf67594b0
--- /dev/null
+++ b/src/main/resources/fr.pasteur.ida.zellige.gui.view/Main.fxml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.control.ComboBox?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.layout.*?>
+<AnchorPane xmlns:fx="http://javafx.com/fxml/1" prefHeight="764.0" prefWidth="826.0" xmlns="http://javafx.com/javafx/17"
+ fx:controller="fr.pasteur.ida.zellige.gui.MainController">
+ <children>
+ <VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="751.0"
+ prefWidth="816.0" spacing="7.0" AnchorPane.bottomAnchor="3.0" AnchorPane.topAnchor="0.0">
+ <children>
+ <HBox prefHeight="26.0" prefWidth="774.0" spacing="8.0">
+ <children>
+ <Label text="File : "/>
+ <ComboBox fx:id="activeDataset" maxWidth="-Infinity" minWidth="-Infinity" prefHeight="26.0"
+ prefWidth="262.0"/>
+ </children>
+ <padding>
+ <Insets left="10.0"/>
+ </padding>
+ </HBox>
+ <fx:include fx:id="selection" source="Selection.fxml"/>
+ <HBox alignment="CENTER_LEFT" prefHeight="319.0" prefWidth="600.0" spacing="20.0">
+ <children>
+ <fx:include fx:id="construction" source="Construction.fxml"/>
+ <fx:include fx:id="projection" source="Projection.fxml"/>
+ </children>
+ </HBox>
+ <StackPane prefHeight="51.0" prefWidth="747.0">
+ <children>
+ <Button fx:id="runButton" mnemonicParsing="false" text="Run Zellige !"/>
+ </children>
+ </StackPane>
+ </children>
+ <padding>
+ <Insets left="10.0" top="5.0"/>
+ </padding>
+ </VBox>
+ </children>
+ <padding>
+ <Insets left="10.0"/>
+ </padding>
+</AnchorPane>
diff --git a/src/main/resources/fr.pasteur.ida.zellige.gui.view/ParameterSlider.fxml b/src/main/resources/fr.pasteur.ida.zellige.gui.view/ParameterSlider.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..eeda355b0c28bb0f7d4bc59c83bc7a06a12c5b57
--- /dev/null
+++ b/src/main/resources/fr.pasteur.ida.zellige.gui.view/ParameterSlider.fxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--No controller specified and need of fx:root-->
+
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.control.Slider?>
+<?import javafx.scene.control.TextField?>
+<?import javafx.scene.layout.*?>
+<fx:root xmlns:fx="http://javafx.com/fxml/1" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
+ minWidth="-Infinity" prefHeight="41.0" prefWidth="338.0" styleClass="parameter" stylesheets="@theme2.css"
+ type="GridPane" xmlns="http://javafx.com/javafx/17">
+ <columnConstraints>
+ <ColumnConstraints halignment="CENTER" hgrow="ALWAYS" maxWidth="130.1999755859375" minWidth="10.0"
+ prefWidth="56.79996337890625"/>
+ <ColumnConstraints hgrow="ALWAYS" maxWidth="415.5999755859375" minWidth="10.0" prefWidth="251.20003662109374"/>
+ <ColumnConstraints halignment="CENTER" hgrow="ALWAYS" maxWidth="242.79998779296875" minWidth="10.0"
+ prefWidth="36.20002441406251"/>
+ </columnConstraints>
+ <rowConstraints>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ </rowConstraints>
+
+ <Label fx:id="label" alignment="CENTER_RIGHT" prefHeight="35.0" prefWidth="71.0" text="Parameter Name"
+ textAlignment="RIGHT" wrapText="true" GridPane.halignment="RIGHT" GridPane.valignment="CENTER"/>
+ <Slider fx:id="slider" stylesheets="@theme2.css" GridPane.columnIndex="1" GridPane.valignment="BOTTOM">
+ <padding>
+ <Insets left="5.0" right="5.0"/>
+ </padding>
+ </Slider>
+ <TextField fx:id="textField" alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
+ minWidth="-Infinity" prefHeight="26.0" prefWidth="30.0" GridPane.columnIndex="2"
+ GridPane.halignment="CENTER" GridPane.valignment="CENTER"/>
+
+</fx:root>
diff --git a/src/main/resources/fr.pasteur.ida.zellige.gui.view/Projection.fxml b/src/main/resources/fr.pasteur.ida.zellige.gui.view/Projection.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..2c8d1d4cd257a0d397c315ad805dc46a792bc4b5
--- /dev/null
+++ b/src/main/resources/fr.pasteur.ida.zellige.gui.view/Projection.fxml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import fr.pasteur.ida.zellige.gui.StepPanel?>
+<?import javafx.geometry.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<StepPanel xmlns:fx="http://javafx.com/fxml/1" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
+ minWidth="-Infinity" name="Projection" prefHeight="342.0" prefWidth="390.0"
+ xmlns="http://javafx.com/javafx/17" fx:controller="fr.pasteur.ida.zellige.gui.ProjectionController">
+ <children>
+ <VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" prefHeight="312.0"
+ prefWidth="389.0">
+ <children>
+ <StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" prefHeight="313.0"
+ prefWidth="362.0">
+ <children>
+ <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
+ minWidth="-Infinity" prefHeight="316.0" prefWidth="362.0">
+ <opaqueInsets>
+ <Insets/>
+ </opaqueInsets>
+ <center>
+ <HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
+ minWidth="-Infinity" prefHeight="61.0" prefWidth="342.0"
+ BorderPane.alignment="CENTER">
+ <children>
+ <VBox alignment="CENTER" prefHeight="108.0" prefWidth="220.0" spacing="5.0">
+ <children>
+ <Label contentDisplay="CENTER" text="Method"/>
+ <ComboBox fx:id="methodComboBox" prefWidth="150.0"/>
+ </children>
+ </VBox>
+ <VBox alignment="CENTER" prefHeight="108.0" prefWidth="216.0" spacing="5.0">
+ <children>
+ <Label text="Delta Z"/>
+ <Spinner fx:id="deltaSpinner" prefHeight="27.0" prefWidth="119.0"/>
+ </children>
+ </VBox>
+ </children>
+ </HBox>
+ </center>
+ <bottom>
+ <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
+ minWidth="-Infinity" prefHeight="222.0" prefWidth="342.0"
+ BorderPane.alignment="CENTER">
+ <top>
+ <Label alignment="TOP_LEFT" styleClass="step-title" text="Output display"
+ BorderPane.alignment="TOP_LEFT">
+ <BorderPane.margin>
+ <Insets/>
+ </BorderPane.margin>
+ <padding>
+ <Insets left="20.0"/>
+ </padding>
+ </Label>
+ </top>
+ <bottom>
+ <VBox alignment="CENTER_LEFT" maxHeight="-Infinity" maxWidth="-Infinity"
+ minHeight="-Infinity" minWidth="-Infinity" prefHeight="201.0"
+ prefWidth="286.0" spacing="10.0" BorderPane.alignment="CENTER">
+ <children>
+ <CheckBox fx:id="projection" mnemonicParsing="false" selected="true"
+ text="2D selectedPixels projection"/>
+ <CheckBox fx:id="rawHeightMap" mnemonicParsing="false" selected="true"
+ text="Raw height map"/>
+ <CheckBox fx:id="extractedHeightMap" mnemonicParsing="false"
+ text="Extracted height map"/>
+ <CheckBox fx:id="segmentedSurface" mnemonicParsing="false"
+ text="3D extracted selectedPixels"/>
+ <CheckBox fx:id="reduced3DSpace" mnemonicParsing="false"
+ text="Height map stack(± delta)"/>
+ <HBox prefHeight="26.0" prefWidth="194.0" spacing="30.0">
+ <children>
+ <CheckBox fx:id="segmentedSurfaceMask" mnemonicParsing="false"
+ text="Surface mask"/>
+ <Spinner fx:id="delta2" prefHeight="26.0" prefWidth="65.0"/>
+ </children>
+ </HBox>
+ </children>
+ <padding>
+ <Insets left="40.0"/>
+ </padding>
+ <opaqueInsets>
+ <Insets/>
+ </opaqueInsets>
+ </VBox>
+ </bottom>
+ </BorderPane>
+ </bottom>
+ </BorderPane>
+ </children>
+ </StackPane>
+ </children>
+ </VBox>
+ </children>
+</StepPanel>
diff --git a/src/main/resources/fr.pasteur.ida.zellige.gui.view/Selection.fxml b/src/main/resources/fr.pasteur.ida.zellige.gui.view/Selection.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..efcc3e81cdf443fb61cacc919629175e6405bb30
--- /dev/null
+++ b/src/main/resources/fr.pasteur.ida.zellige.gui.view/Selection.fxml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import fr.pasteur.ida.zellige.gui.*?>
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.layout.*?>
+<StepPanel xmlns:fx="http://javafx.com/fxml/1" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
+ minWidth="-Infinity" name="Selection" prefHeight="327.0" prefWidth="800.0"
+ xmlns="http://javafx.com/javafx/17" fx:controller="fr.pasteur.ida.zellige.gui.SelectionController">
+ <children>
+ <GridPane prefHeight="296.0" prefWidth="766.0">
+ <columnConstraints>
+ <ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="10.0" prefWidth="390.0"/>
+ <ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="10.0" prefWidth="390.0"/>
+ </columnConstraints>
+ <rowConstraints>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ </rowConstraints>
+ <children>
+ <Pane maxHeight="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="224.0"
+ prefWidth="390.0" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
+ <children>
+ <GridPane alignment="CENTER" layoutX="1.0" prefHeight="223.0" prefWidth="397.0" vgap="15.0">
+ <columnConstraints>
+ <ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="0.0"
+ prefWidth="44.0"/>
+ <ColumnConstraints hgrow="SOMETIMES" maxWidth="542.9999614715576" minWidth="10.0"
+ prefWidth="353.5999816894531"/>
+ </columnConstraints>
+ <rowConstraints>
+ <RowConstraints maxHeight="203.59998168945313" minHeight="10.0"
+ prefHeight="150.40000610351564" vgrow="SOMETIMES"/>
+ <RowConstraints maxHeight="187.99998779296874" minHeight="10.0"
+ prefHeight="114.39999389648438" vgrow="SOMETIMES"/>
+ </rowConstraints>
+ <children>
+ <VBox alignment="CENTER" prefHeight="148.0" prefWidth="352.0" GridPane.columnIndex="1"
+ GridPane.halignment="CENTER" GridPane.valignment="CENTER">
+ <children>
+ <GridPane prefHeight="165.0" prefWidth="370.0">
+ <columnConstraints>
+ <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
+ </columnConstraints>
+ <rowConstraints>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ </rowConstraints>
+ <children>
+ <ParameterSliderInteger fx:id="amplitude" default="10" increment="1"
+ interval="%INTERVAL1" major="10" max="50"
+ min="0" minor="9" name="Amplitude"/>
+ <ParameterSliderInteger fx:id="otsu" default="10" increment="1"
+ interval="%INTERVAL1" major="10" max="50"
+ min="0" minor="1" name="Otsu"
+ GridPane.rowIndex="1"/>
+ <ParameterSliderInteger fx:id="island" default="5" increment="1"
+ interval="%INTERVAL1" major="10" max="50"
+ min="0" minor="1" name="Island Search"
+ GridPane.rowIndex="2"/>
+ </children>
+ </GridPane>
+ </children>
+ </VBox>
+ <VBox alignment="CENTER" prefHeight="69.0" prefWidth="366.0" spacing="10.0"
+ GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1"
+ GridPane.valignment="CENTER">
+ <children>
+ <GridPane alignment="CENTER" prefHeight="66.0" prefWidth="352.0">
+ <columnConstraints>
+ <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
+ </columnConstraints>
+ <rowConstraints>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
+ </rowConstraints>
+ <children>
+ <ParameterSliderInteger default="1" increment="1" interval="%INTERVAL2"
+ major="5" max="10" min="0" minor="4"
+ name="XY Blur" prefHeight="30.0"
+ fx:id="xyBlur"/>
+ <ParameterSliderInteger fx:id="zBlur" default="1" increment="1"
+ interval="%INTERVAL2" major="5" max="10" min="0"
+ minor="4" name="Z Blur " GridPane.rowIndex="1"/>
+ </children>
+ </GridPane>
+ </children>
+ </VBox>
+ <Label alignment="TOP_CENTER" minWidth="-Infinity" prefHeight="16.0" prefWidth="121.0"
+ rotate="-90.0" text="CLASSIFICATION" GridPane.halignment="CENTER"
+ GridPane.valignment="CENTER"/>
+ <Label alignment="TOP_CENTER" minWidth="-Infinity" prefHeight="16.0" prefWidth="121.0"
+ rotate="-90.0" text="SMOOTHING" GridPane.halignment="CENTER"
+ GridPane.rowIndex="1" GridPane.valignment="CENTER"/>
+ </children>
+ </GridPane>
+ </children>
+ <GridPane.margin>
+ <Insets top="10.0"/>
+ </GridPane.margin>
+ </Pane>
+ <VBox prefHeight="200.0" prefWidth="100.0" GridPane.columnIndex="1">
+ <children>
+ <FlowPane fx:id="stack" prefHeight="352.0" prefWidth="346.0"/>
+ <ZSlicesSlider fx:id="zSlices" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity"
+ minHeight="-Infinity" minWidth="-Infinity" prefHeight="42.0" prefWidth="390.0"/>
+ </children>
+ </VBox>
+ </children>
+ </GridPane>
+ </children>
+</StepPanel>
diff --git a/src/main/resources/fr.pasteur.ida.zellige.gui.view/StepPanel.fxml b/src/main/resources/fr.pasteur.ida.zellige.gui.view/StepPanel.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..a4e1cd37b69d2763d8f38b243a834cb430f9e3f3
--- /dev/null
+++ b/src/main/resources/fr.pasteur.ida.zellige.gui.view/StepPanel.fxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.control.Separator?>
+<?import javafx.scene.layout.VBox?>
+<?import java.lang.String?>
+<fx:root xmlns:fx="http://javafx.com/fxml/1" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
+ minWidth="-Infinity" prefHeight="303.0" prefWidth="600.0" stylesheets="@theme2.css" type="VBox"
+ xmlns="http://javafx.com/javafx/17">
+ <children>
+ <Label fx:id="Label2" alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="7.0" prefWidth="131.0"
+ stylesheets="@theme2.css">
+ <styleClass>
+ <String fx:value="step"/>
+ <String fx:value="label"/>
+ </styleClass>
+ </Label>
+ <Separator prefWidth="200.0">
+ <VBox.margin>
+ <Insets left="5.0" right="10.0"/>
+ </VBox.margin>
+ </Separator>
+ </children>
+ <styleClass>
+ <String fx:value="step"/>
+ <String fx:value="vbox"/>
+ </styleClass>
+</fx:root>
diff --git a/src/main/resources/fr.pasteur.ida.zellige.gui.view/ZSlicesSlider.fxml b/src/main/resources/fr.pasteur.ida.zellige.gui.view/ZSlicesSlider.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..bd3b7250821220405a112282eadf0b4318714661
--- /dev/null
+++ b/src/main/resources/fr.pasteur.ida.zellige.gui.view/ZSlicesSlider.fxml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+<?import javafx.scene.control.Slider?>
+<?import javafx.scene.layout.FlowPane?>
+<fx:root xmlns:fx="http://javafx.com/fxml/1" alignment="CENTER" columnHalignment="CENTER" prefHeight="47.0"
+ prefWidth="400.0" stylesheets="@theme2.css" type="FlowPane" xmlns="http://javafx.com/javafx/17">
+ <children>
+ <Slider fx:id="slider" prefHeight="14.0" prefWidth="400.0" visible="false"/>
+ </children>
+</fx:root>
diff --git a/src/main/resources/fr.pasteur.ida.zellige.gui.view/theme1.css b/src/main/resources/fr.pasteur.ida.zellige.gui.view/theme1.css
new file mode 100644
index 0000000000000000000000000000000000000000..e84320af31f37de9294286b1fed29cff4305fdd8
--- /dev/null
+++ b/src/main/resources/fr.pasteur.ida.zellige.gui.view/theme1.css
@@ -0,0 +1,40 @@
+.background {
+ -fx-background-color: #733785;
+}
+
+.step-header {
+ -fx-background-color: #733785;
+}
+
+.step-border {
+ -fx-background-radius: 15 0 0 0;
+ -fx-border-radius: 15 0 0 0;
+ -fx-border-color: #B0B8BA;
+}
+
+.step-title {
+ -fx-font: bold italic 14px System;
+}
+
+
+.parameter.line {
+ /*-fx-background-color: #15BAE7;*/
+ /*blue
+ */
+ -fx-font: 10px Tahoma;
+ /*-fx-vgap : 30px;*/
+ /*-fx-hgap : 30px;*/
+}
+
+.parameter.line.textfield {
+ -fx-alignement: center;
+}
+
+
+.view {
+ -fx-alignement: center;
+}
+
+.spinner {
+ -fx-font: 10px System;
+}
\ No newline at end of file
diff --git a/src/main/resources/fr.pasteur.ida.zellige.gui.view/theme2.css b/src/main/resources/fr.pasteur.ida.zellige.gui.view/theme2.css
new file mode 100644
index 0000000000000000000000000000000000000000..b768c11eddf671d70cc3e708dc910edc73f934d7
--- /dev/null
+++ b/src/main/resources/fr.pasteur.ida.zellige.gui.view/theme2.css
@@ -0,0 +1,152 @@
+
+.root {
+ -fx-base: #ececec;
+ -fx-color: -fx-base;
+ -fx-focus-color: #039E22;
+ -fx-inner-border: linear-gradient(to bottom,
+ ladder(
+ -fx-color,
+ derive(-fx-color, 30%) 0%,
+ derive(-fx-color, 20%) 40%,
+ derive(-fx-color, 25%) 60%,
+ derive(-fx-color, 55%) 80%,
+ derive(-fx-color, 55%) 90%,
+ derive(-fx-color, 75%) 100%
+ ),
+ ladder(
+ -fx-color,
+ derive(-fx-color, 20%) 0%,
+ derive(-fx-color, 10%) 20%,
+ derive(-fx-color, 5%) 40%,
+ derive(-fx-color, -2%) 60%,
+ derive(-fx-color, -5%) 100%
+ ));
+ -fx-body-color: linear-gradient(to bottom,
+ ladder(
+ -fx-color,
+ derive(-fx-color, 8%) 75%,
+ derive(-fx-color, 10%) 80%
+ ),
+ derive(-fx-color, -8%));
+
+}
+
+parameter-slider-integer.label {
+ -fx-text-fill: #252526;
+ -fx-font-size: 0.9em;
+ -fx-font-weight: normal;
+}
+
+/*******************************************************************************
+ * *
+ * Label *
+ * *
+ ******************************************************************************/
+
+.label {
+ -fx-text-fill: #252526;
+ -fx-font-size: 0.9em;
+ -fx-font-weight: normal;
+}
+
+
+/*******************************************************************************
+ * *
+ * Slider *
+ * *
+ ******************************************************************************/
+.slider .thumb:hover {
+ -fx-color: -fx-hover-base;
+}
+
+.slider .thumb:pressed {
+ -fx-color: -fx-pressed-base;
+}
+
+
+.slider .thumb {
+ -fx-background-color: linear-gradient(to bottom, derive(-fx-text-box-border, -20%), derive(-fx-text-box-border, -30%)),
+ -fx-inner-border,
+ -fx-body-color;
+ -fx-background-insets: 0, 1, 2;
+ -fx-background-radius: 1.0em; /* makes sure this remains circular */
+ -fx-padding: 0.583333em; /* 7 */
+ -fx-effect: dropshadow(two-pass-box, rgba(0, 0, 0, 0.1), 5, 0.0, 0, 2);
+}
+
+.slider:focused .thumb {
+ -fx-background-color: #515769, -fx-inner-border, -fx-body-color, #51576936, -fx-body-color;
+ -fx-background-insets: -0.2, 1, 2, -1.4, 2.6;
+ -fx-background-radius: 3, 2, 1, 4, 1;
+}
+
+.slider:focused .thumb {
+ -fx-background-radius: 1.0em; /* makes sure this remains circular */
+}
+
+.slider .track {
+ -fx-background-color: #484c54A3,
+ linear-gradient(to bottom, derive(-fx-text-box-border, -10%), -fx-text-box-border),
+ linear-gradient(to bottom,
+ derive(-fx-control-inner-background, -9%),
+ derive(-fx-control-inner-background, 0%),
+ derive(-fx-control-inner-background, -5%),
+ derive(-fx-control-inner-background, -12%)
+ );
+ -fx-background-insets: 0 0 -1 0, 0, 1;
+ -fx-background-radius: 0.25em, 0.25em, 0.166667em; /* 3 3 2 */
+ -fx-padding: 0.25em; /* 3 */
+}
+
+.axis {
+ AXIS_COLOR: derive(#0f1012, -20%);
+ -fx-tick-label-font-size: 0.7em; /* 10px */
+ -fx-tick-label-fill: #252526;
+}
+
+/*******************************************************************************
+ * *
+ * TextField *
+ * *
+ ******************************************************************************/
+.text-field {
+ -fx-text-fill: #252526;
+ -fx-font-size: 0.8em;
+ -fx-font-weight: normal;
+}
+
+.text-input:error {
+ -fx-text-fill: black;
+ -fx-border-insets: 0;
+ -fx-border-width: 2px;
+ -fx-border-color: red;
+ -fx-border-style: hidden hidden solid hidden;
+ -fx-background-color: derive(red, 99%);
+}
+
+.text-input:focused {
+ -fx-highlight-fill: -fx-accent;
+ -fx-highlight-text-fill: white;
+ -fx-background-color: #515769,
+ -fx-control-inner-background,
+ #51576936,
+ linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background);
+ -fx-background-insets: -0.2, 1, -1.4, 3;
+ -fx-background-radius: 3, 2, 4, 0;
+ -fx-prompt-text-fill: transparent;
+}
+
+
+.step.label {
+ -fx-font-family: Garamond;
+ /*-fx-font-style: oblique;*/
+ -fx-text-fill: #515769;
+ -fx-font-size: 1.2em;
+ -fx-font-weight: bold;
+ -fx-font-smoothing-type: lcd;
+}
+
+.step.vbox {
+ -fx-border-radius: 0.5em 2em 0.5em 0.5em;
+ -fx-border-color: lightgrey;
+}
\ No newline at end of file
diff --git a/src/main/resources/gui.properties b/src/main/resources/gui.properties
new file mode 100644
index 0000000000000000000000000000000000000000..d2b3367b8a90a1ae3c10a4c16844a623b5878333
--- /dev/null
+++ b/src/main/resources/gui.properties
@@ -0,0 +1,7 @@
+#[0-50]
+INTERVAL1=[0-9]|[1-4][0-9]|[5][0]
+#[0-10]
+INTERVAL2=[0-9]|[1][0]
+#[0.0 - 1.0]
+INTERVAL3=0?\\.[0-9]|[1]\\.[0]?|[0]|[1]
+#
\ No newline at end of file
diff --git a/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweep.java b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweep.java
index 87c077caf72a65615a059861de3902385350916a..71c61933cf38db75ca049e8ba97bfee8d1ab9b5a 100644
--- a/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweep.java
+++ b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweep.java
@@ -1,23 +1,29 @@
package fr.pasteur.ida.zellige.behavior;
-import fr.pasteur.ida.zellige.utils.jzy3D.HM_GT_DifferenceDisplay;
import fr.pasteur.ida.zellige.utils.test.*;
-import ij.ImageJ;
-import net.imglib2.RandomAccessibleInterval;
import net.imglib2.img.Img;
-import net.imglib2.img.display.imagej.ImageJFunctions;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
+import net.imglib2.type.numeric.integer.UnsignedShortType;
+import org.junit.Rule;
+import org.junit.internal.runners.statements.FailOnTimeout;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.rules.Timeout;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.concurrent.TimeoutException;
+
+import static fr.pasteur.ida.zellige.behavior.Utils.buildStringLine;
//@Ignore
public class ParameterSweep< T extends RealType< T > & NativeType< T >, R extends RealType< R > & NativeType< R > >
@@ -28,17 +34,57 @@ public class ParameterSweep< T extends RealType< T > & NativeType< T >, R extend
static ArrayList< Img > ref;
static Img tested;
private final int delta = 0;
- private double surfaceMinSizeFactor;
+ private double surfaceMinSizeFactor = 0.05;
+ private static final int MIN_TIMEOUT = 200;
+ public String[] errorLine =
+ new String[]{
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN",
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN" };
+
+ @AfterAll
+ static void closeBw() throws IOException
+ {
+ writer.close();
+ }
+
+ @Rule
+ public Timeout timeout = new Timeout( MIN_TIMEOUT )
+ {
+ public Statement apply( Statement base, Description description )
+ {
+ return new FailOnTimeout( base, MIN_TIMEOUT )
+ {
+ @Override
+ public void evaluate() throws Throwable
+ {
+ try
+ {
+ super.evaluate();
+ throw new TimeoutException();
+ }
+ catch ( Exception e )
+ {
+ }
+ }
+ };
+ }
+
+
+ };
// @Ignore
@BeforeAll
static void init() throws IOException
{
- String imagePath = "doc/Cochlée2.tif";
+ String imagePath = "doc/Mouche.tif";
final String[] refImagePath = new String[]{
- "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\files\\Atlas\\Ground truth Height map.tif",
+ "src/test/resources/Mouche/Ground truth Height map_1.tif",
+ "src/test/resources/Mouche/Ground truth Height map_2.tif",
+ "src/test/resources/Mouche/Ground truth Height map_3.tif",
+ "src/test/resources/Mouche/Ground truth Height map_4.tif"
+
};
- ParameterSweepFiles files = new ParameterSweepFiles( refImagePath, imagePath, "Atlas_selectionTime4" );
+ ParameterSweepFiles files = new ParameterSweepFiles( refImagePath, imagePath, "Timeout" );
ref = files.getRefs();
tested = files.getTested();
writer = new CSVWriter( files.getPath() );
@@ -53,98 +99,115 @@ public class ParameterSweep< T extends RealType< T > & NativeType< T >, R extend
RMSEAndCoverageComputation.setSubtract( - 1 );
}
- @AfterAll
- static void closeBw() throws IOException
+ // The test times out and is skipped
+ public void givesTimeout() throws InterruptedException
{
- writer.close();
+ Thread.sleep( 1000 );
}
// @Ignore
@ParameterizedTest
- @CsvFileSource( files = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\files\\Atlas\\Atlas_ParametersSweepSelectionPT.csv", numLinesToSkip = 0, delimiterString = ";" )
+ @CsvFileSource( files = "src/test/resources/Mouche/Mouche_ParameterSweep.csv", numLinesToSkip = 1, delimiterString = ";" )
void parameterSweep( String testedParameter, String testedParameterValue, String filter, int filterParameter,
- double amplitudeThreshold, double otsuThreshold,
+ int amplitudeThreshold, int otsuThreshold,
int ISConnexity, int ISSize,
double XYSmoothing, double ZSmoothing,
double startingThreshold1, int overlap1, double connexityRate1,
double startingThreshold2, int overlap2, double connexityRate2,
String optimalSet ) throws Exception
{
- LOGGER.info( "Parameter sweep " );
- LOGGER.debug( " The parameter sweep is done for a total of {} ground truths", ref.size() );
- ZParameters parameters = new ZParameters( filter, filterParameter,
- amplitudeThreshold, otsuThreshold, ISConnexity, ISSize, XYSmoothing, ZSmoothing,
- startingThreshold1, overlap1, connexityRate1,
- startingThreshold2, overlap2, connexityRate2, surfaceMinSizeFactor, delta );
-
- parameters.print();
- ZelligePipelineAnalyse< T, R > analyse = new ZelligePipelineAnalyse();
- analyse.run( parameters, tested, ref );
- for ( RMSEAndCoverageComputation r : analyse.getErrorList() )
+ try
{
- String[] line = buildStringLine( testedParameter, testedParameterValue, analyse.getErrorAnalysis( r ), optimalSet );
- writer.writeToFile( line );
- }
- }
+ ZParameters parameters = new ZParameters( filter, filterParameter,
+ amplitudeThreshold, otsuThreshold, ISConnexity, ISSize, XYSmoothing, ZSmoothing,
+ startingThreshold1, overlap1, connexityRate1,
+ startingThreshold2, overlap2, connexityRate2, surfaceMinSizeFactor, delta );
- public String[] buildStringLine( String testedParameter1, String testedParameterValue1,
- String[] error, String optimalSet )
- {
- String[] line = new String[ 3 + error.length ];
- line[ 0 ] = testedParameter1;
- line[ 1 ] = testedParameterValue1;
- int index = 2;
- for ( String s : error )
+ parameters.print();
+ ZelligePipelineAnalyse< T, R > analyse = new ZelligePipelineAnalyse<>();
+ analyse.run( parameters, tested, ref );
+ for ( RMSEAndCoverageComputation< T, UnsignedShortType > r : analyse.getErrorList() )
+ {
+ String[] line = buildStringLine( testedParameter, testedParameterValue, analyse.getErrorAnalysis( r ), optimalSet );
+ writer.writeToFile( line );
+ }
+ }
+ catch ( Exception exception )
{
- line[ index ] = s;
- index++;
+ for ( int i = 0; i < ref.size(); i++ )
+ {
+ writer.writeToFile( errorLine );
+ }
}
- line[ line.length - 1 ] = optimalSet;
- return line;
}
- // @Ignore
- @ParameterizedTest
- @CsvSource( value = "Amplitude;0.9;GaussianBlur;2;0.9;0.1;4;10;2;3;0.7;10;0.7;0.1;10;0.8;YES",
+ // @Disabled( "Ignored" )
+ @Test
+ @CsvSource( value = "Amplitude;0;GaussianBlur;2;0;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO",
delimiterString = ";" )
void parameterSweepSingle( String testedParameter, String testedParameterValue, String filter, int filterParameter,
- double amplitudeThreshold, double otsuThreshold,
+ int amplitudeThreshold, int otsuThreshold,
int ISConnexity, int ISSize,
double XYSmoothing, double ZSmoothing,
double startingThreshold1, int overlap1, double connexityRate1,
double startingThreshold2, int overlap2, double connexityRate2,
String optimalSet ) throws Exception
{
- ImageJ ij = new ImageJ();
- LOGGER.info( "Parameter sweep " );
- LOGGER.debug( " The parameter sweep is done for a total of {} ground truths", ref.size() );
- ZParameters parameters = new ZParameters( filter, filterParameter,
- amplitudeThreshold, otsuThreshold, ISConnexity, ISSize, XYSmoothing, ZSmoothing,
- startingThreshold1, overlap1, connexityRate1,
- startingThreshold2, overlap2, connexityRate2, surfaceMinSizeFactor, delta );
-
- parameters.print();
- ZelligePipelineAnalyse< T, R > analyse = new ZelligePipelineAnalyse();
- analyse.run( parameters, tested, ref );
- for ( RMSEAndCoverageComputation r : analyse.getErrorList() )
- {
- String[] line = buildStringLine( testedParameter, testedParameterValue, analyse.getErrorAnalysis( r ), optimalSet );
- writer.writeToFile( line );
- }
- int index = 0;
- for ( RandomAccessibleInterval rai : ref )
+ try
{
- HM_GT_DifferenceDisplay.displayDiff( ref.get( index ), analyse.getErrorList().get( index ).getProjection() );
- ImageJFunctions.show( ref.get( index ), "GT" );
- ImageJFunctions.show( analyse.getErrorList().get( index ).getProjection(), "HM" );
- index++;
+ ZParameters parameters = new ZParameters( filter, filterParameter,
+ amplitudeThreshold, otsuThreshold, ISConnexity, ISSize, XYSmoothing, ZSmoothing,
+ startingThreshold1, overlap1, connexityRate1,
+ startingThreshold2, overlap2, connexityRate2, surfaceMinSizeFactor, delta );
+
+ parameters.print();
+ ZelligePipelineAnalyse< T, R > analyse = new ZelligePipelineAnalyse<>();
+ analyse.run( parameters, tested, ref );
+ for ( RMSEAndCoverageComputation< T, UnsignedShortType > r : analyse.getErrorList() )
+ {
+ String[] line = buildStringLine( testedParameter, testedParameterValue, analyse.getErrorAnalysis( r ), optimalSet );
+ writer.writeToFile( line );
+ }
}
- while ( true )
+ catch ( InterruptedException exception )
{
-
+ for ( int i = 0; i < ref.size(); i++ )
+ {
+ writer.writeToFile( errorLine );
+ }
}
+
+// ImageJ ij = new ImageJ();
+// LOGGER.info( "Parameter sweep " );
+// LOGGER.debug( " The parameter sweep is done for a total of {} ground truths", ref.size() );
+// ZParameters parameters = new ZParameters( filter, filterParameter,
+// amplitudeThreshold, otsuThreshold, ISConnexity, ISSize, XYSmoothing, ZSmoothing,
+// startingThreshold1, overlap1, connexityRate1,
+// startingThreshold2, overlap2, connexityRate2, surfaceMinSizeFactor, delta );
+//
+// parameters.print();
+// ZelligePipelineAnalyse< T, R > analyse = new ZelligePipelineAnalyse();
+// analyse.run( parameters, tested, ref );
+// for ( RMSEAndCoverageComputation r : analyse.getErrorList() )
+// {
+// String[] line = buildStringLine( testedParameter, testedParameterValue, analyse.getErrorAnalysis( r ), optimalSet );
+// writer.writeToFile( line );
+// }
+
+ int index = 0;
+// for ( RandomAccessibleInterval rai : ref )
+// {
+// HM_GT_DifferenceDisplay.displayDiff( ref.get( index ), analyse.getErrorList().get( index ).getProjection() );
+// ImageJFunctions.show( ref.get( index ), "GT" );
+// ImageJFunctions.show( analyse.getErrorList().get( index ).getProjection(), "HM" );
+// index++;
+// }
+// while ( true )
+// {
+//
+// }
}
}
diff --git a/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepCochlee2.java b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepCochlee2.java
new file mode 100644
index 0000000000000000000000000000000000000000..b8f285c4be28a3a3a49cb1f37d7cc3e798d7ef8a
--- /dev/null
+++ b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepCochlee2.java
@@ -0,0 +1,112 @@
+package fr.pasteur.ida.zellige.behavior;
+
+import fr.pasteur.ida.zellige.utils.test.*;
+import net.imglib2.img.Img;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import net.imglib2.type.numeric.integer.UnsignedShortType;
+import org.junit.Rule;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvFileSource;
+import org.junit.rules.Timeout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import static fr.pasteur.ida.zellige.behavior.Utils.buildStringLine;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+
+public class ParameterSweepCochlee2< T extends RealType< T > & NativeType< T >, R extends RealType< R > & NativeType< R > >
+{
+
+ private final static Logger LOGGER = LoggerFactory.getLogger( ParameterSweepCochlee2.class );
+ private static final String[] header = { "Parameter1", "Parameter1Value",
+ "GroundTruthNb", "SelectedPixelNb", "RMSE", "Coverage", "SelectionPT",
+ "AmplitudePT", "OtsuPT", "IslandSearchPT",
+ "ConstructionPT", "FS_OS_PT", "FS_surface_PT", "SS_OS_PT", "SS_surface_PT", "Total_PT",
+ "FS_OS_count", "FS_startingOS_count", "SS_OS_count", "SS_startingOS_count",
+ "FS_good", "FS_small", "FS_finalised",
+ "SS_good", "SS_small", "SS_finalised", "OptimizedSet" };
+ /* Specific Parameters */
+ private static final String sample = "Cochlée2";
+ private static final String imagePath = "doc/Cochlée2.tif";
+ private static final String[] refImagePath = new String[]{
+ "src/test/resources/Cochlée2/Ground truth Height map.tif"
+ };
+ static ArrayList< Img > ref;
+ static Img tested;
+ private static CSVWriter writer;
+ private final int delta = 0;
+ private final String parameterSweepCSVFile = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\Paper_012022\\ProcessingTime\\Cochlée2_PT.csv";
+ private final double surfaceMinSizeFactor = 0.8;
+ public String[] errorLine =
+ new String[]{
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN",
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN" };
+
+
+ @Rule
+ public Timeout globalTimeout = new Timeout( 10000, SECONDS );
+
+ @BeforeAll
+ static void init() throws IOException
+ {
+ ParameterSweepFiles files = new ParameterSweepFiles( refImagePath, imagePath, "PT_" + sample );
+ ref = files.getRefs();
+ tested = files.getTested();
+ writer = new CSVWriter( files.getPath() );
+ writer.writeToFile( header );
+ RMSEAndCoverageComputation.setSubtract( - 1 );
+ LOGGER.info( "Parameter sweep for the {} sample", sample );
+ LOGGER.debug( " The parameter sweep is done for a total of {} ground truths", ref.size() );
+ }
+
+ @AfterAll
+ static void closeBw() throws IOException
+ {
+ writer.close();
+ }
+
+
+ @ParameterizedTest
+ @CsvFileSource( files = parameterSweepCSVFile, numLinesToSkip = 1, delimiterString = ";" )
+ void parameterSweep( String testedParameter, String testedParameterValue, String filter, int filterParameter,
+ int amplitudeThreshold, int otsuThreshold,
+ int ISConnexity, int ISSize,
+ double XYSmoothing, double ZSmoothing,
+ double startingThreshold1, int overlap1, double connexityRate1,
+ double startingThreshold2, int overlap2, double connexityRate2,
+ String optimalSet ) throws Exception
+ {
+ try
+ {
+ ZParameters parameters = new ZParameters( filter, filterParameter,
+ amplitudeThreshold, otsuThreshold, ISConnexity, ISSize, XYSmoothing, ZSmoothing,
+ startingThreshold1, overlap1, connexityRate1,
+ startingThreshold2, overlap2, connexityRate2, surfaceMinSizeFactor, delta );
+
+ parameters.print();
+ ZelligePipelineAnalyse< T, R > analyse = new ZelligePipelineAnalyse<>();
+ analyse.run( parameters, tested, ref );
+ for ( RMSEAndCoverageComputation< T, UnsignedShortType > r : analyse.getErrorList() )
+ {
+ String[] line = buildStringLine( testedParameter, testedParameterValue, analyse.getErrorAnalysis( r ), optimalSet );
+ writer.writeToFile( line );
+ }
+ }
+ catch ( OutOfMemoryError error )
+ {
+ for ( int i = 0; i < ref.size(); i++ )
+ {
+ writer.writeToFile( errorLine );
+ }
+ }
+ }
+
+
+}
diff --git a/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepCulture.java b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepCulture.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc6c8b1189a3b834e955232da8b02d053bb1e1a9
--- /dev/null
+++ b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepCulture.java
@@ -0,0 +1,105 @@
+package fr.pasteur.ida.zellige.behavior;
+
+import fr.pasteur.ida.zellige.utils.test.*;
+import net.imglib2.img.Img;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import net.imglib2.type.numeric.integer.UnsignedShortType;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvFileSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import static fr.pasteur.ida.zellige.behavior.Utils.buildStringLine;
+
+
+public class ParameterSweepCulture< T extends RealType< T > & NativeType< T >, R extends RealType< R > & NativeType< R > >
+{
+
+ private final static Logger LOGGER = LoggerFactory.getLogger( ParameterSweepCulture.class );
+ private static final String[] header = { "Parameter1", "Parameter1Value",
+ "GroundTruthNb", "SelectedPixelNb", "RMSE", "Coverage", "SelectionPT",
+ "AmplitudePT", "OtsuPT", "IslandSearchPT",
+ "ConstructionPT", "FS_OS_PT", "FS_surface_PT", "SS_OS_PT", "SS_surface_PT", "Total_PT",
+ "FS_OS_count", "FS_startingOS_count", "SS_OS_count", "SS_startingOS_count",
+ "FS_good", "FS_small", "FS_finalised",
+ "SS_good", "SS_small", "SS_finalised", "OptimizedSet" };
+ /* Specific Parameters */
+ private static final String sample = "Culture";
+ private static final String imagePath = "doc/Culture.tif";
+ private static final String[] refImagePath = new String[]{
+ "src/test/resources/Culture/C2-MucilairB spike zo1 J4 Sars-3_Ground truth Height map.tif"
+ };
+ static ArrayList< Img > ref;
+ static Img tested;
+ private static CSVWriter writer;
+ private final int delta = 0;
+ private final String parameterSweepCSVFile = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\Paper_012022\\ProcessingTime\\Cuture_PT.csv";
+ private final double surfaceMinSizeFactor = 0.3;
+ public String[] errorLine =
+ new String[]{
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN",
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN" };
+
+ // @Ignore
+ @BeforeAll
+ static void init() throws IOException
+ {
+ ParameterSweepFiles files = new ParameterSweepFiles( refImagePath, imagePath, "PT_" + sample );
+ ref = files.getRefs();
+ tested = files.getTested();
+ writer = new CSVWriter( files.getPath() );
+ writer.writeToFile( header );
+ RMSEAndCoverageComputation.setSubtract( - 1 );
+ LOGGER.info( "Parameter sweep for the {} sample", sample );
+ LOGGER.debug( " The parameter sweep is done for a total of {} ground truths", ref.size() );
+ }
+
+ @AfterAll
+ static void closeBw() throws IOException
+ {
+ writer.close();
+ }
+
+ @ParameterizedTest
+ @CsvFileSource( files = parameterSweepCSVFile, numLinesToSkip = 1, delimiterString = ";" )
+ void parameterSweep( String testedParameter, String testedParameterValue, String filter, int filterParameter,
+ int amplitudeThreshold, int otsuThreshold,
+ int ISConnexity, int ISSize,
+ double XYSmoothing, double ZSmoothing,
+ double startingThreshold1, int overlap1, double connexityRate1,
+ double startingThreshold2, int overlap2, double connexityRate2,
+ String optimalSet ) throws Exception
+ {
+ try
+ {
+ ZParameters parameters = new ZParameters( filter, filterParameter,
+ amplitudeThreshold, otsuThreshold, ISConnexity, ISSize, XYSmoothing, ZSmoothing,
+ startingThreshold1, overlap1, connexityRate1,
+ startingThreshold2, overlap2, connexityRate2, surfaceMinSizeFactor, delta );
+
+ parameters.print();
+ ZelligePipelineAnalyse< T, R > analyse = new ZelligePipelineAnalyse<>();
+ analyse.run( parameters, tested, ref );
+ for ( RMSEAndCoverageComputation< T, UnsignedShortType > r : analyse.getErrorList() )
+ {
+ String[] line = buildStringLine( testedParameter, testedParameterValue, analyse.getErrorAnalysis( r ), optimalSet );
+ writer.writeToFile( line );
+ }
+ }
+ catch ( OutOfMemoryError error )
+ {
+ for ( int i = 0; i < ref.size(); i++ )
+ {
+ writer.writeToFile( errorLine );
+ }
+ }
+ }
+
+
+}
diff --git a/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepMouche.java b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepMouche.java
new file mode 100644
index 0000000000000000000000000000000000000000..555e356f8403de4b664fb718790689d83a861931
--- /dev/null
+++ b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepMouche.java
@@ -0,0 +1,110 @@
+package fr.pasteur.ida.zellige.behavior;
+
+import fr.pasteur.ida.zellige.utils.test.*;
+import net.imglib2.img.Img;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import net.imglib2.type.numeric.integer.UnsignedShortType;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvFileSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import static fr.pasteur.ida.zellige.behavior.Utils.buildStringLine;
+
+
+public class ParameterSweepMouche< T extends RealType< T > & NativeType< T >, R extends RealType< R > & NativeType< R > >
+{
+
+ private final static Logger LOGGER = LoggerFactory.getLogger( ParameterSweepMouche.class );
+ private static final String[] header = { "Parameter1", "Parameter1Value",
+ "GroundTruthNb", "SelectedPixelNb", "RMSE", "Coverage", "SelectionPT",
+ "AmplitudePT", "OtsuPT", "IslandSearchPT",
+ "ConstructionPT", "FS_OS_PT", "FS_surface_PT", "SS_OS_PT", "SS_surface_PT", "Total_PT",
+ "FS_OS_count", "FS_startingOS_count", "SS_OS_count", "SS_startingOS_count",
+ "FS_good", "FS_small", "FS_finalised",
+ "SS_good", "SS_small", "SS_finalised", "OptimizedSet" };
+ public String[] errorLine =
+ new String[]{
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN",
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN" };
+ /* Specific Parameters */
+ private static final String sample = "Mouche";
+ private static final String imagePath = "doc/Mouche.tif";
+ private static final String[] refImagePath = new String[]{
+ "src/test/resources/Mouche/Ground truth Height map_1.tif",
+ "src/test/resources/Mouche/Ground truth Height map_2.tif",
+ "src/test/resources/Mouche/Ground truth Height map_3_crop.tif",
+ "src/test/resources/Mouche/Ground truth Height map_4_crop.tif"
+
+ };
+ static ArrayList< Img > ref;
+ static Img tested;
+ private static CSVWriter writer;
+ private final int delta = 0;
+ private final String parameterSweepCSVFile = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\Paper_012022\\ProcessingTime\\Mouche_PT.csv";
+ private final double surfaceMinSizeFactor = 0.05;
+
+ // @Ignore
+ @BeforeAll
+ static void init() throws IOException
+ {
+ ParameterSweepFiles files = new ParameterSweepFiles( refImagePath, imagePath, "PT_" + sample );
+ ref = files.getRefs();
+ tested = files.getTested();
+ writer = new CSVWriter( files.getPath() );
+ writer.writeToFile( header );
+ RMSEAndCoverageComputation.setSubtract( - 1 );
+ LOGGER.info( "Parameter sweep for the {} sample", sample );
+ LOGGER.debug( " The parameter sweep is done for a total of {} ground truths", ref.size() );
+ }
+
+ @AfterAll
+ static void closeBw() throws IOException
+ {
+ writer.close();
+ }
+
+ @ParameterizedTest
+ @CsvFileSource( files = parameterSweepCSVFile, numLinesToSkip = 1, delimiterString = ";" )
+ void parameterSweep( String testedParameter, String testedParameterValue, String filter, int filterParameter,
+ int amplitudeThreshold, int otsuThreshold,
+ int ISConnexity, int ISSize,
+ double XYSmoothing, double ZSmoothing,
+ double startingThreshold1, int overlap1, double connexityRate1,
+ double startingThreshold2, int overlap2, double connexityRate2,
+ String optimalSet ) throws Exception
+ {
+
+ try
+ {
+ ZParameters parameters = new ZParameters( filter, filterParameter,
+ amplitudeThreshold, otsuThreshold, ISConnexity, ISSize, XYSmoothing, ZSmoothing,
+ startingThreshold1, overlap1, connexityRate1,
+ startingThreshold2, overlap2, connexityRate2, surfaceMinSizeFactor, delta );
+
+ parameters.print();
+ ZelligePipelineAnalyse< T, R > analyse = new ZelligePipelineAnalyse<>();
+ analyse.run( parameters, tested, ref );
+ for ( RMSEAndCoverageComputation< T, UnsignedShortType > r : analyse.getErrorList() )
+ {
+ String[] line = buildStringLine( testedParameter, testedParameterValue, analyse.getErrorAnalysis( r ), optimalSet );
+ writer.writeToFile( line );
+ }
+ }
+ catch ( Exception exception )
+ {
+ for ( int i = 0; i < ref.size(); i++ )
+ {
+ writer.writeToFile( errorLine );
+ }
+ }
+ }
+
+
+}
diff --git a/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepOrganoid.java b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepOrganoid.java
new file mode 100644
index 0000000000000000000000000000000000000000..723c6d144b940b2f32268cd9c037c28edadb23db
--- /dev/null
+++ b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepOrganoid.java
@@ -0,0 +1,107 @@
+package fr.pasteur.ida.zellige.behavior;
+
+import fr.pasteur.ida.zellige.utils.test.*;
+import net.imglib2.img.Img;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import net.imglib2.type.numeric.integer.UnsignedShortType;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvFileSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import static fr.pasteur.ida.zellige.behavior.Utils.buildStringLine;
+
+
+public class ParameterSweepOrganoid< T extends RealType< T > & NativeType< T >, R extends RealType< R > & NativeType< R > >
+{
+
+ private final static Logger LOGGER = LoggerFactory.getLogger( ParameterSweepOrganoid.class );
+ private static final String[] header = { "Parameter1", "Parameter1Value",
+ "GroundTruthNb", "SelectedPixelNb", "RMSE", "Coverage", "SelectionPT",
+ "AmplitudePT", "OtsuPT", "IslandSearchPT",
+ "ConstructionPT", "FS_OS_PT", "FS_surface_PT", "SS_OS_PT", "SS_surface_PT", "Total_PT",
+ "FS_OS_count", "FS_startingOS_count", "SS_OS_count", "SS_startingOS_count",
+ "FS_good", "FS_small", "FS_finalised",
+ "SS_good", "SS_small", "SS_finalised", "OptimizedSet" };
+ public String[] errorLine =
+ new String[]{
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN",
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN" };
+ /* Specific Parameters */
+ private static final String sample = "Organoid";
+ private static final String imagePath = "doc/Organoid.tif";
+ private static final String[] refImagePath = new String[]{
+ "src/test/resources/Organoid/HM1.tif",
+ "src/test/resources/Organoid/HM2.tif"
+ };
+ static ArrayList< Img > ref;
+ static Img tested;
+ private static CSVWriter writer;
+ private final int delta = 0;
+ private final String parameterSweepCSVFile = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\Paper_012022\\ProcessingTime\\Organoid_PT.csv";
+ private final double surfaceMinSizeFactor = 0.1;
+
+ // @Ignore
+ @BeforeAll
+ static void init() throws IOException
+ {
+ ParameterSweepFiles files = new ParameterSweepFiles( refImagePath, imagePath, "PT_" + sample );
+ ref = files.getRefs();
+ tested = files.getTested();
+ writer = new CSVWriter( files.getPath() );
+ writer.writeToFile( header );
+ RMSEAndCoverageComputation.setSubtract( - 1 );
+ LOGGER.info( "Parameter sweep for the {} sample", sample );
+ LOGGER.debug( " The parameter sweep is done for a total of {} ground truths", ref.size() );
+ }
+
+ @AfterAll
+ static void closeBw() throws IOException
+ {
+ writer.close();
+ }
+
+ @ParameterizedTest
+ @CsvFileSource( files = parameterSweepCSVFile, numLinesToSkip = 1, delimiterString = ";" )
+ void parameterSweep( String testedParameter, String testedParameterValue, String filter, int filterParameter,
+ int amplitudeThreshold, int otsuThreshold,
+ int ISConnexity, int ISSize,
+ double XYSmoothing, double ZSmoothing,
+ double startingThreshold1, int overlap1, double connexityRate1,
+ double startingThreshold2, int overlap2, double connexityRate2,
+ String optimalSet ) throws Exception
+ {
+
+ try
+ {
+ ZParameters parameters = new ZParameters( filter, filterParameter,
+ amplitudeThreshold, otsuThreshold, ISConnexity, ISSize, XYSmoothing, ZSmoothing,
+ startingThreshold1, overlap1, connexityRate1,
+ startingThreshold2, overlap2, connexityRate2, surfaceMinSizeFactor, delta );
+
+ parameters.print();
+ ZelligePipelineAnalyse< T, R > analyse = new ZelligePipelineAnalyse<>();
+ analyse.run( parameters, tested, ref );
+ for ( RMSEAndCoverageComputation< T, UnsignedShortType > r : analyse.getErrorList() )
+ {
+ String[] line = buildStringLine( testedParameter, testedParameterValue, analyse.getErrorAnalysis( r ), optimalSet );
+ writer.writeToFile( line );
+ }
+ }
+ catch ( Exception exception )
+ {
+ for ( int i = 0; i < ref.size(); i++ )
+ {
+ writer.writeToFile( errorLine );
+ }
+ }
+ }
+
+
+}
diff --git a/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepPhantom.java b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepPhantom.java
new file mode 100644
index 0000000000000000000000000000000000000000..019eb98df43d9a8e2141d8bae7ad060652681479
--- /dev/null
+++ b/src/test/java/fr/pasteur/ida/zellige/behavior/ParameterSweepPhantom.java
@@ -0,0 +1,108 @@
+package fr.pasteur.ida.zellige.behavior;
+
+import fr.pasteur.ida.zellige.utils.test.*;
+import net.imglib2.img.Img;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.RealType;
+import net.imglib2.type.numeric.integer.UnsignedShortType;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvFileSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import static fr.pasteur.ida.zellige.behavior.Utils.buildStringLine;
+
+
+public class ParameterSweepPhantom< T extends RealType< T > & NativeType< T >, R extends RealType< R > & NativeType< R > >
+{
+
+ private final static Logger LOGGER = LoggerFactory.getLogger( ParameterSweepPhantom.class );
+ private static final String[] header = { "Parameter1", "Parameter1Value",
+ "GroundTruthNb", "SelectedPixelNb", "RMSE", "Coverage", "SelectionPT",
+ "AmplitudePT", "OtsuPT", "IslandSearchPT",
+ "ConstructionPT", "FS_OS_PT", "FS_surface_PT", "SS_OS_PT", "SS_surface_PT", "Total_PT",
+ "FS_OS_count", "FS_startingOS_count", "SS_OS_count", "SS_startingOS_count",
+ "FS_good", "FS_small", "FS_finalised",
+ "SS_good", "SS_small", "SS_finalised", "OptimizedSet" };
+ public String[] errorLine =
+ new String[]{
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN",
+ "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN", "NaN" };
+ /* Specific Parameters */
+ private static final String sample = "Phantom";
+ private static final String imagePath = "doc/Phantom.tif";
+ private static final String[] refImagePath = new String[]{
+ "src/test/resources/Phantom/phantoms_snrtest_zmap1_gt.tif",
+ "src/test/resources/Phantom/phantoms_snrtest_zmap2_gt.tif",
+ "src/test/resources/Phantom/phantoms_snrtest_zmap3_gt.tif"
+ };
+ static ArrayList< Img > ref;
+ static Img tested;
+ private static CSVWriter writer;
+ private final int delta = 0;
+ private final String parameterSweepCSVFile = "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\Paper_012022\\ProcessingTime\\Phantom_PT.csv";
+ private final double surfaceMinSizeFactor = 0.8;
+
+ // @Ignore
+ @BeforeAll
+ static void init() throws IOException
+ {
+ ParameterSweepFiles files = new ParameterSweepFiles( refImagePath, imagePath, "PT_" + sample );
+ ref = files.getRefs();
+ tested = files.getTested();
+ writer = new CSVWriter( files.getPath() );
+ writer.writeToFile( header );
+ RMSEAndCoverageComputation.setSubtract( 0 );
+ LOGGER.info( "Parameter sweep for the {} sample", sample );
+ LOGGER.debug( " The parameter sweep is done for a total of {} ground truths", ref.size() );
+ }
+
+ @AfterAll
+ static void closeBw() throws IOException
+ {
+ writer.close();
+ }
+
+ @ParameterizedTest
+ @CsvFileSource( files = parameterSweepCSVFile, numLinesToSkip = 1, delimiterString = ";" )
+ void parameterSweep( String testedParameter, String testedParameterValue, String filter, int filterParameter,
+ int amplitudeThreshold, int otsuThreshold,
+ int ISConnexity, int ISSize,
+ double XYSmoothing, double ZSmoothing,
+ double startingThreshold1, int overlap1, double connexityRate1,
+ double startingThreshold2, int overlap2, double connexityRate2,
+ String optimalSet ) throws Exception
+ {
+
+ try
+ {
+ ZParameters parameters = new ZParameters( filter, filterParameter,
+ amplitudeThreshold, otsuThreshold, ISConnexity, ISSize, XYSmoothing, ZSmoothing,
+ startingThreshold1, overlap1, connexityRate1,
+ startingThreshold2, overlap2, connexityRate2, surfaceMinSizeFactor, delta );
+
+ parameters.print();
+ ZelligePipelineAnalyse< T, R > analyse = new ZelligePipelineAnalyse<>();
+ analyse.run( parameters, tested, ref );
+ for ( RMSEAndCoverageComputation< T, UnsignedShortType > r : analyse.getErrorList() )
+ {
+ String[] line = buildStringLine( testedParameter, testedParameterValue, analyse.getErrorAnalysis( r ), optimalSet );
+ writer.writeToFile( line );
+ }
+ }
+ catch ( Exception exception )
+ {
+ for ( int i = 0; i < ref.size(); i++ )
+ {
+ writer.writeToFile( errorLine );
+ }
+ }
+ }
+
+
+}
diff --git a/src/test/java/fr/pasteur/ida/zellige/behavior/StartingOSE_SameSurfaceTest.java b/src/test/java/fr/pasteur/ida/zellige/behavior/StartingOSE_SameSurfaceTest.java
index bd17aaa75d598d2cb5c574d1e0790c545d4cb93d..587095c7957aed4ca0582a060cff940d72e2e798 100644
--- a/src/test/java/fr/pasteur/ida/zellige/behavior/StartingOSE_SameSurfaceTest.java
+++ b/src/test/java/fr/pasteur/ida/zellige/behavior/StartingOSE_SameSurfaceTest.java
@@ -37,8 +37,8 @@ public class StartingOSE_SameSurfaceTest
< T extends RealType< T > & NativeType< T > > void TwoStartingOSEFromTheSameSurface_whenUseForStartASurface_DonTProduceTheExactSameSurface() throws DataValidationException, EmptyOutputException, NoClassificationException
{
/* Parameters*/
- double amplitude = 0.2;
- double otsu = 0.2;
+ int amplitude = 5;
+ int otsu = 5;
double sigmaXY = 2;
double sigmaZ = 0;
double startingSizeThreshold = 0.9;
diff --git a/src/test/java/fr/pasteur/ida/zellige/behavior/Utils.java b/src/test/java/fr/pasteur/ida/zellige/behavior/Utils.java
new file mode 100644
index 0000000000000000000000000000000000000000..458ccc8533e9cafed1b4a9be78a004fa951c61d3
--- /dev/null
+++ b/src/test/java/fr/pasteur/ida/zellige/behavior/Utils.java
@@ -0,0 +1,21 @@
+package fr.pasteur.ida.zellige.behavior;
+
+public class Utils
+{
+
+ public static String[] buildStringLine( String testedParameter1, String testedParameterValue1,
+ String[] error, String optimalSet )
+ {
+ String[] line = new String[ 3 + error.length ];
+ line[ 0 ] = testedParameter1;
+ line[ 1 ] = testedParameterValue1;
+ int index = 2;
+ for ( String s : error )
+ {
+ line[ index ] = s;
+ index++;
+ }
+ line[ line.length - 1 ] = optimalSet;
+ return line;
+ }
+}
diff --git a/src/test/java/fr/pasteur/ida/zellige/parameters/ClassificationParametersTest.java b/src/test/java/fr/pasteur/ida/zellige/parameters/ClassificationParametersTest.java
index 99db282925d1983a432804d8727cbb3c83355966..0029d1df97a487e3c726c5f07a2d5c44f46045f5 100644
--- a/src/test/java/fr/pasteur/ida/zellige/parameters/ClassificationParametersTest.java
+++ b/src/test/java/fr/pasteur/ida/zellige/parameters/ClassificationParametersTest.java
@@ -15,8 +15,8 @@ public class ClassificationParametersTest
@Test
void rightPixelClassificationParameters_whenCreatingANewInstance_DonTRaiseAValidationDataException()
{
- double amplitudeThreshold = 1.0;
- double otsuThreshold = 1.5;
+ int amplitudeThreshold = 5;
+ int otsuThreshold = 5;
assertDoesNotThrow( () -> new ClassificationParameters( amplitudeThreshold, otsuThreshold ) );
}
@@ -25,22 +25,22 @@ public class ClassificationParametersTest
@Test
void amplitudeThresholdUnderZero_WhenCreatingANewInstance_raisesAValidationDataException()
{
- double amplitudeThreshold = -1;
- double otsuThreshold = 1.5;
+ int amplitudeThreshold = - 1;
+ int otsuThreshold = 2;
DataValidationException exception = assertThrows( DataValidationException.class, () ->
new ClassificationParameters( amplitudeThreshold, otsuThreshold ) );
- assertThat(exception).hasMessageContaining( "Amplitude" );
+ assertThat( exception ).hasMessageContaining( "Amplitude" );
}
@DisplayName( " An otsu threshold inferior to zero raises a ValidationDataException with a specific message " )
@Test
void otsuThresholdUnderZero_WhenCreatingANewInstance_raisesAValidationDataException()
{
- double amplitudeThreshold = 1;
- double otsuThreshold = - 1;
+ int amplitudeThreshold = 1;
+ int otsuThreshold = - 1;
DataValidationException exception = assertThrows( DataValidationException.class, () ->
new ClassificationParameters( amplitudeThreshold, otsuThreshold ) );
- assertThat(exception).hasMessageContaining( "Otsu" );
+ assertThat( exception ).hasMessageContaining( "Otsu" );
}
diff --git "a/src/test/resources/Cochl\303\251e2/Ground truth Height map.tif" "b/src/test/resources/Cochl\303\251e2/Ground truth Height map.tif"
new file mode 100644
index 0000000000000000000000000000000000000000..cbe88c0b0988f206ee3d043036f58e377016066d
Binary files /dev/null and "b/src/test/resources/Cochl\303\251e2/Ground truth Height map.tif" differ
diff --git "a/src/test/resources/Cochl\303\251e2/PS_Cochl\303\251e2.csv" "b/src/test/resources/Cochl\303\251e2/PS_Cochl\303\251e2.csv"
new file mode 100644
index 0000000000000000000000000000000000000000..7a2e083dbf7fdcd3d9b79ae0a26123e9bbab6528
--- /dev/null
+++ "b/src/test/resources/Cochl\303\251e2/PS_Cochl\303\251e2.csv"
@@ -0,0 +1,163 @@
+Cochlee2;;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;
+Amplitude;0;GaussianBlur;2;0;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;1;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+Amplitude;2;GaussianBlur;2;2;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;3;GaussianBlur;2;3;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;4;GaussianBlur;2;4;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;5;GaussianBlur;2;5;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;6;GaussianBlur;2;6;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;7;GaussianBlur;2;7;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;8;GaussianBlur;2;8;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;9;GaussianBlur;2;9;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;10;GaussianBlur;2;10;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;11;GaussianBlur;2;11;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;12;GaussianBlur;2;12;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;13;GaussianBlur;2;13;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;14;GaussianBlur;2;14;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;15;GaussianBlur;2;15;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;16;GaussianBlur;2;16;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;17;GaussianBlur;2;17;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;18;GaussianBlur;2;18;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;19;GaussianBlur;2;19;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;20;GaussianBlur;2;20;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;21;GaussianBlur;2;21;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;22;GaussianBlur;2;22;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;23;GaussianBlur;2;23;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;24;GaussianBlur;2;24;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;25;GaussianBlur;2;25;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;26;GaussianBlur;2;26;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;27;GaussianBlur;2;27;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;28;GaussianBlur;2;28;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;29;GaussianBlur;2;29;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Amplitude;30;GaussianBlur;2;30;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;0;GaussianBlur;2;1;0;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;1;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+Otsu;2;GaussianBlur;2;1;2;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;3;GaussianBlur;2;1;3;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;4;GaussianBlur;2;1;4;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;5;GaussianBlur;2;1;5;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;6;GaussianBlur;2;1;6;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;7;GaussianBlur;2;1;7;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;8;GaussianBlur;2;1;8;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;9;GaussianBlur;2;1;9;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;10;GaussianBlur;2;1;10;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;11;GaussianBlur;2;1;11;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;12;GaussianBlur;2;1;12;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;13;GaussianBlur;2;1;13;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;14;GaussianBlur;2;1;14;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;15;GaussianBlur;2;1;15;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;16;GaussianBlur;2;1;16;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;17;GaussianBlur;2;1;17;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;18;GaussianBlur;2;1;18;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;19;GaussianBlur;2;1;19;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;20;GaussianBlur;2;1;20;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;21;GaussianBlur;2;1;21;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;22;GaussianBlur;2;1;22;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;23;GaussianBlur;2;1;23;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;24;GaussianBlur;2;1;24;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;25;GaussianBlur;2;1;25;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;26;GaussianBlur;2;1;26;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;27;GaussianBlur;2;1;27;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;28;GaussianBlur;2;1;28;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;29;GaussianBlur;2;1;29;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Otsu;30;GaussianBlur;2;1;30;4;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+IS Connexity;4;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+IS Connexity;8;GaussianBlur;2;1;1;8;5;4;1;0.1;5;0.7;0.1;10;0.8;NO
+IS Min Size;0;GaussianBlur;2;1;1;4;0;4;1;0.1;5;0.7;0.1;10;0.8;NO
+IS Min Size;5;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+IS Min Size;10;GaussianBlur;2;1;1;4;10;4;1;0.1;5;0.7;0.1;10;0.8;NO
+IS Min Size;15;GaussianBlur;2;1;1;4;15;4;1;0.1;5;0.7;0.1;10;0.8;NO
+IS Min Size;20;GaussianBlur;2;1;1;4;20;4;1;0.1;5;0.7;0.1;10;0.8;NO
+IS Min Size;25;GaussianBlur;2;1;1;4;25;4;1;0.1;5;0.7;0.1;10;0.8;NO
+IS Min Size;30;GaussianBlur;2;1;1;4;30;4;1;0.1;5;0.7;0.1;10;0.8;NO
+IS Min Size;35;GaussianBlur;2;1;1;4;35;4;1;0.1;5;0.7;0.1;10;0.8;NO
+IS Min Size;40;GaussianBlur;2;1;1;4;40;4;1;0.1;5;0.7;0.1;10;0.8;NO
+IS Min Size;45;GaussianBlur;2;1;1;4;45;4;1;0.1;5;0.7;0.1;10;0.8;NO
+IS Min Size;50;GaussianBlur;2;1;1;4;50;4;1;0.1;5;0.7;0.1;10;0.8;NO
+Blur XY;0;GaussianBlur;2;1;1;4;5;0;1;0.1;5;0.7;0.1;10;0.8;NO
+Blur XY;1;GaussianBlur;2;1;1;4;5;1;1;0.1;5;0.7;0.1;10;0.8;NO
+Blur XY;2;GaussianBlur;2;1;1;4;5;2;1;0.1;5;0.7;0.1;10;0.8;NO
+Blur XY;3;GaussianBlur;2;1;1;4;5;3;1;0.1;5;0.7;0.1;10;0.8;NO
+Blur XY;4;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+Blur XY;5;GaussianBlur;2;1;1;4;5;5;1;0.1;5;0.7;0.1;10;0.8;NO
+Blur XY;6;GaussianBlur;2;1;1;4;5;6;1;0.1;5;0.7;0.1;10;0.8;NO
+Blur XY;7;GaussianBlur;2;1;1;4;5;7;1;0.1;5;0.7;0.1;10;0.8;NO
+Blur XY;8;GaussianBlur;2;1;1;4;5;8;1;0.1;5;0.7;0.1;10;0.8;NO
+Blur XY;9;GaussianBlur;2;1;1;4;5;9;1;0.1;5;0.7;0.1;10;0.8;NO
+Blur XY;10;GaussianBlur;2;1;1;4;5;10;1;0.1;5;0.7;0.1;10;0.8;NO
+Blur Z;0;GaussianBlur;2;1;1;4;5;4;0;0.1;5;0.7;0.1;10;0.8;NO
+Blur Z;1;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+Blur Z;2;GaussianBlur;2;1;1;4;5;4;2;0.1;5;0.7;0.1;10;0.8;NO
+Blur Z;3;GaussianBlur;2;1;1;4;5;4;3;0.1;5;0.7;0.1;10;0.8;NO
+Blur Z;4;GaussianBlur;2;1;1;4;5;4;4;0.1;5;0.7;0.1;10;0.8;NO
+Blur Z;5;GaussianBlur;2;1;1;4;5;4;5;0.1;5;0.7;0.1;10;0.8;NO
+Blur Z;6;GaussianBlur;2;1;1;4;5;4;6;0.1;5;0.7;0.1;10;0.8;NO
+Blur Z;7;GaussianBlur;2;1;1;4;5;4;7;0.1;5;0.7;0.1;10;0.8;NO
+Blur Z;8;GaussianBlur;2;1;1;4;5;4;8;0.1;5;0.7;0.1;10;0.8;NO
+Blur Z;9;GaussianBlur;2;1;1;4;5;4;9;0.1;5;0.7;0.1;10;0.8;NO
+Blur Z;10;GaussianBlur;2;1;1;4;5;4;10;0.1;5;0.7;0.1;10;0.8;NO
+ST_1;0.0;GaussianBlur;2;1;1;4;5;4;1;0.0;5;0.7;0.1;10;0.8;NO
+ST_1;0.1;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+ST_1;0.2;GaussianBlur;2;1;1;4;5;4;1;0.2;5;0.7;0.1;10;0.8;NO
+ST_1;0.3;GaussianBlur;2;1;1;4;5;4;1;0.3;5;0.7;0.1;10;0.8;NO
+ST_1;0.4;GaussianBlur;2;1;1;4;5;4;1;0.4;5;0.7;0.1;10;0.8;NO
+ST_1;0.5;GaussianBlur;2;1;1;4;5;4;1;0.5;5;0.7;0.1;10;0.8;NO
+ST_1;0.6;GaussianBlur;2;1;1;4;5;4;1;0.6;5;0.7;0.1;10;0.8;NO
+ST_1;0.7;GaussianBlur;2;1;1;4;5;4;1;0.7;5;0.7;0.1;10;0.8;NO
+ST_1;0.8;GaussianBlur;2;1;1;4;5;4;1;0.8;5;0.7;0.1;10;0.8;NO
+Overlap_1;0;GaussianBlur;2;1;1;4;5;4;1;0.1;0;0.7;0.1;10;0.8;NO
+Overlap_1;5;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+Overlap_1;10;GaussianBlur;2;1;1;4;5;4;1;0.1;10;0.7;0.1;10;0.8;NO
+Overlap_1;15;GaussianBlur;2;1;1;4;5;4;1;0.1;15;0.7;0.1;10;0.8;NO
+Overlap_1;17;GaussianBlur;2;1;1;4;5;4;1;0.1;17;0.7;0.1;10;0.8;NO
+Overlap_1;20;GaussianBlur;2;1;1;4;5;4;1;0.1;20;0.7;0.1;10;0.8;NO
+Overlap_1;25;GaussianBlur;2;1;1;4;5;4;1;0.1;25;0.7;0.1;10;0.8;NO
+Overlap_1;30;GaussianBlur;2;1;1;4;5;4;1;0.1;30;0.7;0.1;10;0.8;NO
+Overlap_1;35;GaussianBlur;2;1;1;4;5;4;1;0.1;35;0.7;0.1;10;0.8;NO
+Overlap_1;40;GaussianBlur;2;1;1;4;5;4;1;0.1;40;0.7;0.1;10;0.8;NO
+Overlap_1;45;GaussianBlur;2;1;1;4;5;4;1;0.1;45;0.7;0.1;10;0.8;NO
+Overlap_1;50;GaussianBlur;2;1;1;4;5;4;1;0.1;50;0.7;0.1;10;0.8;NO
+CR_1;0.5;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.5;0.1;10;0.8;NO
+CR_1;0.55;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.55;0.1;10;0.8;NO
+CR_1;0.6;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.6;0.1;10;0.8;NO
+CR_1;0.65;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.65;0.1;10;0.8;NO
+CR_1;0.7;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+CR_1;0.75;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.75;0.1;10;0.8;NO
+CR_1;0.8;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.8;0.1;10;0.8;NO
+CR_1;0.85;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.85;0.1;10;0.8;NO
+CR_1;0.9;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.9;0.1;10;0.8;NO
+CR_1;0.95;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.95;0.1;10;0.8;NO
+CR_1;1;GaussianBlur;2;1;1;4;5;4;1;0.1;5;1;0.1;10;0.8;NO
+ST_2;0.0;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.0;10;0.8;NO
+ST_2;0.1;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+ST_2;0.2;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.2;10;0.8;NO
+ST_2;0.3;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.3;10;0.8;NO
+ST_2;0.4;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.4;10;0.8;NO
+ST_2;0.5;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.5;10;0.8;NO
+ST_2;0.6;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.6;10;0.8;NO
+ST_2;0.7;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.7;10;0.8;NO
+ST_2;0.8;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.8;10;0.8;NO
+ST_2;0.9;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.9;10;0.8;NO
+ST_2;1.0;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;1.0;10;0.8;NO
+Overlap_2;0;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;0;0.8;NO
+Overlap_2;5;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;5;0.8;NO
+Overlap_2;10;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+Overlap_2;15;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;15;0.8;NO
+Overlap_2;20;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;20;0.8;NO
+Overlap_2;25;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;25;0.8;NO
+Overlap_2;30;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;30;0.8;NO
+Overlap_2;35;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;35;0.8;NO
+Overlap_2;40;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;40;0.8;NO
+Overlap_2;45;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;45;0.8;NO
+Overlap_2;50;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;50;0.8;NO
+CR_2;0.5;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.5;NO
+CR_2;0.55;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.55;NO
+CR_2;0.6;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.6;NO
+CR_2;0.65;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.65;NO
+CR_2;0.7;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.7;NO
+CR_2;0.75;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.75;NO
+CR_2;0.8;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.8;YES
+CR_2;0.85;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.85;NO
+CR_2;0.9;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.9;NO
+CR_2;0.95;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;0.95;NO
+CR_2;1;GaussianBlur;2;1;1;4;5;4;1;0.1;5;0.7;0.1;10;1;NO
diff --git a/src/test/resources/Culture/C2-MucilairB spike zo1 J4 Sars-3_Ground truth Height map.tif b/src/test/resources/Culture/C2-MucilairB spike zo1 J4 Sars-3_Ground truth Height map.tif
new file mode 100644
index 0000000000000000000000000000000000000000..05ab8be7dc6ed804ebfb35e6992e27888b2afc77
Binary files /dev/null and b/src/test/resources/Culture/C2-MucilairB spike zo1 J4 Sars-3_Ground truth Height map.tif differ
diff --git a/src/test/resources/Culture/PS_Culture.csv b/src/test/resources/Culture/PS_Culture.csv
new file mode 100644
index 0000000000000000000000000000000000000000..5c17726415525c51009dcffab80646a50f7e1344
--- /dev/null
+++ b/src/test/resources/Culture/PS_Culture.csv
@@ -0,0 +1,165 @@
+Culture;;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;
+Amplitude;0;GaussianBlur;2;0;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;1;GaussianBlur;2;1;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;2;GaussianBlur;2;2;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;3;GaussianBlur;2;3;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;4;GaussianBlur;2;4;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;5;GaussianBlur;2;5;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;6;GaussianBlur;2;6;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;7;GaussianBlur;2;7;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;8;GaussianBlur;2;8;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;9;GaussianBlur;2;9;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;10;GaussianBlur;2;10;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;11;GaussianBlur;2;11;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;12;GaussianBlur;2;12;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;13;GaussianBlur;2;13;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;14;GaussianBlur;2;14;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;15;GaussianBlur;2;15;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;16;GaussianBlur;2;16;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;17;GaussianBlur;2;17;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;18;GaussianBlur;2;18;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;19;GaussianBlur;2;19;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;20;GaussianBlur;2;20;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;21;GaussianBlur;2;21;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;22;GaussianBlur;2;22;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;23;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+Amplitude;24;GaussianBlur;2;24;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;25;GaussianBlur;2;25;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;26;GaussianBlur;2;26;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;27;GaussianBlur;2;27;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;28;GaussianBlur;2;28;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;29;GaussianBlur;2;29;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Amplitude;30;GaussianBlur;2;30;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;0;GaussianBlur;2;23;0;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;1;GaussianBlur;2;23;1;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;2;GaussianBlur;2;23;2;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;3;GaussianBlur;2;23;3;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;4;GaussianBlur;2;23;4;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;5;GaussianBlur;2;23;5;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;6;GaussianBlur;2;23;6;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;7;GaussianBlur;2;23;7;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;8;GaussianBlur;2;23;8;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;9;GaussianBlur;2;23;9;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;10;GaussianBlur;2;23;10;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;11;GaussianBlur;2;23;11;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;12;GaussianBlur;2;23;12;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;13;GaussianBlur;2;23;13;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;14;GaussianBlur;2;23;14;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;15;GaussianBlur;2;23;15;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;16;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+Otsu;17;GaussianBlur;2;23;17;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;18;GaussianBlur;2;23;18;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;19;GaussianBlur;2;23;19;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;20;GaussianBlur;2;23;20;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;21;GaussianBlur;2;23;21;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;22;GaussianBlur;2;23;22;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;23;GaussianBlur;2;23;23;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;24;GaussianBlur;2;23;24;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;25;GaussianBlur;2;23;25;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;26;GaussianBlur;2;23;26;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;27;GaussianBlur;2;23;27;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;28;GaussianBlur;2;23;28;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;29;GaussianBlur;2;23;29;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Otsu;30;GaussianBlur;2;23;30;4;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+IS Connexity;4;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+IS Connexity;8;GaussianBlur;2;23;16;8;5;4;1;0.9;5;0.9;0.1;5;0.8;NO
+IS Min Size;0;GaussianBlur;2;23;16;4;0;4;1;0.9;5;0.9;0.1;5;0.8;NO
+IS Min Size;5;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+IS Min Size;10;GaussianBlur;2;23;16;4;10;4;1;0.9;5;0.9;0.1;5;0.8;NO
+IS Min Size;15;GaussianBlur;2;23;16;4;15;4;1;0.9;5;0.9;0.1;5;0.8;NO
+IS Min Size;20;GaussianBlur;2;23;16;4;20;4;1;0.9;5;0.9;0.1;5;0.8;NO
+IS Min Size;25;GaussianBlur;2;23;16;4;25;4;1;0.9;5;0.9;0.1;5;0.8;NO
+IS Min Size;30;GaussianBlur;2;23;16;4;30;4;1;0.9;5;0.9;0.1;5;0.8;NO
+IS Min Size;35;GaussianBlur;2;23;16;4;35;4;1;0.9;5;0.9;0.1;5;0.8;NO
+IS Min Size;40;GaussianBlur;2;23;16;4;40;4;1;0.9;5;0.9;0.1;5;0.8;NO
+IS Min Size;45;GaussianBlur;2;23;16;4;45;4;1;0.9;5;0.9;0.1;5;0.8;NO
+IS Min Size;50;GaussianBlur;2;23;16;4;50;4;1;0.9;5;0.9;0.1;5;0.8;NO
+Blur XY;0;GaussianBlur;2;23;16;4;5;0;1;0.9;5;0.9;0.1;5;0.8;NO
+Blur XY;1;GaussianBlur;2;23;16;4;5;1;1;0.9;5;0.9;0.1;5;0.8;NO
+Blur XY;2;GaussianBlur;2;23;16;4;5;2;1;0.9;5;0.9;0.1;5;0.8;NO
+Blur XY;3;GaussianBlur;2;23;16;4;5;3;1;0.9;5;0.9;0.1;5;0.8;NO
+Blur XY;4;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+Blur XY;5;GaussianBlur;2;23;16;4;5;5;1;0.9;5;0.9;0.1;5;0.8;NO
+Blur XY;6;GaussianBlur;2;23;16;4;5;6;1;0.9;5;0.9;0.1;5;0.8;NO
+Blur XY;7;GaussianBlur;2;23;16;4;5;7;1;0.9;5;0.9;0.1;5;0.8;NO
+Blur XY;8;GaussianBlur;2;23;16;4;5;8;1;0.9;5;0.9;0.1;5;0.8;NO
+Blur XY;9;GaussianBlur;2;23;16;4;5;9;1;0.9;5;0.9;0.1;5;0.8;NO
+Blur XY;10;GaussianBlur;2;23;16;4;5;10;1;0.9;5;0.9;0.1;5;0.8;NO
+Blur Z;0;GaussianBlur;2;23;16;4;5;4;0;0.9;5;0.9;0.1;5;0.8;NO
+Blur Z;1;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+Blur Z;2;GaussianBlur;2;23;16;4;5;4;2;0.9;5;0.9;0.1;5;0.8;NO
+Blur Z;3;GaussianBlur;2;23;16;4;5;4;3;0.9;5;0.9;0.1;5;0.8;NO
+Blur Z;4;GaussianBlur;2;23;16;4;5;4;4;0.9;5;0.9;0.1;5;0.8;NO
+Blur Z;5;GaussianBlur;2;23;16;4;5;4;5;0.9;5;0.9;0.1;5;0.8;NO
+Blur Z;6;GaussianBlur;2;23;16;4;5;4;6;0.9;5;0.9;0.1;5;0.8;NO
+Blur Z;7;GaussianBlur;2;23;16;4;5;4;7;0.9;5;0.9;0.1;5;0.8;NO
+Blur Z;8;GaussianBlur;2;23;16;4;5;4;8;0.9;5;0.9;0.1;5;0.8;NO
+Blur Z;9;GaussianBlur;2;23;16;4;5;4;9;0.9;5;0.9;0.1;5;0.8;NO
+Blur Z;10;GaussianBlur;2;23;16;4;5;4;10;0.9;5;0.9;0.1;5;0.8;NO
+ST_1;0.0;GaussianBlur;2;23;16;4;5;4;1;0.0;5;0.9;0.1;5;0.8;NO
+ST_1;0.1;GaussianBlur;2;23;16;4;5;4;1;0.1;5;0.9;0.1;5;0.8;NO
+ST_1;0.2;GaussianBlur;2;23;16;4;5;4;1;0.2;5;0.9;0.1;5;0.8;NO
+ST_1;0.3;GaussianBlur;2;23;16;4;5;4;1;0.3;5;0.9;0.1;5;0.8;NO
+ST_1;0.4;GaussianBlur;2;23;16;4;5;4;1;0.4;5;0.9;0.1;5;0.8;NO
+ST_1;0.5;GaussianBlur;2;23;16;4;5;4;1;0.5;5;0.9;0.1;5;0.8;NO
+ST_1;0.6;GaussianBlur;2;23;16;4;5;4;1;0.6;5;0.9;0.1;5;0.8;NO
+ST_1;0.7;GaussianBlur;2;23;16;4;5;4;1;0.7;5;0.9;0.1;5;0.8;NO
+ST_1;0.8;GaussianBlur;2;23;16;4;5;4;1;0.8;5;0.9;0.1;5;0.8;NO
+ST_1;0.9;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+ST_1;1.0;GaussianBlur;2;23;16;4;5;4;1;1.0;5;0.9;0.1;5;0.8;NO
+Overlap_1;0;GaussianBlur;2;23;16;4;5;4;1;0.9;0;0.9;0.1;5;0.8;NO
+Overlap_1;5;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+Overlap_1;10;GaussianBlur;2;23;16;4;5;4;1;0.9;10;0.9;0.1;5;0.8;NO
+Overlap_1;15;GaussianBlur;2;23;16;4;5;4;1;0.9;15;0.9;0.1;5;0.8;NO
+Overlap_1;17;GaussianBlur;2;23;16;4;5;4;1;0.9;17;0.9;0.1;5;0.8;NO
+Overlap_1;20;GaussianBlur;2;23;16;4;5;4;1;0.9;20;0.9;0.1;5;0.8;NO
+Overlap_1;25;GaussianBlur;2;23;16;4;5;4;1;0.9;25;0.9;0.1;5;0.8;NO
+Overlap_1;30;GaussianBlur;2;23;16;4;5;4;1;0.9;30;0.9;0.1;5;0.8;NO
+Overlap_1;35;GaussianBlur;2;23;16;4;5;4;1;0.9;35;0.9;0.1;5;0.8;NO
+Overlap_1;40;GaussianBlur;2;23;16;4;5;4;1;0.9;40;0.9;0.1;5;0.8;NO
+Overlap_1;45;GaussianBlur;2;23;16;4;5;4;1;0.9;45;0.9;0.1;5;0.8;NO
+Overlap_1;50;GaussianBlur;2;23;16;4;5;4;1;0.9;50;0.9;0.1;5;0.8;NO
+CR_1;0.5;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.5;0.1;5;0.8;NO
+CR_1;0.55;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.55;0.1;5;0.8;NO
+CR_1;0.6;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.6;0.1;5;0.8;NO
+CR_1;0.65;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.65;0.1;5;0.8;NO
+CR_1;0.7;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.7;0.1;5;0.8;NO
+CR_1;0.75;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.75;0.1;5;0.8;NO
+CR_1;0.8;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.8;0.1;5;0.8;NO
+CR_1;0.85;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.85;0.1;5;0.8;NO
+CR_1;0.9;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+CR_1;0.95;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.95;0.1;5;0.8;NO
+CR_1;1;GaussianBlur;2;23;16;4;5;4;1;0.9;5;1;0.1;5;0.8;NO
+ST_2;0.0;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.0;5;0.8;NO
+ST_2;0.1;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+ST_2;0.2;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.2;5;0.8;NO
+ST_2;0.3;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.3;5;0.8;NO
+ST_2;0.4;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.4;5;0.8;NO
+ST_2;0.5;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.5;5;0.8;NO
+ST_2;0.6;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.6;5;0.8;NO
+ST_2;0.7;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.7;5;0.8;NO
+ST_2;0.8;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.8;5;0.8;NO
+ST_2;0.9;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.9;5;0.8;NO
+ST_2;1.0;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;1.0;5;0.8;NO
+Overlap_2;0;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;0;0.8;NO
+Overlap_2;5;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+Overlap_2;10;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;10;0.8;NO
+Overlap_2;15;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;15;0.8;NO
+Overlap_2;20;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;20;0.8;NO
+Overlap_2;25;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;25;0.8;NO
+Overlap_2;30;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;30;0.8;NO
+Overlap_2;35;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;35;0.8;NO
+Overlap_2;40;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;40;0.8;NO
+Overlap_2;45;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;45;0.8;NO
+Overlap_2;50;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;50;0.8;NO
+CR_2;0.5;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.5;NO
+CR_2;0.55;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.55;NO
+CR_2;0.6;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.6;NO
+CR_2;0.65;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.65;NO
+CR_2;0.7;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.7;NO
+CR_2;0.75;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.75;NO
+CR_2;0.8;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.8;YES
+CR_2;0.85;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.85;NO
+CR_2;0.9;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.9;NO
+CR_2;0.95;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;0.95;NO
+CR_2;1;GaussianBlur;2;23;16;4;5;4;1;0.9;5;0.9;0.1;5;1;NO
diff --git a/src/test/resources/Mouche_c01_f0001_p013/Ground truth Height map_1.tif b/src/test/resources/Mouche/Ground truth Height map_1.tif
similarity index 100%
rename from src/test/resources/Mouche_c01_f0001_p013/Ground truth Height map_1.tif
rename to src/test/resources/Mouche/Ground truth Height map_1.tif
diff --git a/src/test/resources/Mouche_c01_f0001_p013/Ground truth Height map_2.tif b/src/test/resources/Mouche/Ground truth Height map_2.tif
similarity index 100%
rename from src/test/resources/Mouche_c01_f0001_p013/Ground truth Height map_2.tif
rename to src/test/resources/Mouche/Ground truth Height map_2.tif
diff --git a/src/test/resources/Mouche/Ground truth Height map_3_crop.tif b/src/test/resources/Mouche/Ground truth Height map_3_crop.tif
new file mode 100644
index 0000000000000000000000000000000000000000..4926f1d9e01c2a03d1f7f5370f572c9d47fa24e0
Binary files /dev/null and b/src/test/resources/Mouche/Ground truth Height map_3_crop.tif differ
diff --git a/src/test/resources/Mouche/Ground truth Height map_4_crop.tif b/src/test/resources/Mouche/Ground truth Height map_4_crop.tif
new file mode 100644
index 0000000000000000000000000000000000000000..97818d6078907014ce2fe0abc2bcbf8c86d6a3d7
Binary files /dev/null and b/src/test/resources/Mouche/Ground truth Height map_4_crop.tif differ
diff --git a/src/test/resources/Mouche/Mouche_PS.csv b/src/test/resources/Mouche/Mouche_PS.csv
new file mode 100644
index 0000000000000000000000000000000000000000..18d0a6f5e303094da2ed3f765c443c9d0083c78c
--- /dev/null
+++ b/src/test/resources/Mouche/Mouche_PS.csv
@@ -0,0 +1,165 @@
+Mouche;;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;
+Amplitude;0;GaussianBlur;2;0;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;1;GaussianBlur;2;1;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;2;GaussianBlur;2;2;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;3;GaussianBlur;2;3;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;4;GaussianBlur;2;4;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;5;GaussianBlur;2;5;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;6;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+Amplitude;7;GaussianBlur;2;7;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;8;GaussianBlur;2;8;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;9;GaussianBlur;2;9;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;10;GaussianBlur;2;10;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;11;GaussianBlur;2;11;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;12;GaussianBlur;2;12;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;13;GaussianBlur;2;13;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;14;GaussianBlur;2;14;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;15;GaussianBlur;2;15;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;16;GaussianBlur;2;16;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;17;GaussianBlur;2;17;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;18;GaussianBlur;2;18;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;19;GaussianBlur;2;19;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;20;GaussianBlur;2;20;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;21;GaussianBlur;2;21;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;22;GaussianBlur;2;22;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;23;GaussianBlur;2;23;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;24;GaussianBlur;2;24;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;25;GaussianBlur;2;25;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;26;GaussianBlur;2;26;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;27;GaussianBlur;2;27;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;28;GaussianBlur;2;28;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;29;GaussianBlur;2;29;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Amplitude;30;GaussianBlur;2;30;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;0;GaussianBlur;2;6;0;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;1;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+Otsu;2;GaussianBlur;2;6;2;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;3;GaussianBlur;2;6;3;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;4;GaussianBlur;2;6;4;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;5;GaussianBlur;2;6;5;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;6;GaussianBlur;2;6;6;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;7;GaussianBlur;2;6;7;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;8;GaussianBlur;2;6;8;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;9;GaussianBlur;2;6;9;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;10;GaussianBlur;2;6;10;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;11;GaussianBlur;2;6;11;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;12;GaussianBlur;2;6;12;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;13;GaussianBlur;2;6;13;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;14;GaussianBlur;2;6;14;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;15;GaussianBlur;2;6;15;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;16;GaussianBlur;2;6;16;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;17;GaussianBlur;2;6;17;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;18;GaussianBlur;2;6;18;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;19;GaussianBlur;2;6;19;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;20;GaussianBlur;2;6;20;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;21;GaussianBlur;2;6;21;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;22;GaussianBlur;2;6;22;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;23;GaussianBlur;2;6;23;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;24;GaussianBlur;2;6;24;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;25;GaussianBlur;2;6;25;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;26;GaussianBlur;2;6;26;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;27;GaussianBlur;2;6;27;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;28;GaussianBlur;2;6;28;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;29;GaussianBlur;2;6;29;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Otsu;30;GaussianBlur;2;6;30;4;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+IS Connexity;4;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+IS Connexity;8;GaussianBlur;2;6;1;8;5;5;1;0.7;10;0.8;0.1;5;0.9;NO
+IS Min Size;0;GaussianBlur;2;6;1;4;0;5;1;0.7;10;0.8;0.1;5;0.9;NO
+IS Min Size;5;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+IS Min Size;10;GaussianBlur;2;6;1;4;10;5;1;0.7;10;0.8;0.1;5;0.9;NO
+IS Min Size;15;GaussianBlur;2;6;1;4;15;5;1;0.7;10;0.8;0.1;5;0.9;NO
+IS Min Size;20;GaussianBlur;2;6;1;4;20;5;1;0.7;10;0.8;0.1;5;0.9;NO
+IS Min Size;25;GaussianBlur;2;6;1;4;25;5;1;0.7;10;0.8;0.1;5;0.9;NO
+IS Min Size;30;GaussianBlur;2;6;1;4;30;5;1;0.7;10;0.8;0.1;5;0.9;NO
+IS Min Size;35;GaussianBlur;2;6;1;4;35;5;1;0.7;10;0.8;0.1;5;0.9;NO
+IS Min Size;40;GaussianBlur;2;6;1;4;40;5;1;0.7;10;0.8;0.1;5;0.9;NO
+IS Min Size;45;GaussianBlur;2;6;1;4;45;5;1;0.7;10;0.8;0.1;5;0.9;NO
+IS Min Size;50;GaussianBlur;2;6;1;4;50;5;1;0.7;10;0.8;0.1;5;0.9;NO
+Blur XY;0;GaussianBlur;2;6;1;4;5;0;1;0.7;10;0.8;0.1;5;0.9;NO
+Blur XY;1;GaussianBlur;2;6;1;4;5;1;1;0.7;10;0.8;0.1;5;0.9;NO
+Blur XY;2;GaussianBlur;2;6;1;4;5;2;1;0.7;10;0.8;0.1;5;0.9;NO
+Blur XY;3;GaussianBlur;2;6;1;4;5;3;1;0.7;10;0.8;0.1;5;0.9;NO
+Blur XY;4;GaussianBlur;2;6;1;4;5;4;1;0.7;10;0.8;0.1;5;0.9;NO
+Blur XY;5;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+Blur XY;6;GaussianBlur;2;6;1;4;5;6;1;0.7;10;0.8;0.1;5;0.9;NO
+Blur XY;7;GaussianBlur;2;6;1;4;5;7;1;0.7;10;0.8;0.1;5;0.9;NO
+Blur XY;8;GaussianBlur;2;6;1;4;5;8;1;0.7;10;0.8;0.1;5;0.9;NO
+Blur XY;9;GaussianBlur;2;6;1;4;5;9;1;0.7;10;0.8;0.1;5;0.9;NO
+Blur XY;10;GaussianBlur;2;6;1;4;5;10;1;0.7;10;0.8;0.1;5;0.9;NO
+Blur Z;0;GaussianBlur;2;6;1;4;5;5;0;0.7;10;0.8;0.1;5;0.9;NO
+Blur Z;1;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+Blur Z;2;GaussianBlur;2;6;1;4;5;5;2;0.7;10;0.8;0.1;5;0.9;NO
+Blur Z;3;GaussianBlur;2;6;1;4;5;5;3;0.7;10;0.8;0.1;5;0.9;NO
+Blur Z;4;GaussianBlur;2;6;1;4;5;5;4;0.7;10;0.8;0.1;5;0.9;NO
+Blur Z;5;GaussianBlur;2;6;1;4;5;5;5;0.7;10;0.8;0.1;5;0.9;NO
+Blur Z;6;GaussianBlur;2;6;1;4;5;5;6;0.7;10;0.8;0.1;5;0.9;NO
+Blur Z;7;GaussianBlur;2;6;1;4;5;5;7;0.7;10;0.8;0.1;5;0.9;NO
+Blur Z;8;GaussianBlur;2;6;1;4;5;5;8;0.7;10;0.8;0.1;5;0.9;NO
+Blur Z;9;GaussianBlur;2;6;1;4;5;5;9;0.7;10;0.8;0.1;5;0.9;NO
+Blur Z;10;GaussianBlur;2;6;1;4;5;5;10;0.7;10;0.8;0.1;5;0.9;NO
+ST_1;0.0;GaussianBlur;2;6;1;4;5;5;1;0.0;10;0.8;0.1;5;0.9;NO
+ST_1;0.1;GaussianBlur;2;6;1;4;5;5;1;0.1;10;0.8;0.1;5;0.9;NO
+ST_1;0.2;GaussianBlur;2;6;1;4;5;5;1;0.2;10;0.8;0.1;5;0.9;NO
+ST_1;0.3;GaussianBlur;2;6;1;4;5;5;1;0.3;10;0.8;0.1;5;0.9;NO
+ST_1;0.4;GaussianBlur;2;6;1;4;5;5;1;0.4;10;0.8;0.1;5;0.9;NO
+ST_1;0.5;GaussianBlur;2;6;1;4;5;5;1;0.5;10;0.8;0.1;5;0.9;NO
+ST_1;0.6;GaussianBlur;2;6;1;4;5;5;1;0.6;10;0.8;0.1;5;0.9;NO
+ST_1;0.7;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+ST_1;0.8;GaussianBlur;2;6;1;4;5;5;1;0.8;10;0.8;0.1;5;0.9;NO
+ST_1;0.9;GaussianBlur;2;6;1;4;5;5;1;0.9;10;0.8;0.1;5;0.9;NO
+ST_1;1.0;GaussianBlur;2;6;1;4;5;5;1;1.0;10;0.8;0.1;5;0.9;NO
+Overlap_1;0;GaussianBlur;2;6;1;4;5;5;1;0.7;0;0.8;0.1;5;0.9;NO
+Overlap_1;5;GaussianBlur;2;6;1;4;5;5;1;0.7;5;0.8;0.1;5;0.9;NO
+Overlap_1;10;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+Overlap_1;15;GaussianBlur;2;6;1;4;5;5;1;0.7;15;0.8;0.1;5;0.9;NO
+Overlap_1;17;GaussianBlur;2;6;1;4;5;5;1;0.7;17;0.8;0.1;5;0.9;NO
+Overlap_1;20;GaussianBlur;2;6;1;4;5;5;1;0.7;20;0.8;0.1;5;0.9;NO
+Overlap_1;25;GaussianBlur;2;6;1;4;5;5;1;0.7;25;0.8;0.1;5;0.9;NO
+Overlap_1;30;GaussianBlur;2;6;1;4;5;5;1;0.7;30;0.8;0.1;5;0.9;NO
+Overlap_1;35;GaussianBlur;2;6;1;4;5;5;1;0.7;35;0.8;0.1;5;0.9;NO
+Overlap_1;40;GaussianBlur;2;6;1;4;5;5;1;0.7;40;0.8;0.1;5;0.9;NO
+Overlap_1;45;GaussianBlur;2;6;1;4;5;5;1;0.7;45;0.8;0.1;5;0.9;NO
+Overlap_1;50;GaussianBlur;2;6;1;4;5;5;1;0.7;50;0.8;0.1;5;0.9;NO
+CR_1;0.5;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.5;0.1;5;0.9;NO
+CR_1;0.55;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.55;0.1;5;0.9;NO
+CR_1;0.6;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.6;0.1;5;0.9;NO
+CR_1;0.65;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.65;0.1;5;0.9;NO
+CR_1;0.7;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.7;0.1;5;0.9;NO
+CR_1;0.75;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.75;0.1;5;0.9;NO
+CR_1;0.8;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+CR_1;0.85;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.85;0.1;5;0.9;NO
+CR_1;0.9;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.9;0.1;5;0.9;NO
+CR_1;0.95;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.95;0.1;5;0.9;NO
+CR_1;1;GaussianBlur;2;6;1;4;5;5;1;0.7;10;1;0.1;5;0.9;NO
+ST_2;0.0;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.0;5;0.9;NO
+ST_2;0.1;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+ST_2;0.2;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.2;5;0.9;NO
+ST_2;0.3;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.3;5;0.9;NO
+ST_2;0.4;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.4;5;0.9;NO
+ST_2;0.5;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.5;5;0.9;NO
+ST_2;0.6;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.6;5;0.9;NO
+ST_2;0.7;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.7;5;0.9;NO
+ST_2;0.8;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.8;5;0.9;NO
+ST_2;0.9;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.9;5;0.9;NO
+ST_2;1.0;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;1.0;5;0.9;NO
+Overlap_2;0;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;0;0.9;NO
+Overlap_2;5;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+Overlap_2;10;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;10;0.9;NO
+Overlap_2;15;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;15;0.9;NO
+Overlap_2;20;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;20;0.9;NO
+Overlap_2;25;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;25;0.9;NO
+Overlap_2;30;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;30;0.9;NO
+Overlap_2;35;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;35;0.9;NO
+Overlap_2;40;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;40;0.9;NO
+Overlap_2;45;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;45;0.9;NO
+Overlap_2;50;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;50;0.9;NO
+CR_2;0.5;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.5;NO
+CR_2;0.55;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.55;NO
+CR_2;0.6;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.6;NO
+CR_2;0.65;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.65;NO
+CR_2;0.7;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.7;NO
+CR_2;0.75;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.75;NO
+CR_2;0.8;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.8;NO
+CR_2;0.85;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.85;NO
+CR_2;0.9;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.9;YES
+CR_2;0.95;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;0.95;NO
+CR_2;1;GaussianBlur;2;6;1;4;5;5;1;0.7;10;0.8;0.1;5;1;NO
diff --git a/src/test/resources/Mouche_c01_f0001_p013/Ground truth Height map_3.tif b/src/test/resources/Mouche_c01_f0001_p013/Ground truth Height map_3.tif
deleted file mode 100644
index acf79178f75a795c33c5f8d4f2c5822ffdca8048..0000000000000000000000000000000000000000
Binary files a/src/test/resources/Mouche_c01_f0001_p013/Ground truth Height map_3.tif and /dev/null differ
diff --git a/src/test/resources/Mouche_c01_f0001_p013/Ground truth Height map_4.tif b/src/test/resources/Mouche_c01_f0001_p013/Ground truth Height map_4.tif
deleted file mode 100644
index c82952b11d718be33e0fa731173c7599216d08da..0000000000000000000000000000000000000000
Binary files a/src/test/resources/Mouche_c01_f0001_p013/Ground truth Height map_4.tif and /dev/null differ
diff --git a/src/test/resources/Mouche_c01_f0001_p013/Mouche_c01_f0001_p013_SweepSelection.csv b/src/test/resources/Mouche_c01_f0001_p013/Mouche_c01_f0001_p013_SweepSelection.csv
deleted file mode 100644
index d266d749a1cc68976486c5ecd359c6aa78c39b7c..0000000000000000000000000000000000000000
--- a/src/test/resources/Mouche_c01_f0001_p013/Mouche_c01_f0001_p013_SweepSelection.csv
+++ /dev/null
@@ -1,48 +0,0 @@
-;;GaussianBlur;2;0.8;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;
-AmplitudeThreshold;0;GaussianBlur;2;0;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.1;GaussianBlur;2;0.1;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;GaussianBlur;2;0.2;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;GaussianBlur;2;0.3;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;GaussianBlur;2;0.4;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;GaussianBlur;2;0.5;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;GaussianBlur;2;0.6;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;GaussianBlur;2;0.7;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.8;GaussianBlur;2;0.8;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;YES
-AmplitudeThreshold;0.9;GaussianBlur;2;0.9;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;GaussianBlur;2;1;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-Otsu Threshold;0;GaussianBlur;2;0.8;0;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-Otsu Threshold;0.1;GaussianBlur;2;0.8;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;YES
-Otsu Threshold;0.2;GaussianBlur;2;0.8;0.2;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-Otsu Threshold;0.3;GaussianBlur;2;0.8;0.3;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-Otsu Threshold;0.4;GaussianBlur;2;0.8;0.4;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-Otsu Threshold;0.5;GaussianBlur;2;0.8;0.5;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-Otsu Threshold;0.6;GaussianBlur;2;0.8;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-Otsu Threshold;0.7;GaussianBlur;2;0.8;0.7;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-Otsu Threshold;0.8;GaussianBlur;2;0.8;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-Otsu Threshold;0.9;GaussianBlur;2;0.8;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-Otsu Threshold;1;GaussianBlur;2;0.8;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-IS Connexity;4;GaussianBlur;2;0.8;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;YES
-IS Connexity;8;GaussianBlur;2;0.8;0.1;8;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-IS Min Size;0;GaussianBlur;2;0.8;0.1;4;0;4;1;0.75;10;0.8;0.1;10;0.9;NO
-IS Min Size;5;GaussianBlur;2;0.8;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;YES
-IS Min Size;10;GaussianBlur;2;0.8;0.1;4;10;4;1;0.75;10;0.8;0.1;10;0.9;NO
-IS Min Size;15;GaussianBlur;2;0.8;0.1;4;15;4;1;0.75;10;0.8;0.1;10;0.9;NO
-IS Min Size;20;GaussianBlur;2;0.8;0.1;4;20;4;1;0.75;10;0.8;0.1;10;0.9;NO
-IS Min Size;25;GaussianBlur;2;0.8;0.1;4;25;4;1;0.75;10;0.8;0.1;10;0.9;NO
-IS Min Size;30;GaussianBlur;2;0.8;0.1;4;30;4;1;0.75;10;0.8;0.1;10;0.9;NO
-IS Min Size;35;GaussianBlur;2;0.8;0.1;4;35;4;1;0.75;10;0.8;0.1;10;0.9;NO
-IS Min Size;40;GaussianBlur;2;0.8;0.1;4;40;4;1;0.75;10;0.8;0.1;10;0.9;NO
-IS Min Size;45;GaussianBlur;2;0.8;0.1;4;45;4;1;0.75;10;0.8;0.1;10;0.9;NO
-IS Min Size;50;GaussianBlur;2;0.8;0.1;4;50;4;1;0.75;10;0.8;0.1;10;0.9;NO
-Blur XY;0;GaussianBlur;2;0.8;0.1;4;5;0;1;0.75;10;0.8;0.1;10;0.9;NO
-Blur XY;1;GaussianBlur;2;0.8;0.1;4;5;1;1;0.75;10;0.8;0.1;10;0.9;NO
-Blur XY;2;GaussianBlur;2;0.8;0.1;4;5;2;1;0.75;10;0.8;0.1;10;0.9;NO
-Blur XY;3;GaussianBlur;2;0.8;0.1;4;5;3;1;0.75;10;0.8;0.1;10;0.9;NO
-Blur XY;4;GaussianBlur;2;0.8;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;YES
-Blur XY;5;GaussianBlur;2;0.8;0.1;4;5;5;1;0.75;10;0.8;0.1;10;0.9;NO
-BlurZ;0;GaussianBlur;2;0.8;0.1;4;5;4;0;0.75;10;0.8;0.1;10;0.9;NO
-BlurZ;1;GaussianBlur;2;0.8;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;YES
-BlurZ;2;GaussianBlur;2;0.8;0.1;4;5;4;2;0.75;10;0.8;0.1;10;0.9;NO
-BlurZ;3;GaussianBlur;2;0.8;0.1;4;5;4;3;0.75;10;0.8;0.1;10;0.9;NO
-BlurZ;4;GaussianBlur;2;0.8;0.1;4;5;4;4;0.75;10;0.8;0.1;10;0.9;NO
-BlurZ;5;GaussianBlur;2;0.8;0.1;4;5;4;5;0.75;10;0.8;0.1;10;0.9;NO
diff --git a/src/test/resources/Mouche_c01_f0001_p013/Mouche_c01_f0001_p013_SweepThreshold.csv b/src/test/resources/Mouche_c01_f0001_p013/Mouche_c01_f0001_p013_SweepThreshold.csv
deleted file mode 100644
index 3752dc8e3287496ef9c9464b87598cec54ff35bb..0000000000000000000000000000000000000000
--- a/src/test/resources/Mouche_c01_f0001_p013/Mouche_c01_f0001_p013_SweepThreshold.csv
+++ /dev/null
@@ -1,120 +0,0 @@
-;;;;GaussianBlur;2;0.8;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;
-AmplitudeThreshold;0;Otsu Threshold;0.1;GaussianBlur;2;0;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0;Otsu Threshold;0.2;GaussianBlur;2;0;0.2;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0;Otsu Threshold;0.3;GaussianBlur;2;0;0.3;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0;Otsu Threshold;0.4;GaussianBlur;2;0;0.4;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0;Otsu Threshold;0.5;GaussianBlur;2;0;0.5;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0;Otsu Threshold;0.6;GaussianBlur;2;0;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0;Otsu Threshold;0.7;GaussianBlur;2;0;0.7;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0;Otsu Threshold;0.8;GaussianBlur;2;0;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0;Otsu Threshold;0.9;GaussianBlur;2;0;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0;Otsu Threshold;1;GaussianBlur;2;0;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.1;Otsu Threshold;0.1;GaussianBlur;2;0.1;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.1;Otsu Threshold;0.2;GaussianBlur;2;0.1;0.2;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.1;Otsu Threshold;0.3;GaussianBlur;2;0.1;0.3;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.1;Otsu Threshold;0.4;GaussianBlur;2;0.1;0.4;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.1;Otsu Threshold;0.5;GaussianBlur;2;0.1;0.5;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.1;Otsu Threshold;0.6;GaussianBlur;2;0.1;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.1;Otsu Threshold;0.7;GaussianBlur;2;0.1;0.7;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.1;Otsu Threshold;0.8;GaussianBlur;2;0.1;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.1;Otsu Threshold;0.9;GaussianBlur;2;0.1;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.1;Otsu Threshold;1;GaussianBlur;2;0.1;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;Otsu Threshold;0;GaussianBlur;2;0.2;0;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;Otsu Threshold;0.1;GaussianBlur;2;0.2;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;Otsu Threshold;0.2;GaussianBlur;2;0.2;0.2;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;Otsu Threshold;0.3;GaussianBlur;2;0.2;0.3;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;Otsu Threshold;0.4;GaussianBlur;2;0.2;0.4;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;Otsu Threshold;0.5;GaussianBlur;2;0.2;0.5;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;Otsu Threshold;0.6;GaussianBlur;2;0.2;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;Otsu Threshold;0.7;GaussianBlur;2;0.2;0.7;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;Otsu Threshold;0.8;GaussianBlur;2;0.2;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;Otsu Threshold;0.9;GaussianBlur;2;0.2;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.2;Otsu Threshold;1;GaussianBlur;2;0.2;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;Otsu Threshold;0;GaussianBlur;2;0.3;0;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;Otsu Threshold;0.1;GaussianBlur;2;0.3;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;Otsu Threshold;0.2;GaussianBlur;2;0.3;0.2;4;5;0;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;Otsu Threshold;0.3;GaussianBlur;2;0.3;0.3;4;5;1;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;Otsu Threshold;0.4;GaussianBlur;2;0.3;0.4;4;5;2;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;Otsu Threshold;0.5;GaussianBlur;2;0.3;0.5;4;5;3;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;Otsu Threshold;0.6;GaussianBlur;2;0.3;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;Otsu Threshold;0.7;GaussianBlur;2;0.3;0.7;4;5;5;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;Otsu Threshold;0.8;GaussianBlur;2;0.3;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;Otsu Threshold;0.9;GaussianBlur;2;0.3;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.3;Otsu Threshold;1;GaussianBlur;2;0.3;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;Otsu Threshold;0;GaussianBlur;2;0.4;0;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;Otsu Threshold;0.1;GaussianBlur;2;0.4;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;Otsu Threshold;0.2;GaussianBlur;2;0.4;0.2;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;Otsu Threshold;0.3;GaussianBlur;2;0.4;0.3;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;Otsu Threshold;0.4;GaussianBlur;2;0.4;0.4;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;Otsu Threshold;0.5;GaussianBlur;2;0.4;0.5;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;Otsu Threshold;0.6;GaussianBlur;2;0.4;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;Otsu Threshold;0.7;GaussianBlur;2;0.4;0.7;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;Otsu Threshold;0.8;GaussianBlur;2;0.4;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;Otsu Threshold;0.9;GaussianBlur;2;0.4;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.4;Otsu Threshold;1;GaussianBlur;2;0.4;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;Otsu Threshold;0;GaussianBlur;2;0.5;0;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;Otsu Threshold;0.1;GaussianBlur;2;0.5;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;Otsu Threshold;0.2;GaussianBlur;2;0.5;0.2;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;Otsu Threshold;0.3;GaussianBlur;2;0.5;0.3;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;Otsu Threshold;0.4;GaussianBlur;2;0.5;0.4;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;Otsu Threshold;0.5;GaussianBlur;2;0.5;0.5;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;Otsu Threshold;0.6;GaussianBlur;2;0.5;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;Otsu Threshold;0.7;GaussianBlur;2;0.5;0.7;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;Otsu Threshold;0.8;GaussianBlur;2;0.5;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;Otsu Threshold;0.9;GaussianBlur;2;0.5;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.5;Otsu Threshold;1;GaussianBlur;2;0.5;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;Otsu Threshold;0;GaussianBlur;2;0.6;0;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;Otsu Threshold;0.1;GaussianBlur;2;0.6;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;Otsu Threshold;0.2;GaussianBlur;2;0.6;0.2;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;Otsu Threshold;0.3;GaussianBlur;2;0.6;0.3;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;Otsu Threshold;0.4;GaussianBlur;2;0.6;0.4;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;Otsu Threshold;0.5;GaussianBlur;2;0.6;0.5;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;Otsu Threshold;0.6;GaussianBlur;2;0.6;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;Otsu Threshold;0.7;GaussianBlur;2;0.6;0.7;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;Otsu Threshold;0.8;GaussianBlur;2;0.6;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;Otsu Threshold;0.9;GaussianBlur;2;0.6;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.6;Otsu Threshold;1;GaussianBlur;2;0.6;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;Otsu Threshold;0;GaussianBlur;2;0.7;0;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;Otsu Threshold;0.1;GaussianBlur;2;0.7;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;Otsu Threshold;0.2;GaussianBlur;2;0.7;0.2;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;Otsu Threshold;0.3;GaussianBlur;2;0.7;0.3;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;Otsu Threshold;0.4;GaussianBlur;2;0.7;0.4;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;Otsu Threshold;0.5;GaussianBlur;2;0.7;0.5;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;Otsu Threshold;0.6;GaussianBlur;2;0.7;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;Otsu Threshold;0.7;GaussianBlur;2;0.7;0.7;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;Otsu Threshold;0.8;GaussianBlur;2;0.7;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;Otsu Threshold;0.9;GaussianBlur;2;0.7;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.7;Otsu Threshold;1;GaussianBlur;2;0.7;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.8;Otsu Threshold;0;GaussianBlur;2;0.8;0;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.8;Otsu Threshold;0.1;GaussianBlur;2;0.8;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;YES
-AmplitudeThreshold;0.8;Otsu Threshold;0.2;GaussianBlur;2;0.8;0.2;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.8;Otsu Threshold;0.3;GaussianBlur;2;0.8;0.3;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.8;Otsu Threshold;0.4;GaussianBlur;2;0.8;0.4;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.8;Otsu Threshold;0.5;GaussianBlur;2;0.8;0.5;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.8;Otsu Threshold;0.6;GaussianBlur;2;0.8;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.8;Otsu Threshold;0.7;GaussianBlur;2;0.8;0.7;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.8;Otsu Threshold;0.8;GaussianBlur;2;0.8;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.8;Otsu Threshold;0.9;GaussianBlur;2;0.8;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.8;Otsu Threshold;1;GaussianBlur;2;0.8;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.9;Otsu Threshold;0;GaussianBlur;2;0.9;0;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.9;Otsu Threshold;0.1;GaussianBlur;2;0.9;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.9;Otsu Threshold;0.2;GaussianBlur;2;0.9;0.2;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.9;Otsu Threshold;0.3;GaussianBlur;2;0.9;0.3;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.9;Otsu Threshold;0.4;GaussianBlur;2;0.9;0.4;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.9;Otsu Threshold;0.5;GaussianBlur;2;0.9;0.5;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.9;Otsu Threshold;0.6;GaussianBlur;2;0.9;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.9;Otsu Threshold;0.7;GaussianBlur;2;0.9;0.7;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.9;Otsu Threshold;0.8;GaussianBlur;2;0.9;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.9;Otsu Threshold;0.9;GaussianBlur;2;0.9;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;0.9;Otsu Threshold;1;GaussianBlur;2;0.9;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;Otsu Threshold;0;GaussianBlur;2;1;0;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;Otsu Threshold;0.1;GaussianBlur;2;1;0.1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;Otsu Threshold;0.2;GaussianBlur;2;1;0.2;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;Otsu Threshold;0.3;GaussianBlur;2;1;0.3;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;Otsu Threshold;0.4;GaussianBlur;2;1;0.4;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;Otsu Threshold;0.5;GaussianBlur;2;1;0.5;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;Otsu Threshold;0.6;GaussianBlur;2;1;0.6;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;Otsu Threshold;0.7;GaussianBlur;2;1;0.7;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;Otsu Threshold;0.8;GaussianBlur;2;1;0.8;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;Otsu Threshold;0.9;GaussianBlur;2;1;0.9;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
-AmplitudeThreshold;1;Otsu Threshold;1;GaussianBlur;2;1;1;4;5;4;1;0.75;10;0.8;0.1;10;0.9;NO
diff --git a/src/test/resources/Mouche_c01_f0001_p013/ParameterSweep_Mouche_13.csv b/src/test/resources/Mouche_c01_f0001_p013/ParameterSweep_Mouche_13.csv
deleted file mode 100644
index 0faeaeb7ea490fef211d49dea28475b1d2caa1f6..0000000000000000000000000000000000000000
--- a/src/test/resources/Mouche_c01_f0001_p013/ParameterSweep_Mouche_13.csv
+++ /dev/null
@@ -1,124 +0,0 @@
-;;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;
-Amplitude;0.0;GaussianBlur;2;0.0;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Amplitude;0.1;GaussianBlur;2;0.1;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Amplitude;0.2;GaussianBlur;2;0.2;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Amplitude;0.3;GaussianBlur;2;0.3;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Amplitude;0.4;GaussianBlur;2;0.4;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Amplitude;0.5;GaussianBlur;2;0.5;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Amplitude;0.6;GaussianBlur;2;0.6;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Amplitude;0.7;GaussianBlur;2;0.7;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Amplitude;0.8;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-Amplitude;0.9;GaussianBlur;2;0.9;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Amplitude;1.0;GaussianBlur;2;1.0;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Otsu;0.0;GaussianBlur;2;0.8;0.0;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Otsu;0.1;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-Otsu;0.2;GaussianBlur;2;0.8;0.2;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Otsu;0.3;GaussianBlur;2;0.8;0.3;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Otsu;0.4;GaussianBlur;2;0.8;0.4;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Otsu;0.5;GaussianBlur;2;0.8;0.5;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Otsu;0.6;GaussianBlur;2;0.8;0.6;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Otsu;0.7;GaussianBlur;2;0.8;0.7;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Otsu;0.8;GaussianBlur;2;0.8;0.8;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Otsu;0.9;GaussianBlur;2;0.8;0.9;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Otsu;1.0;GaussianBlur;2;0.8;1.0;4;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-IS Connexity;4;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-IS Connexity;8;GaussianBlur;2;0.8;0.1;8;10;4;1;0.7;10;0.8;0.1;10;0.9;NO
-IS Min Size;0;GaussianBlur;2;0.8;0.1;4;0;4;1;0.7;10;0.8;0.1;10;0.9;NO
-IS Min Size;5;GaussianBlur;2;0.8;0.1;4;5;4;1;0.7;10;0.8;0.1;10;0.9;NO
-IS Min Size;10;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-IS Min Size;15;GaussianBlur;2;0.8;0.1;4;15;4;1;0.7;10;0.8;0.1;10;0.9;NO
-IS Min Size;20;GaussianBlur;2;0.8;0.1;4;20;4;1;0.7;10;0.8;0.1;10;0.9;NO
-IS Min Size;25;GaussianBlur;2;0.8;0.1;4;25;4;1;0.7;10;0.8;0.1;10;0.9;NO
-IS Min Size;30;GaussianBlur;2;0.8;0.1;4;30;4;1;0.7;10;0.8;0.1;10;0.9;NO
-IS Min Size;35;GaussianBlur;2;0.8;0.1;4;35;4;1;0.7;10;0.8;0.1;10;0.9;NO
-IS Min Size;40;GaussianBlur;2;0.8;0.1;4;40;4;1;0.7;10;0.8;0.1;10;0.9;NO
-IS Min Size;45;GaussianBlur;2;0.8;0.1;4;45;4;1;0.7;10;0.8;0.1;10;0.9;NO
-IS Min Size;50;GaussianBlur;2;0.8;0.1;4;50;4;1;0.7;10;0.8;0.1;10;0.9;NO
-Blur XY;0;GaussianBlur;2;0.8;0.1;4;10;0;1;0.7;10;0.8;0.1;10;0.9;NO
-Blur XY;1;GaussianBlur;2;0.8;0.1;4;10;1;1;0.7;10;0.8;0.1;10;0.9;NO
-Blur XY;2;GaussianBlur;2;0.8;0.1;4;10;2;1;0.7;10;0.8;0.1;10;0.9;NO
-Blur XY;3;GaussianBlur;2;0.8;0.1;4;10;3;1;0.7;10;0.8;0.1;10;0.9;NO
-Blur XY;4;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-Blur XY;5;GaussianBlur;2;0.8;0.1;4;10;5;1;0.7;10;0.8;0.1;10;0.9;NO
-Blur XY;6;GaussianBlur;2;0.8;0.1;4;10;6;1;0.7;10;0.8;0.1;10;0.9;NO
-Blur XY;7;GaussianBlur;2;0.8;0.1;4;10;7;1;0.7;10;0.8;0.1;10;0.9;NO
-Blur XY;8;GaussianBlur;2;0.8;0.1;4;10;8;1;0.7;10;0.8;0.1;10;0.9;NO
-Blur XY;9;GaussianBlur;2;0.8;0.1;4;10;9;1;0.7;10;0.8;0.1;10;0.9;NO
-Blur XY;10;GaussianBlur;2;0.8;0.1;4;10;10;1;0.7;10;0.8;0.1;10;0.9;NO
-Blur Z;0;GaussianBlur;2;0.8;0.1;4;10;4;0;0.7;10;0.8;0.1;10;0.9;NO
-Blur Z;1;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-Blur Z;2;GaussianBlur;2;0.8;0.1;4;10;4;2;0.7;10;0.8;0.1;10;0.9;NO
-Blur Z;3;GaussianBlur;2;0.8;0.1;4;10;4;3;0.7;10;0.8;0.1;10;0.9;NO
-Blur Z;4;GaussianBlur;2;0.8;0.1;4;10;4;4;0.7;10;0.8;0.1;10;0.9;NO
-Blur Z;5;GaussianBlur;2;0.8;0.1;4;10;4;5;0.7;10;0.8;0.1;10;0.9;NO
-Blur Z;6;GaussianBlur;2;0.8;0.1;4;10;4;6;0.7;10;0.8;0.1;10;0.9;NO
-Blur Z;7;GaussianBlur;2;0.8;0.1;4;10;4;7;0.7;10;0.8;0.1;10;0.9;NO
-Blur Z;8;GaussianBlur;2;0.8;0.1;4;10;4;8;0.7;10;0.8;0.1;10;0.9;NO
-Blur Z;9;GaussianBlur;2;0.8;0.1;4;10;4;9;0.7;10;0.8;0.1;10;0.9;NO
-Blur Z;10;GaussianBlur;2;0.8;0.1;4;10;4;10;0.7;10;0.8;0.1;10;0.9;NO
-ST_1;0.0;GaussianBlur;2;0.8;0.1;4;10;4;1;0.0;10;0.8;0.1;10;0.9;NO
-ST_1;0.1;GaussianBlur;2;0.8;0.1;4;10;4;1;0.1;10;0.8;0.1;10;0.9;NO
-ST_1;0.2;GaussianBlur;2;0.8;0.1;4;10;4;1;0.2;10;0.8;0.1;10;0.9;NO
-ST_1;0.3;GaussianBlur;2;0.8;0.1;4;10;4;1;0.3;10;0.8;0.1;10;0.9;NO
-ST_1;0.4;GaussianBlur;2;0.8;0.1;4;10;4;1;0.4;10;0.8;0.1;10;0.9;NO
-ST_1;0.5;GaussianBlur;2;0.8;0.1;4;10;4;1;0.5;10;0.8;0.1;10;0.9;NO
-ST_1;0.6;GaussianBlur;2;0.8;0.1;4;10;4;1;0.6;10;0.8;0.1;10;0.9;NO
-ST_1;0.7;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-ST_1;0.8;GaussianBlur;2;0.8;0.1;4;10;4;1;0.8;10;0.8;0.1;10;0.9;NO
-ST_1;0.9;GaussianBlur;2;0.8;0.1;4;10;4;1;0.9;10;0.8;0.1;10;0.9;NO
-ST_1;1.0;GaussianBlur;2;0.8;0.1;4;10;4;1;1.0;10;0.8;0.1;10;0.9;NO
-Overlap_1;0;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;0;0.8;0.1;10;0.9;NO
-Overlap_1;5;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;5;0.8;0.1;10;0.9;NO
-Overlap_1;10;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-Overlap_1;15;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;15;0.8;0.1;10;0.9;NO
-Overlap_1;20;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;20;0.8;0.1;10;0.9;NO
-Overlap_1;25;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;25;0.8;0.1;10;0.9;NO
-Overlap_1;30;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;30;0.8;0.1;10;0.9;NO
-Overlap_1;35;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;35;0.8;0.1;10;0.9;NO
-Overlap_1;40;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;40;0.8;0.1;10;0.9;NO
-Overlap_1;45;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;45;0.8;0.1;10;0.9;NO
-Overlap_1;50;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;50;0.8;0.1;10;0.9;NO
-CR_1;0.5;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.5;0.1;10;0.9;NO
-CR_1;0.55;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.55;0.1;10;0.9;NO
-CR_1;0.6;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.6;0.1;10;0.9;NO
-CR_1;0.65;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.65;0.1;10;0.9;NO
-CR_1;0.7;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.7;0.1;10;0.9;NO
-CR_1;0.75;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.75;0.1;10;0.9;NO
-CR_1;0.8;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-CR_1;0.85;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.85;0.1;10;0.9;NO
-CR_1;0.9;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.9;0.1;10;0.9;NO
-CR_1;0.95;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.95;0.1;10;0.9;NO
-CR_1;1;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;1;0.1;10;0.9;NO
-ST_2;0.0;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.0;10;0.9;NO
-ST_2;0.1;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-ST_2;0.2;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.2;10;0.9;NO
-ST_2;0.3;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.3;10;0.9;NO
-ST_2;0.4;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.4;10;0.9;NO
-ST_2;0.5;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.5;10;0.9;NO
-ST_2;0.6;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.6;10;0.9;NO
-ST_2;0.7;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.7;10;0.9;NO
-ST_2;0.8;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.8;10;0.9;NO
-ST_2;0.9;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.9;10;0.9;NO
-ST_2;1.0;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;1.0;10;0.9;NO
-Overlap_2;0;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;0;0.9;NO
-Overlap_2;5;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;5;0.9;NO
-Overlap_2;10;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-Overlap_2;15;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;15;0.9;NO
-Overlap_2;20;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;20;0.9;NO
-Overlap_2;25;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;25;0.9;NO
-Overlap_2;30;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;30;0.9;NO
-Overlap_2;35;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;35;0.9;NO
-Overlap_2;40;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;40;0.9;NO
-Overlap_2;45;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;45;0.9;NO
-Overlap_2;50;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;50;0.9;NO
-CR_2;0.5;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.5;NO
-CR_2;0.55;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.55;NO
-CR_2;0.6;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.6;NO
-CR_2;0.65;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.65;NO
-CR_2;0.7;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.7;NO
-CR_2;0.75;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.75;NO
-CR_2;0.8;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.8;NO
-CR_2;0.85;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.85;NO
-CR_2;0.9;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.9;YES
-CR_2;0.95;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;0.95;NO
-CR_2;1;GaussianBlur;2;0.8;0.1;4;10;4;1;0.7;10;0.8;0.1;10;1;NO
diff --git a/src/test/resources/Mouche_c01_f0001_p013/STK_Mouche_c01_f0001_p013.tif b/src/test/resources/Mouche_c01_f0001_p013/STK_Mouche_c01_f0001_p013.tif
deleted file mode 100644
index 32c9cfa57fcdf0da7ffd43d2151a0ece9dc65b2e..0000000000000000000000000000000000000000
Binary files a/src/test/resources/Mouche_c01_f0001_p013/STK_Mouche_c01_f0001_p013.tif and /dev/null differ
diff --git a/src/test/resources/Organoid/HM1.tif b/src/test/resources/Organoid/HM1.tif
new file mode 100644
index 0000000000000000000000000000000000000000..4ce5204c3b5db2dc2ff96d866caaedc4e7042197
Binary files /dev/null and b/src/test/resources/Organoid/HM1.tif differ
diff --git a/src/test/resources/Organoid/HM2.tif b/src/test/resources/Organoid/HM2.tif
new file mode 100644
index 0000000000000000000000000000000000000000..52801e3d4a0299d658edc0e0e852bd0136a9c5a6
Binary files /dev/null and b/src/test/resources/Organoid/HM2.tif differ
diff --git a/src/test/resources/Organoid/Organoid_PS.csv b/src/test/resources/Organoid/Organoid_PS.csv
new file mode 100644
index 0000000000000000000000000000000000000000..f24014c0bb6f1f588b03698c71770e2b490a6486
--- /dev/null
+++ b/src/test/resources/Organoid/Organoid_PS.csv
@@ -0,0 +1,165 @@
+Organoid;;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;
+Amplitude;0;GaussianBlur;2;0;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;1;GaussianBlur;2;1;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;2;GaussianBlur;2;2;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;3;GaussianBlur;2;3;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;4;GaussianBlur;2;4;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;5;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+Amplitude;6;GaussianBlur;2;6;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;7;GaussianBlur;2;7;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;8;GaussianBlur;2;8;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;9;GaussianBlur;2;9;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;10;GaussianBlur;2;10;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;11;GaussianBlur;2;11;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;12;GaussianBlur;2;12;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;13;GaussianBlur;2;13;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;14;GaussianBlur;2;14;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;15;GaussianBlur;2;15;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;16;GaussianBlur;2;16;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;17;GaussianBlur;2;17;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;18;GaussianBlur;2;18;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;19;GaussianBlur;2;19;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;20;GaussianBlur;2;20;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;21;GaussianBlur;2;21;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;22;GaussianBlur;2;22;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;23;GaussianBlur;2;23;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;24;GaussianBlur;2;24;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;25;GaussianBlur;2;25;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;26;GaussianBlur;2;26;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;27;GaussianBlur;2;27;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;28;GaussianBlur;2;28;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;29;GaussianBlur;2;29;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;30;GaussianBlur;2;30;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;0;GaussianBlur;2;5;0;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;1;GaussianBlur;2;5;1;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;2;GaussianBlur;2;5;2;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;3;GaussianBlur;2;5;3;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;4;GaussianBlur;2;5;4;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;5;GaussianBlur;2;5;5;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;6;GaussianBlur;2;5;6;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;7;GaussianBlur;2;5;7;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;8;GaussianBlur;2;5;8;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;9;GaussianBlur;2;5;9;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;10;GaussianBlur;2;5;10;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;11;GaussianBlur;2;5;11;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;12;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+Otsu;13;GaussianBlur;2;5;13;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;14;GaussianBlur;2;5;14;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;15;GaussianBlur;2;5;15;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;16;GaussianBlur;2;5;16;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;17;GaussianBlur;2;5;17;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;18;GaussianBlur;2;5;18;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;19;GaussianBlur;2;5;19;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;20;GaussianBlur;2;5;20;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;21;GaussianBlur;2;5;21;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;22;GaussianBlur;2;5;22;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;23;GaussianBlur;2;5;23;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;24;GaussianBlur;2;5;24;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;25;GaussianBlur;2;5;25;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;26;GaussianBlur;2;5;26;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;27;GaussianBlur;2;5;27;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;28;GaussianBlur;2;5;28;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;29;GaussianBlur;2;5;29;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;30;GaussianBlur;2;5;30;4;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+IS Connexity;4;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+IS Connexity;8;GaussianBlur;2;5;12;8;5;2;1;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;0;GaussianBlur;2;5;12;4;0;2;1;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;5;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+IS Min Size;10;GaussianBlur;2;5;12;4;10;2;1;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;15;GaussianBlur;2;5;12;4;15;2;1;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;20;GaussianBlur;2;5;12;4;20;2;1;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;25;GaussianBlur;2;5;12;4;25;2;1;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;30;GaussianBlur;2;5;12;4;30;2;1;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;35;GaussianBlur;2;5;12;4;35;2;1;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;40;GaussianBlur;2;5;12;4;40;2;1;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;45;GaussianBlur;2;5;12;4;45;2;1;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;50;GaussianBlur;2;5;12;4;50;2;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;0;GaussianBlur;2;5;12;4;5;0;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;1;GaussianBlur;2;5;12;4;5;1;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;2;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+Blur XY;3;GaussianBlur;2;5;12;4;5;3;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;4;GaussianBlur;2;5;12;4;5;4;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;5;GaussianBlur;2;5;12;4;5;5;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;6;GaussianBlur;2;5;12;4;5;6;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;7;GaussianBlur;2;5;12;4;5;7;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;8;GaussianBlur;2;5;12;4;5;8;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;9;GaussianBlur;2;5;12;4;5;9;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;10;GaussianBlur;2;5;12;4;5;10;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;0;GaussianBlur;2;5;12;4;5;2;0;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;1;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+Blur Z;2;GaussianBlur;2;5;12;4;5;2;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;3;GaussianBlur;2;5;12;4;5;2;3;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;4;GaussianBlur;2;5;12;4;5;2;4;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;5;GaussianBlur;2;5;12;4;5;2;5;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;6;GaussianBlur;2;5;12;4;5;2;6;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;7;GaussianBlur;2;5;12;4;5;2;7;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;8;GaussianBlur;2;5;12;4;5;2;8;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;9;GaussianBlur;2;5;12;4;5;2;9;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;10;GaussianBlur;2;5;12;4;5;2;10;0.9;5;0.8;0.1;10;0.8;NO
+ST_1;0.0;GaussianBlur;2;5;12;4;5;2;1;0.0;5;0.8;0.1;10;0.8;NO
+ST_1;0.1;GaussianBlur;2;5;12;4;5;2;1;0.1;5;0.8;0.1;10;0.8;NO
+ST_1;0.2;GaussianBlur;2;5;12;4;5;2;1;0.2;5;0.8;0.1;10;0.8;NO
+ST_1;0.3;GaussianBlur;2;5;12;4;5;2;1;0.3;5;0.8;0.1;10;0.8;NO
+ST_1;0.4;GaussianBlur;2;5;12;4;5;2;1;0.4;5;0.8;0.1;10;0.8;NO
+ST_1;0.5;GaussianBlur;2;5;12;4;5;2;1;0.5;5;0.8;0.1;10;0.8;NO
+ST_1;0.6;GaussianBlur;2;5;12;4;5;2;1;0.6;5;0.8;0.1;10;0.8;NO
+ST_1;0.7;GaussianBlur;2;5;12;4;5;2;1;0.7;5;0.8;0.1;10;0.8;NO
+ST_1;0.8;GaussianBlur;2;5;12;4;5;2;1;0.8;5;0.8;0.1;10;0.8;NO
+ST_1;0.9;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+ST_1;1.0;GaussianBlur;2;5;12;4;5;2;1;1.0;5;0.8;0.1;10;0.8;NO
+Overlap_1;0;GaussianBlur;2;5;12;4;5;2;1;0.9;0;0.8;0.1;10;0.8;NO
+Overlap_1;5;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+Overlap_1;10;GaussianBlur;2;5;12;4;5;2;1;0.9;10;0.8;0.1;10;0.8;NO
+Overlap_1;15;GaussianBlur;2;5;12;4;5;2;1;0.9;15;0.8;0.1;10;0.8;NO
+Overlap_1;17;GaussianBlur;2;5;12;4;5;2;1;0.9;17;0.8;0.1;10;0.8;NO
+Overlap_1;20;GaussianBlur;2;5;12;4;5;2;1;0.9;20;0.8;0.1;10;0.8;NO
+Overlap_1;25;GaussianBlur;2;5;12;4;5;2;1;0.9;25;0.8;0.1;10;0.8;NO
+Overlap_1;30;GaussianBlur;2;5;12;4;5;2;1;0.9;30;0.8;0.1;10;0.8;NO
+Overlap_1;35;GaussianBlur;2;5;12;4;5;2;1;0.9;35;0.8;0.1;10;0.8;NO
+Overlap_1;40;GaussianBlur;2;5;12;4;5;2;1;0.9;40;0.8;0.1;10;0.8;NO
+Overlap_1;45;GaussianBlur;2;5;12;4;5;2;1;0.9;45;0.8;0.1;10;0.8;NO
+Overlap_1;50;GaussianBlur;2;5;12;4;5;2;1;0.9;50;0.8;0.1;10;0.8;NO
+CR_1;0.5;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.5;0.1;10;0.8;NO
+CR_1;0.55;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.55;0.1;10;0.8;NO
+CR_1;0.6;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.6;0.1;10;0.8;NO
+CR_1;0.65;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.65;0.1;10;0.8;NO
+CR_1;0.7;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.7;0.1;10;0.8;NO
+CR_1;0.75;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.75;0.1;10;0.8;NO
+CR_1;0.8;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+CR_1;0.85;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.85;0.1;10;0.8;NO
+CR_1;0.9;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.9;0.1;10;0.8;NO
+CR_1;0.95;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.95;0.1;10;0.8;NO
+CR_1;1;GaussianBlur;2;5;12;4;5;2;1;0.9;5;1;0.1;10;0.8;NO
+ST_2;0.0;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.0;10;0.8;NO
+ST_2;0.1;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+ST_2;0.2;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.2;10;0.8;NO
+ST_2;0.3;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.3;10;0.8;NO
+ST_2;0.4;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.4;10;0.8;NO
+ST_2;0.5;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.5;10;0.8;NO
+ST_2;0.6;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.6;10;0.8;NO
+ST_2;0.7;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.7;10;0.8;NO
+ST_2;0.8;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.8;10;0.8;NO
+ST_2;0.9;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.9;10;0.8;NO
+ST_2;1.0;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;1.0;10;0.8;NO
+Overlap_2;0;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;0;0.8;NO
+Overlap_2;5;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;5;0.8;NO
+Overlap_2;10;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+Overlap_2;15;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;15;0.8;NO
+Overlap_2;20;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;20;0.8;NO
+Overlap_2;25;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;25;0.8;NO
+Overlap_2;30;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;30;0.8;NO
+Overlap_2;35;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;35;0.8;NO
+Overlap_2;40;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;40;0.8;NO
+Overlap_2;45;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;45;0.8;NO
+Overlap_2;50;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;50;0.8;NO
+CR_2;0.5;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.5;NO
+CR_2;0.55;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.55;NO
+CR_2;0.6;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.6;NO
+CR_2;0.65;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.65;NO
+CR_2;0.7;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.7;NO
+CR_2;0.75;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.75;NO
+CR_2;0.8;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.8;YES
+CR_2;0.85;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.85;NO
+CR_2;0.9;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.9;NO
+CR_2;0.95;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;0.95;NO
+CR_2;1;GaussianBlur;2;5;12;4;5;2;1;0.9;5;0.8;0.1;10;1;NO
diff --git a/src/test/resources/Phantom/Phantom_PS.csv b/src/test/resources/Phantom/Phantom_PS.csv
new file mode 100644
index 0000000000000000000000000000000000000000..a26a291b828a76be7b9f36f5ae439a4df5a44cd5
--- /dev/null
+++ b/src/test/resources/Phantom/Phantom_PS.csv
@@ -0,0 +1,165 @@
+Phantom;;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;
+Amplitude;0;GaussianBlur;2;0;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;1;GaussianBlur;2;1;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;2;GaussianBlur;2;2;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;3;GaussianBlur;2;3;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;4;GaussianBlur;2;4;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;5;GaussianBlur;2;5;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;6;GaussianBlur;2;6;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;7;GaussianBlur;2;7;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;8;GaussianBlur;2;8;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;9;GaussianBlur;2;9;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;10;GaussianBlur;2;10;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;11;GaussianBlur;2;11;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;12;GaussianBlur;2;12;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;13;GaussianBlur;2;13;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;14;GaussianBlur;2;14;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;15;GaussianBlur;2;15;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;16;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+Amplitude;17;GaussianBlur;2;17;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;18;GaussianBlur;2;18;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;19;GaussianBlur;2;19;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;20;GaussianBlur;2;20;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;21;GaussianBlur;2;21;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;22;GaussianBlur;2;22;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;23;GaussianBlur;2;23;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;24;GaussianBlur;2;24;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;25;GaussianBlur;2;25;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;26;GaussianBlur;2;26;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;27;GaussianBlur;2;27;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;28;GaussianBlur;2;28;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;29;GaussianBlur;2;29;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Amplitude;30;GaussianBlur;2;30;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;0;GaussianBlur;2;16;0;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;1;GaussianBlur;2;16;1;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;2;GaussianBlur;2;16;2;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;3;GaussianBlur;2;16;3;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;4;GaussianBlur;2;16;4;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;5;GaussianBlur;2;16;5;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;6;GaussianBlur;2;16;6;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;7;GaussianBlur;2;16;7;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;8;GaussianBlur;2;16;8;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;9;GaussianBlur;2;16;9;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;10;GaussianBlur;2;16;10;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;11;GaussianBlur;2;16;11;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;12;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+Otsu;13;GaussianBlur;2;16;13;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;14;GaussianBlur;2;16;14;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;15;GaussianBlur;2;16;15;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;16;GaussianBlur;2;16;16;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;17;GaussianBlur;2;16;17;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;18;GaussianBlur;2;16;18;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;19;GaussianBlur;2;16;19;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;20;GaussianBlur;2;16;20;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;21;GaussianBlur;2;16;21;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;22;GaussianBlur;2;16;22;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;23;GaussianBlur;2;16;23;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;24;GaussianBlur;2;16;24;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;25;GaussianBlur;2;16;25;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;26;GaussianBlur;2;16;26;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;27;GaussianBlur;2;16;27;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;28;GaussianBlur;2;16;28;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;29;GaussianBlur;2;16;29;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Otsu;30;GaussianBlur;2;16;30;4;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+IS Connexity;4;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+IS Connexity;8;GaussianBlur;2;16;12;8;5;4;2;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;0;GaussianBlur;2;16;12;4;0;4;2;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;5;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+IS Min Size;10;GaussianBlur;2;16;12;4;10;4;2;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;15;GaussianBlur;2;16;12;4;15;4;2;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;20;GaussianBlur;2;16;12;4;20;4;2;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;25;GaussianBlur;2;16;12;4;25;4;2;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;30;GaussianBlur;2;16;12;4;30;4;2;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;35;GaussianBlur;2;16;12;4;35;4;2;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;40;GaussianBlur;2;16;12;4;40;4;2;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;45;GaussianBlur;2;16;12;4;45;4;2;0.9;5;0.8;0.1;10;0.8;NO
+IS Min Size;50;GaussianBlur;2;16;12;4;50;4;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;0;GaussianBlur;2;16;12;4;5;0;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;1;GaussianBlur;2;16;12;4;5;1;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;2;GaussianBlur;2;16;12;4;5;2;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;3;GaussianBlur;2;16;12;4;5;3;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;4;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+Blur XY;5;GaussianBlur;2;16;12;4;5;5;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;6;GaussianBlur;2;16;12;4;5;6;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;7;GaussianBlur;2;16;12;4;5;7;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;8;GaussianBlur;2;16;12;4;5;8;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;9;GaussianBlur;2;16;12;4;5;9;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur XY;10;GaussianBlur;2;16;12;4;5;10;2;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;0;GaussianBlur;2;16;12;4;5;4;0;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;1;GaussianBlur;2;16;12;4;5;4;1;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;2;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+Blur Z;3;GaussianBlur;2;16;12;4;5;4;3;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;4;GaussianBlur;2;16;12;4;5;4;4;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;5;GaussianBlur;2;16;12;4;5;4;5;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;6;GaussianBlur;2;16;12;4;5;4;6;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;7;GaussianBlur;2;16;12;4;5;4;7;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;8;GaussianBlur;2;16;12;4;5;4;8;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;9;GaussianBlur;2;16;12;4;5;4;9;0.9;5;0.8;0.1;10;0.8;NO
+Blur Z;10;GaussianBlur;2;16;12;4;5;4;10;0.9;5;0.8;0.1;10;0.8;NO
+ST_1;0.0;GaussianBlur;2;16;12;4;5;4;2;0.0;5;0.8;0.1;10;0.8;NO
+ST_1;0.1;GaussianBlur;2;16;12;4;5;4;2;0.1;5;0.8;0.1;10;0.8;NO
+ST_1;0.2;GaussianBlur;2;16;12;4;5;4;2;0.2;5;0.8;0.1;10;0.8;NO
+ST_1;0.3;GaussianBlur;2;16;12;4;5;4;2;0.3;5;0.8;0.1;10;0.8;NO
+ST_1;0.4;GaussianBlur;2;16;12;4;5;4;2;0.4;5;0.8;0.1;10;0.8;NO
+ST_1;0.5;GaussianBlur;2;16;12;4;5;4;2;0.5;5;0.8;0.1;10;0.8;NO
+ST_1;0.6;GaussianBlur;2;16;12;4;5;4;2;0.6;5;0.8;0.1;10;0.8;NO
+ST_1;0.7;GaussianBlur;2;16;12;4;5;4;2;0.7;5;0.8;0.1;10;0.8;NO
+ST_1;0.8;GaussianBlur;2;16;12;4;5;4;2;0.8;5;0.8;0.1;10;0.8;NO
+ST_1;0.9;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+ST_1;1.0;GaussianBlur;2;16;12;4;5;4;2;1.0;5;0.8;0.1;10;0.8;NO
+Overlap_1;0;GaussianBlur;2;16;12;4;5;4;2;0.9;0;0.8;0.1;10;0.8;NO
+Overlap_1;5;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+Overlap_1;10;GaussianBlur;2;16;12;4;5;4;2;0.9;10;0.8;0.1;10;0.8;NO
+Overlap_1;15;GaussianBlur;2;16;12;4;5;4;2;0.9;15;0.8;0.1;10;0.8;NO
+Overlap_1;17;GaussianBlur;2;16;12;4;5;4;2;0.9;17;0.8;0.1;10;0.8;NO
+Overlap_1;20;GaussianBlur;2;16;12;4;5;4;2;0.9;20;0.8;0.1;10;0.8;NO
+Overlap_1;25;GaussianBlur;2;16;12;4;5;4;2;0.9;25;0.8;0.1;10;0.8;NO
+Overlap_1;30;GaussianBlur;2;16;12;4;5;4;2;0.9;30;0.8;0.1;10;0.8;NO
+Overlap_1;35;GaussianBlur;2;16;12;4;5;4;2;0.9;35;0.8;0.1;10;0.8;NO
+Overlap_1;40;GaussianBlur;2;16;12;4;5;4;2;0.9;40;0.8;0.1;10;0.8;NO
+Overlap_1;45;GaussianBlur;2;16;12;4;5;4;2;0.9;45;0.8;0.1;10;0.8;NO
+Overlap_1;50;GaussianBlur;2;16;12;4;5;4;2;0.9;50;0.8;0.1;10;0.8;NO
+CR_1;0.5;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.5;0.1;10;0.8;NO
+CR_1;0.55;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.55;0.1;10;0.8;NO
+CR_1;0.6;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.6;0.1;10;0.8;NO
+CR_1;0.65;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.65;0.1;10;0.8;NO
+CR_1;0.7;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.7;0.1;10;0.8;NO
+CR_1;0.75;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.75;0.1;10;0.8;NO
+CR_1;0.8;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+CR_1;0.85;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.85;0.1;10;0.8;NO
+CR_1;0.9;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.9;0.1;10;0.8;NO
+CR_1;0.95;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.95;0.1;10;0.8;NO
+CR_1;1;GaussianBlur;2;16;12;4;5;4;2;0.9;5;1;0.1;10;0.8;NO
+ST_2;0.0;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.0;10;0.8;NO
+ST_2;0.1;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+ST_2;0.2;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.2;10;0.8;NO
+ST_2;0.3;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.3;10;0.8;NO
+ST_2;0.4;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.4;10;0.8;NO
+ST_2;0.5;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.5;10;0.8;NO
+ST_2;0.6;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.6;10;0.8;NO
+ST_2;0.7;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.7;10;0.8;NO
+ST_2;0.8;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.8;10;0.8;NO
+ST_2;0.9;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.9;10;0.8;NO
+ST_2;1.0;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;1.0;10;0.8;NO
+Overlap_2;0;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;0;0.8;NO
+Overlap_2;5;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;5;0.8;NO
+Overlap_2;10;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+Overlap_2;15;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;15;0.8;NO
+Overlap_2;20;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;20;0.8;NO
+Overlap_2;25;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;25;0.8;NO
+Overlap_2;30;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;30;0.8;NO
+Overlap_2;35;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;35;0.8;NO
+Overlap_2;40;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;40;0.8;NO
+Overlap_2;45;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;45;0.8;NO
+Overlap_2;50;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;50;0.8;NO
+CR_2;0.5;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.5;NO
+CR_2;0.55;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.55;NO
+CR_2;0.6;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.6;NO
+CR_2;0.65;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.65;NO
+CR_2;0.7;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.7;NO
+CR_2;0.75;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.75;NO
+CR_2;0.8;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.8;YES
+CR_2;0.85;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.85;NO
+CR_2;0.9;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.9;NO
+CR_2;0.95;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;0.95;NO
+CR_2;1;GaussianBlur;2;16;12;4;5;4;2;0.9;5;0.8;0.1;10;1;NO
diff --git a/src/test/resources/Phantom/phantoms_snrtest_zmap1_gt.tif b/src/test/resources/Phantom/phantoms_snrtest_zmap1_gt.tif
new file mode 100644
index 0000000000000000000000000000000000000000..54307b7423ae2fc823633f6cc8b6b7e092ed260e
Binary files /dev/null and b/src/test/resources/Phantom/phantoms_snrtest_zmap1_gt.tif differ
diff --git a/src/test/resources/Phantom/phantoms_snrtest_zmap2_gt.tif b/src/test/resources/Phantom/phantoms_snrtest_zmap2_gt.tif
new file mode 100644
index 0000000000000000000000000000000000000000..ec64c533ec1261c7e8cbf77cc0b533cd46fd3200
Binary files /dev/null and b/src/test/resources/Phantom/phantoms_snrtest_zmap2_gt.tif differ
diff --git a/src/test/resources/Phantom/phantoms_snrtest_zmap3_gt.tif b/src/test/resources/Phantom/phantoms_snrtest_zmap3_gt.tif
new file mode 100644
index 0000000000000000000000000000000000000000..e624076fa8cde24da6b249d333142b997ce78ff1
Binary files /dev/null and b/src/test/resources/Phantom/phantoms_snrtest_zmap3_gt.tif differ