Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • dev-batch-mode
  • 25-multithreads-heavy-tasks
  • dev
  • 10-multi-channel-image-handling
  • 9-gui-features
  • master
  • dev-display
  • median-3d
  • Cnam
  • zellige-core-1.0.0
  • zellige-core-1.1.0
  • zellige-core-1.1.1
  • zellige-core-1.1.3
13 results

Target

Select target project
  • IdA Public / Zellige-core
1 result
Select Git revision
  • dev-batch-mode
  • 25-multithreads-heavy-tasks
  • dev
  • 10-multi-channel-image-handling
  • 9-gui-features
  • master
  • dev-display
  • median-3d
  • Cnam
  • zellige-core-1.0.0
  • zellige-core-1.1.0
  • zellige-core-1.1.1
  • zellige-core-1.1.3
13 results
Show changes
120 files
+ 5270
3414
Compare changes
  • Side-by-side
  • Inline

Files

+13 −6
Original line number Diff line number Diff line
@@ -6,7 +6,8 @@
    <parent>
        <groupId>org.scijava</groupId>
        <artifactId>pom-scijava</artifactId>
        <version>31.1.0</version>
        <version>39.0.0</version>
        <relativePath />
    </parent>

    <groupId>org.example</groupId>
@@ -48,7 +49,13 @@
        </repository>
    </repositories>


    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
@@ -124,11 +131,11 @@
            <artifactId>imagej-legacy</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/net.imglib2/imglib2-script -->
        <dependency>
            <groupId>net.imglib2</groupId>
            <artifactId>imglib2-script</artifactId>
        </dependency>
<!--        &lt;!&ndash; https://mvnrepository.com/artifact/net.imglib2/imglib2-script &ndash;&gt;-->
<!--        <dependency>-->
<!--            <groupId>net.imglib2</groupId>-->
<!--            <artifactId>imglib2-script</artifactId>-->
<!--        </dependency>-->

        <!-- https://mvnrepository.com/artifact/net.imglib2/imglib2 -->
        <dependency>
Original line number Diff line number Diff line
@@ -29,23 +29,49 @@
package fr.pasteur.ida.zellige;


import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.FileAppender;
import fr.pasteur.ida.zellige.element.ReferenceSurface;
import fr.pasteur.ida.zellige.steps.construction.Construction;
import fr.pasteur.ida.zellige.steps.construction.rounds.ConstructionParameters;
import fr.pasteur.ida.zellige.steps.projection.DisplayParameters;
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.ClassificationParameters;
import fr.pasteur.ida.zellige.steps.selection.postTreatment.PostTreatmentParameters;
import fr.pasteur.ida.zellige.steps.selection.pretreatment.PretreatmentParameters;
import ij.IJ;
import ij.ImageJ;
import io.scif.img.IO;
import io.scif.img.SCIFIOImgPlus;
import fr.pasteur.ida.zellige.steps.selection.util.ArgumentCheck;
import io.scif.img.ImgSaver;
import net.imagej.Dataset;
import net.imagej.ImageJ;
import net.imagej.ImgPlus;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.display.ColorTable;
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 net.imglib2.type.numeric.real.FloatType;
import net.imglib2.view.Views;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.text.RandomStringGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static fr.pasteur.ida.zellige.utils.Util.create4dimImage;


/**
@@ -54,108 +80,13 @@ import java.awt.*;
public class Main
{

    private final static Logger LOGGER = LoggerFactory.getLogger( Main.class );

    @SuppressWarnings( "unchecked" )
    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 =// "C:\\Users\\ctrebeau\\Desktop\\Zellige analysis\\files\\SNR\\snr_000\\multiSurfaces\\phantoms_snr0.mat.tif";
                args[ 0 ]; /* The image path goes here !!!! */
        LOGGER.debug( imagePath );
        /* JY version for opening files. */
        final SCIFIOImgPlus< ? > imgPlus = IO.openAll( imagePath ).get( 0 );

        final Img< T > stackImage = ( Img< T > ) imgPlus.getImg();


        /* User Parameters AKA arguments to run the program*/
        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 ] );
        double sigmaZ = Double.parseDouble( args[ 6 ] );
        double startingOsSize1 = Double.parseDouble( args[ 7 ] );
        int overlap1 = Integer.parseInt( args[ 8 ] );
        double connexityRate1 = Double.parseDouble( args[ 9 ] );
        double startingOsSize2 = Double.parseDouble( args[ 10 ] );
        int overlap2 = Integer.parseInt( args[ 11 ] );
        double connexityRate2 = Double.parseDouble( args[ 12 ] );
        double surfaceMinSizeFactor = Double.parseDouble( args[ 13 ] );
        int delta = Integer.parseInt( args[ 14 ] );
        /* End of parameters. */


        // Fixed parameters for now...
        String filter = "GaussianBlur";
        double filterParameter = 2;


        /* Print parameters.*/
        LOGGER.debug( "Input image : " + imagePath );
        LOGGER.debug( "filter : " + filter );
        LOGGER.debug( "filter parameter : " + filterParameter );
        LOGGER.debug( "amplitude  : " + amplitude );
        LOGGER.debug( "threshold  : " + otsu );
        LOGGER.debug( "connexity : " + connexity );
        LOGGER.debug( "island size : " + islandSize );
        LOGGER.debug( "sigmaXY : " + sigmaXY );
        LOGGER.debug( "sigmaZ : " + sigmaZ );
        LOGGER.debug( "starting os size1 : " + startingOsSize1 );
        LOGGER.debug( "overlap1 :" + overlap1 );
        LOGGER.debug( "connexityRate1  :" + connexityRate1 );
        LOGGER.debug( "starting os size2 : " + startingOsSize2 );
        LOGGER.debug( "overlap2 :" + overlap2 );
        LOGGER.debug( "connexityRate2  :" + connexityRate2 );
        LOGGER.debug( "surface Minimum size factor : " + surfaceMinSizeFactor );
        LOGGER.debug( "delta : " + delta );
        LOGGER.debug( System.lineSeparator() );
        /* End of  Print parameters.*/

        PretreatmentParameters pretreatmentParameters = new PretreatmentParameters( filter, filterParameter );
        ClassificationParameters classificationParameters = new ClassificationParameters( amplitude, otsu );
        PostTreatmentParameters postTreatmentParameters = new PostTreatmentParameters( sigmaXY, sigmaZ, islandSize, connexity );
        ProjectionParameters projectionParameters = new ProjectionParameters( delta, "MIP" );// no other method implemented yet.
        ConstructionParameters[] constructionParameters = new ConstructionParameters[]{
                new ConstructionParameters( startingOsSize1, overlap1, connexityRate1, surfaceMinSizeFactor ),
                new ConstructionParameters( startingOsSize2, overlap2, connexityRate2, surfaceMinSizeFactor ) };


        DisplayParameters displayParameters = new DisplayParameters(
                true,
                true,
                true,
                true,
                true, true );
        IJ.log( "Type: " + imgPlus.firstElement().getClass().toGenericString() );

        if ( stackImage.numDimensions() == 3 )// Is it a stack ?
        {
            ReferenceSurfaceExtraction< T > rse = new ReferenceSurfaceExtraction<>
                    ( stackImage, stackImage.factory() );
            rse.select( pretreatmentParameters, classificationParameters, postTreatmentParameters );
            rse.construct( constructionParameters );
            rse.project( projectionParameters, displayParameters );
            if ( ! GraphicsEnvironment.isHeadless() )
            {
                try
                {
                    rse.project( projectionParameters, displayParameters );
                }
                catch ( Exception e )
                {
                    LOGGER.debug( e.getMessage() );
                }
            }
        }
        else
    public static < T extends RealType< T > & NativeType< T > > void main( String [] args ) throws Exception
    {
            LOGGER.debug( " This image has to be a z-stack ! " );
        }
        String CSV_FILE ="doc/test.csv";
        ReferenceSurfaceExtraction.run( CSV_FILE );
    }

}
Original line number Diff line number Diff line
@@ -50,18 +50,19 @@ public class Zellige extends ContextCommand
                .getPath( "" )
                .toAbsolutePath()
                .toString();
//        String imageFilePath = "C:\\Users\\ctrebeau\\Desktop\\channel_test.tif";
        String imageFilePath = "doc/Mouche.tif";

        // Launch ImageJ.
        ImageJ ij = new ImageJ();
        ij.launch( args );

        // Load the image.
        Object obj = ij.io().open( new File( currentFolder, imageFilePath ).getAbsolutePath() );
        Object obj = ij.io().open( new File( imageFilePath ).getAbsolutePath() );

        // Display it.
        ij.ui().show( obj );


        ij.command().run( Zellige.class, true );
    }

Original line number Diff line number Diff line
@@ -30,67 +30,64 @@ 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 final int offset;
    private final int deltaZ;
    private String method;
    private final ReferenceSurface<T> referenceSurface;
    private Img< T > projection;
    private Img< UnsignedShortType > extractedHeightMap;
    private Img< T > segmentedSurface;
    private Img< T > reduced3DSpace;
    private Img< BitType > segmentedSurfaceMask;
    private int index;
    private Img<T> subVolume;


    public Img< T > getSegmentedSurface()
    public Projection( int offset, int deltaZ, String method, ReferenceSurface< T > referenceSurface )
    {
        return segmentedSurface;
        this.offset = offset;
        this.deltaZ = deltaZ;
        this.method = method;
        this.referenceSurface = referenceSurface;
    }

    public void setSegmentedSurface( Img< T > segmentedSurface )
    public Img< T > get()
    {
        this.segmentedSurface = segmentedSurface;
        return projection;
    }

    public Img< UnsignedShortType > getExtractedHeightMap()
    public void setProjection( Img< T > projection )
    {
        return extractedHeightMap;
        this.projection = projection;
    }

    public void setExtractedHeightMap( Img< UnsignedShortType > extractedHeightMap )
    public Img< T > getSubVolume()
    {
        this.extractedHeightMap = extractedHeightMap;
        return subVolume;
    }

    public Img< T > get()
    public int getOffset()
    {
        return projection;
        return offset;
    }

    public void setProjection( Img< T > projection )
    public int getDeltaZ()
    {
        this.projection = projection;
        return deltaZ;
    }

    public Img< T > getReduced3DSpace()
    public String getMethod()
    {
        return reduced3DSpace;
        return method;
    }

    public void setReduced3DSpace( Img< T > reduced3DSpace )
    public void setSubVolume( Img< T > subVolume )
    {
        this.reduced3DSpace = reduced3DSpace;
        this.subVolume = subVolume;
    }

    public Img< BitType > getSegmentedSurfaceMask()
    public void setMethod( String method )
    {
        return segmentedSurfaceMask;
        this.method = method;
    }

    public void setSegmentedSurfaceMask( Img< BitType > segmentedSurfaceMask )
    {
        this.segmentedSurfaceMask = segmentedSurfaceMask;
    }
}
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
 */
package fr.pasteur.ida.zellige.element;

import net.imglib2.RandomAccess;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.img.Img;
import net.imglib2.img.ImgFactory;
@@ -35,14 +36,18 @@ import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.numeric.integer.UnsignedShortType;

import static fr.pasteur.ida.zellige.steps.Utils.setPositionAndGet;

public class ReferenceSurface< T extends RealType< T > & NativeType< T > >
{
    private final RandomAccessibleInterval< T > input;
    private final ImgFactory< T > factory;
    private final Img< UnsignedShortType > zMap;
    private final int index;
    private Projection< T > projection;
    private final String name;


    private final Img <T> rawProjection;

    public ReferenceSurface( RandomAccessibleInterval< T > input,
                             ImgFactory< T > factory, Img< UnsignedShortType > zMap, int index )
@@ -50,13 +55,35 @@ public class ReferenceSurface< T extends RealType< T > & NativeType< T > >
        this.input = input;
        this.factory = factory;
        this.zMap = zMap;
        this.projection = new Projection<>();
        this.rawProjection = factory.create(zMap);
        this.index = index;
        this.name = "Reference Surface n°" + (index + 1);
        setRawProjection();
    }

    public Projection< T > getProjection()
    /**
     * Creates the raw height map projection
     */
    private void setRawProjection()
    {
        RandomAccess<T> projectionAccess = rawProjection.randomAccess();
        RandomAccess< UnsignedShortType > zMapAccess = zMap.randomAccess();
        RandomAccess <T > inputAccess = input.randomAccess();
        for ( int x = 0; x < zMap.dimension (0 ); x++ )
        {
        return projection;
            for ( int y = 0; y <zMap.dimension (1 ); y++ )
            {
                // Z value on Height Map
                int z  = setPositionAndGet( zMapAccess, x, y ).getInteger();
                if( z > 0 )
                {
                    // pixel value on input
                    T value = setPositionAndGet( inputAccess, x, y, z - 1 );
                    // Set value on projection
                    setPositionAndGet( projectionAccess, x, y ).set( value );
                }
            }
        }
    }

    public RandomAccessibleInterval< T > getInput()
@@ -74,14 +101,14 @@ public class ReferenceSurface< T extends RealType< T > & NativeType< T > >
        return zMap;
    }

    public int getIndex()
    public String getName()
    {
        return index;
        return name;
    }

    public void init()
    public int getIndex()
    {
        this.projection = new Projection<>();
        return index;
    }
}

Original line number Diff line number Diff line
@@ -149,43 +149,6 @@ public class Surface
        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 another {@link Surface} object.
     *
Original line number Diff line number Diff line
@@ -36,9 +36,7 @@ import java.util.ArrayList;
public abstract class AbstractOSE extends ArrayList< Coordinate >
{

    /* Not necessary for the program.*/
    private final OSEStartingStatus startingStatus;
    /*-------------*/

    /**
     * The visited status for the 1D and 2D reconstructions.
@@ -62,10 +60,8 @@ public abstract class AbstractOSE extends ArrayList< Coordinate >
     */
    public void set()
    {
        Integer j = startingStatus.get( this.size() );
        startingStatus.put( this.size(), ( j == null ) ? 1 : j + 1 );
        startingStatus.compute( this.size(), ( k, j ) -> ( j == null ) ? 1 : j + 1 );
        startingStatus.setOSCount();

    }

    /**
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import java.util.Collection;
public class OSEList extends ArrayList< AbstractOSE >
{


    public OSEList()
    {
    }
@@ -66,6 +65,10 @@ public class OSEList extends ArrayList< AbstractOSE >
        return add;
    }

    /**
     *
     * @return the size of the OSE list
     */
    public int getSize()
    {
        int size = 0;
@@ -76,6 +79,9 @@ public class OSEList extends ArrayList< AbstractOSE >
        return size;
    }

    /**
     * Resets to false the visited status
     */
    public void reset()
    {
        for ( AbstractOSE os : this )
@@ -84,6 +90,10 @@ public class OSEList extends ArrayList< AbstractOSE >
        }
    }

    /**
     *
     * @return true if the OSE list contains a starting OSE
     */
    public boolean containsAStart()
    {
        for ( AbstractOSE os : this )
Original line number Diff line number Diff line
@@ -75,13 +75,14 @@ public abstract class SurfaceLine
            set( os );
    }

    
    public SurfaceLine( AbstractOSE os, int size )
    {
        this.dimension = new Pixels[ size] ;
        set( os );
    }

    /**
     *
     * @param os
     * @param overlap
     * @param connexity
     * @param surfaceLine
     * @return
     */
    public SurfaceLine match2( AbstractOSE os, int overlap, double connexity, SurfaceLine surfaceLine )
    {
        int match = 0;
Original line number Diff line number Diff line
@@ -44,6 +44,15 @@ public class SurfaceLineX extends SurfaceLine
        this.setLine( os.get( 0 ).getY() );
    }

    /**
     * Tests if the OS matches the SurfaceLine instance and creates a new SurfaceLine object if so.
     *
     * @param os      - the OS to test against the SurfaceLine instance.
     * @param direction       - an integer witch indicates the line of the resulting SurfaceLine.
     * @param overlap - the minimum number of matching coordinates.
     * @param connexity - the minimum percentage of match between the OS and the current instance.
     * @return - a new SurfaceLine if there is a match, null otherwise.
     */
    public SurfaceLine match( AbstractOSE os, int direction, int overlap, double connexity )
    {
        SurfaceLineX surfaceLineX = new SurfaceLineX( this.getLength(), this.getLine() + direction );
@@ -61,12 +70,4 @@ public class SurfaceLineX extends SurfaceLine
        super(length,  line );
    }

    public SurfaceLineX( AbstractOSE os, int size )
    {
        super( os , size);
        this.setLine( os.get( 0 ).getY() );
    }



}
Original line number Diff line number Diff line
@@ -66,8 +66,6 @@ public class SurfaceLineY extends SurfaceLine
     * @param connexity - the minimum percentage of match between the OS and the current instance.
     * @return - a new SurfaceLine if there is a match, null otherwise.
     */


    public SurfaceLine match( AbstractOSE os, int direction, int overlap, double connexity )
    {
        SurfaceLineY surfaceLineY = new SurfaceLineY( this.getLength(), this.getLine() + direction );
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.Pane;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class ChannelPanel extends Pane implements Initializable
{
    @FXML
    private Spinner<Integer> deltaZ;

    @FXML
    private ChoiceBox<String> method;

    @FXML
    private Spinner<Integer> offset;

    @FXML
    private Button view;

    public ChannelPanel(  )
    {
        FXMLLoader fxmlLoader = new FXMLLoader( ChannelPanel.class.getClassLoader().
                getResource( "fr.pasteur.ida.zellige.gui.view/ChannelProjection.fxml" ) );
        fxmlLoader.setRoot(this);
        fxmlLoader.setController( this );
        try
        {
            fxmlLoader.load();
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
    }

    @Override
    public void initialize( URL url, ResourceBundle resourceBundle )
    {
        SpinnerValueFactory< Integer > valueFactory =
                new SpinnerValueFactory.IntegerSpinnerValueFactory( 0, 30, 1, 1 );
        deltaZ.setValueFactory( valueFactory );
        ObservableList< String > list = FXCollections.observableArrayList( "MIP", "Mean" );
        method.setItems( list );
        method.getSelectionModel().selectFirst();
        SpinnerValueFactory< Integer > valueFactory2 =
                new SpinnerValueFactory.IntegerSpinnerValueFactory( 0, 30, 0, 1 );
        offset.setValueFactory( valueFactory2 );

    }

    public Spinner< Integer > getDeltaZ()
    {
        return deltaZ;
    }

    public ChoiceBox< String > getMethod()
    {
        return method;
    }

    public Spinner< Integer > getOffset()
    {
        return offset;
    }

    public Button getView()
    {
        return view;
    }
}
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui;

import javafx.beans.property.*;
import net.imglib2.img.Img;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;

public class ChannelToolProperty < T extends RealType< T > & NativeType< T > >
{
    private final IntegerProperty deltaZ = new SimpleIntegerProperty();
    private final IntegerProperty offset = new SimpleIntegerProperty();
    private final StringProperty method = new SimpleStringProperty("");

    private final SimpleObjectProperty<  Img< T >  > subVolume = new SimpleObjectProperty<>();
    private final SimpleObjectProperty<  Img< T >  > projection = new SimpleObjectProperty<>();
//    private final SimpleObjectProperty< RandomAccessibleInterval<T> > reducedStack = new SimpleObjectProperty<>();
//    private final BooleanProperty parameterChanged = new SimpleBooleanProperty( true );
//    private final SimpleObjectProperty< RandomAccessibleInterval<T>> projection = new SimpleObjectProperty<>();

    public StringProperty getMethod()
    {
        return method;
    }

    public IntegerProperty getOffset()
    {
        return offset;
    }

    public IntegerProperty getDeltaZ()
    {
        return deltaZ;
    }

//    public void setProperties(int delta, int offset, String method)
//    {
//
//        getDeltaZ().set( delta);
//        getOffset().set( offset );
//        getMethod().set( method );
//    }

    public ChannelToolProperty()
    {
        deltaZ.addListener(( observableValue, number, newValue ) ->
        {
            if (number.intValue() != newValue.intValue())
            {
                subVolume.set( null );
                projection.set( null );
            }
        });

        offset.addListener(( observableValue, number, newValue ) ->
        {
            if (number.intValue() != newValue.intValue())
            {
                subVolume.set( null );
                projection.set( null );
            }
        });

        method.addListener(( observableValue, number, newValue ) ->
        {
            if (! number.equals(   newValue))
            {
                projection.set( null );
            }
        });
    }

    public SimpleObjectProperty< Img< T > > getSubVolume()
    {
        return subVolume;
    }

    public SimpleObjectProperty< Img< T > > getProjection()
    {
        return projection;
    }


}
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;

import java.io.IOException;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.VBox;

public class ConstructionDisplay extends VBox
{

    @FXML
    private Label surfaceNb;

    @FXML
    private FlowPane display;

    @FXML
    private Label log;

    @FXML
    private Button minus;

    @FXML
    private Button plus;



    private int surfaceNumber = 1;

    private int nbOfSurfaces;



    public ConstructionDisplay( )
    {
        FXMLLoader fxmlLoader = new FXMLLoader( ConstructionDisplay.class.getClassLoader().getResource(
                "fr.pasteur.ida.zellige.gui.view/ConstructionDisplay.fxml" ) );
        fxmlLoader.setRoot( this );
        fxmlLoader.setController( this );
        try
        {
            fxmlLoader.load();
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
    }

    public void next()
    {
        if (surfaceNumber == nbOfSurfaces)
            {
                surfaceNumber = 1;
            }
            else
            {
                surfaceNumber++;
            }
    }

    public void previous()
    {
        if (surfaceNumber == 1)
            {
                surfaceNumber = nbOfSurfaces;
            }
            else
            {
                surfaceNumber--;
            }
    }
    public void set( ImageView image, int index )
    {
        display.getChildren().add( image );
        surfaceNb.setText( "Height map n°" + index );
        if ( nbOfSurfaces == 1 )
        {
            log.setText( "Extraction of " + nbOfSurfaces + " height map." );
        }
        else
        {
            log.setText( "Extraction of " + nbOfSurfaces + " height maps." );
        }


    }



    public void setNbOfSurfaces( int nbOfSurfaces )
    {
        this.nbOfSurfaces = nbOfSurfaces;
    }

    public Label getLog()
    {
        return log;
    }

    public Button getMinus()
    {
        return minus;
    }

    public Button getPlus()
    {
        return plus;
    }

    public int getSurfaceNumber()
    {
        return surfaceNumber;
    }

    public int getNbOfSurfaces()
    {
        return nbOfSurfaces;
    }

    public void setSurfaceNumber( int surfaceNumber )
    {
        this.surfaceNumber = surfaceNumber;
    }

    public FlowPane getDisplay()
    {
        return display;
    }
}
Original line number Diff line number Diff line
@@ -28,60 +28,50 @@
 */
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 javafx.scene.image.*;
import net.imglib2.Cursor;
import net.imglib2.IterableInterval;
import net.imglib2.type.logic.BitType;
import net.imglib2.algorithm.stats.Normalize;
import net.imglib2.img.Img;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.util.ImgUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ImageFXDisplay
{

    private final static Logger LOGGER = LoggerFactory.getLogger( ImageFXDisplay.class );

    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 )
    public static < T extends RealType< T > & NativeType< T > > void setSelectedPixels( Img< T > input, ImageView[] imageViews )
    {
        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 );
        int width = ( int ) input.dimension( 0 );
        int height = ( int ) input.dimension( 1 );
        int depth = ( int ) input.dimension( 2 );
        int[] data = convertToBinary( input, width, height, depth );
        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 ] );
            pixelWriter.setPixels( 0, 0, width, height, PixelFormat.getIntArgbInstance(), data, height * width * z, width );
            ImageView imageView = new ImageView( writableImage );
            setImageViews( imageView, width, height , 270);
            imageViews[ z ] = imageView;
        }

        LOGGER.debug( "Selected pixels ImageViews set." );
    }


    public int[] convert2( IterableInterval< BitType > input )
    public static < T extends RealType< T > & NativeType< T > > int[] convertToBinary( IterableInterval< T > input, int width, int height, int depth )
    {
        int[] data = new int[ height * width * depth ];
        Cursor< BitType > cursor = input.cursor();
        Cursor< T > cursor = input.cursor();
        int index = 0;
        System.out.println( 0xFFFFFFFF );
        while ( cursor.hasNext() )
        {
            cursor.fwd();
            if ( cursor.get().get() )
            if ( cursor.next().getRealFloat() > 0 )
            {
                data[ index++ ] = ( 0xFFFFFFFF );
            }
@@ -89,37 +79,101 @@ public class ImageFXDisplay
            {
                data[ index++ ] = 0xFF000000;
            }


        }
        LOGGER.debug( "Selected pixels data converted for selected pixels display.");
        return data;
    }

    public ImageView[] getImageViews()
    public static < T extends RealType< T > & NativeType< T > > void setHM( Img< T > input, ImageView[] imageViews, int index )
    {
        return this.imageViews;
        int width = ( int ) input.dimension( 0 );
        int height = ( int ) input.dimension( 1 );
        int[] data = convertToGrays( normalize( input ), width, height );
        WritableImage writableImage = new WritableImage( width, height );
        PixelWriter pixelWriter = writableImage.getPixelWriter();
        pixelWriter.setPixels( 0, 0, width, height, PixelFormat.getIntArgbInstance(), data, 0, width );
        ImageView imageView = new ImageView( writableImage );
        setImageViews( imageView, width, height, 300 );
        imageViews[ index ] = imageView;
        LOGGER.debug( "Height Map ImageView set." );
    }

    public void setImageViews( ImageView imageView )
    public static < T extends RealType< T > & NativeType< T > > int[] convertToGrays( IterableInterval< T > input, int width, int height )
    {
        imageView.setPreserveRatio( true );
        setFit( imageView );
        int[] data = new int[ height * width ];
        Cursor< T > cursor = input.cursor();
        int index = 0;
        while ( cursor.hasNext() )
        {
            int value = ( int ) cursor.next().getRealFloat();

            data[ index++ ] = ( 255 ) << 24 | ( 0xFF & value ) << 16 | ( 0xFF & value ) << 8 | ( 0xFF & value );
        }
        LOGGER.debug( "Height map data converted for construction display.");
        return data;
    }

    public static void setImageViews( ImageView imageView, int width, int height, int size )
    {
        imageView.setPreserveRatio( true );
        setFit( imageView, width, height , size);
        imageView.setSmooth( true );
        imageView.setCache( true );
    }

    public void setFit( ImageView imageView )
    public static void setFit( ImageView imageView, int width, int height, int size )
    {
        if ( width >= height )
        {
            imageView.setFitWidth( 254 );
            imageView.setFitWidth( size );
        }
        else
        {
            imageView.setFitHeight( 254 );
            imageView.setFitHeight( size );
        }
    }

    public static < T extends RealType< T > & NativeType< T > > Img< T > normalize( Img< T > input )
    {
        Img< T > normalizedImage = input.factory().create( input.dimensionsAsLongArray() );
        ImgUtil.copy( input, normalizedImage );
        T min = normalizedImage.firstElement().createVariable();
        min.setReal( 0 );
        T max = normalizedImage.firstElement().copy().createVariable();
        max.setReal( 255 );
        Normalize.normalize( normalizedImage, min, max );
        return normalizedImage;
    }

    /**
     * Creates a copy of an array of ImageView objects.
     *
     * Each ImageView in the new array is a separate instance
     * with the same image and properties as the original.
     *
     * @param original The original array of ImageView objects to copy.
     * @return A new array of ImageView objects with the same content.
     */
    public static ImageView[] copyImageViewArray(ImageView[] original) {
        if (original == null) {
            return null;
        }

        ImageView[] copy = new ImageView[original.length];
        for (int i = 0; i < original.length; i++) {
            if (original[i] != null) {
                ImageView originalView = original[i];
                ImageView newView = new ImageView(originalView.getImage());

                // Optional: Copy some properties
                newView.setFitWidth(originalView.getFitWidth());
                newView.setFitHeight(originalView.getFitHeight());
                newView.setPreserveRatio(originalView.isPreserveRatio());
                newView.setSmooth(originalView.isSmooth());

                copy[i] = newView;
            }
        }
        return copy;
    }
}
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ public class LogAppender extends AppenderBase< ILoggingEvent >
    protected void append( ILoggingEvent iLoggingEvent )
    {
        String level = iLoggingEvent.getLevel().toString();
        if ( level.equals( Level.INFO.toString() ) )
        if ( level.equals( Level.INFO.toString()) && iLoggingEvent.getMarker().contains( "GUI" ))
        {
            logMessage.setValue( iLoggingEvent.getFormattedMessage() );
        }
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ import org.scijava.log.LogService;
import org.scijava.plugin.Parameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;

import javax.swing.*;
import java.awt.*;
@@ -57,7 +59,7 @@ import java.util.ResourceBundle;
public class MainAppFrame extends JFrame
{

    private final static Logger LOGGER = LoggerFactory.getLogger( MainAppFrame.class );
    public static final Marker GUI_MARKER = MarkerFactory.getMarker("GUI");
    private ImageJ ij;
    private final ImageDisplayService image;
    @Parameter
@@ -86,15 +88,21 @@ public class MainAppFrame extends JFrame
     */
    public void setLogStatus()
    {
        LoggerContext lc = ( LoggerContext ) LoggerFactory.getILoggerFactory();
        PatternLayoutEncoder ple = new PatternLayoutEncoder();
        ple.setPattern( "%msg%n" );
        ple.setContext( lc );
        ple.start();
        LogAppender appender = new LogAppender();
        // Get the logger context
        LoggerContext context = ( LoggerContext ) LoggerFactory.getILoggerFactory();

        // Configure the log pattern
        PatternLayoutEncoder layout = new PatternLayoutEncoder();
        layout.setPattern( "%msg%n" );
        layout.setContext( context );
        layout.start();

        appender.setContext( lc );
        // Create and start the custom LogAppender
        LogAppender appender = new LogAppender();
        appender.setContext( context );
        appender.start();

        // Get the root logger and add the appender
        ch.qos.logback.classic.Logger logbackLogger =
                ( ch.qos.logback.classic.Logger ) LoggerFactory.getLogger( Logger.ROOT_LOGGER_NAME );
        logbackLogger.addAppender( appender );
@@ -102,7 +110,6 @@ public class MainAppFrame extends JFrame

    public MainAppFrame( Context context )
    {
//        this.ij = context.;
        this.image = context.getService( ImageDisplayService.class );
        this.logService = context.getService( LogService.class );
        this.setIconImages( ICONS );
@@ -160,21 +167,19 @@ public class MainAppFrame extends JFrame
        {
            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 );

            VBox 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() + 50 );
            controller.initExtraction();
//            controller.initExtraction();
        }
        catch ( IOException e )
        {
@@ -183,4 +188,6 @@ public class MainAppFrame extends JFrame
    }




}
Original line number Diff line number Diff line
@@ -29,7 +29,9 @@
package fr.pasteur.ida.zellige.gui;

import javafx.beans.NamedArg;
import javafx.beans.binding.NumberExpressionBase;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.Property;
import javafx.beans.property.StringProperty;
import javafx.css.PseudoClass;
import javafx.fxml.FXML;
@@ -134,6 +136,8 @@ public abstract class ParameterSlider extends GridPane
    }




    public void enable()
    {
        this.getSlider().setDisable( false );
@@ -186,6 +190,16 @@ public abstract class ParameterSlider extends GridPane
    {
        this.sliderProperty().set( value );
    }

    public Number getValue ()
    {
        return this.sliderProperty().getValue();
    }

    public String getName()
    {
        return name;
    }
}


Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui;

import javafx.beans.property.SimpleObjectProperty;
import net.imglib2.img.Img;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;

import java.util.ArrayList;

public class ProjectionProperties< T extends RealType< T > & NativeType< T > >
{


    private final SimpleObjectProperty< ArrayList< ChannelToolProperty<T> > > properties = new SimpleObjectProperty<>(new ArrayList<>());

    public ProjectionProperties( int channels)
    {
        for ( int i = 0; i < channels; i++ )
        {
            getProperties().get().add( new ChannelToolProperty<>() );
        }

    }

    public SimpleObjectProperty< ArrayList< ChannelToolProperty <T>> > getProperties()
    {
        return properties;
    }
}
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.Pane;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;

import java.io.IOException;

public class ReferenceSurfacePanel < T extends RealType< T > & NativeType< T > > extends Pane
{

    @FXML
    private TabPane channelTools;



    @FXML
    private Button run;

    private final ProjectionProperties<T> projectionProperties;


    public ReferenceSurfacePanel( int channels)
    {
        FXMLLoader fxmlLoader = new FXMLLoader( ReferenceSurfacePanel.class.getClassLoader().
                getResource( "fr.pasteur.ida.zellige.gui.view/ReferenceSurfacePanel.fxml" ) );
        fxmlLoader.setRoot(this);
        fxmlLoader.setController( this );
        try
        {
            fxmlLoader.load();
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
        for ( int i = 1; i <= channels; i++ )
        {
            Tab tab = new Tab( "C" + i );
            ChannelPanel pane = new ChannelPanel();
            tab.setContent( pane );
            getChannelTools().getTabs().add( tab );

        }
        projectionProperties =new ProjectionProperties<>( channels );
    }

    public TabPane getChannelTools()
    {
        return channelTools;
    }

    public Button getRun()
    {
        return run;
    }

    public ProjectionProperties< T > getProjectionProperties()
    {
        return projectionProperties;
    }
}
Original line number Diff line number Diff line
@@ -39,32 +39,25 @@ 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();
        }
    }

//    public StepPanel( @NamedArg( "name" ) String 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 );
    }
}
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui.controller;

import fr.pasteur.ida.zellige.Main;
import fr.pasteur.ida.zellige.ReferenceSurfaceExtraction;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class BatchModeDialog extends VBox implements Initializable
{
    @FXML
    private Button browse;

    @FXML
    private TextField filePathField; // TextField to display selected file path

    @FXML
    private Button run;

    public BatchModeDialog()
    {

        FXMLLoader fxmlLoader = new FXMLLoader( BatchModeDialog.class.getClassLoader().
                getResource( "fr.pasteur.ida.zellige.gui.view/BatchModeDialog.fxml" ) );
        fxmlLoader.setRoot(this);
        fxmlLoader.setController( this );
        try
        {
            fxmlLoader.load();
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
    }



    private File selectedFile; // Store the selected file

    // Handle Browse Button Click
    @FXML
    private void handleBrowse() {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Select File");

        // Set file filter (optional)
        fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Text Files", "*.csv"));

        // Open FileChooser
        Stage stage = (Stage) filePathField.getScene().getWindow();
        File file = fileChooser.showOpenDialog(stage);

        if (file != null) {
            selectedFile = file;
            filePathField.setText(file.getAbsolutePath());
        }
    }

    // Handle Run Button Click
    @FXML
    private void handleRun() throws Exception
    {
        if (selectedFile != null) {
            System.out.println("Running with file: " + selectedFile.getAbsolutePath());
            ReferenceSurfaceExtraction.run(selectedFile.getAbsolutePath());
            // Add logic to process the file
        } else {
            System.out.println("No file selected!");
        }
    }


    @Override
    public void initialize( URL url, ResourceBundle resourceBundle )
    {
        browse.setOnAction(e -> handleBrowse());
        run.setOnAction( e->
        {
            try
            {
                handleRun();
            }
            catch ( Exception ex )
            {
                throw new RuntimeException( ex );
            }
        } );
    }
}
Original line number Diff line number Diff line
@@ -28,14 +28,18 @@
 */
package fr.pasteur.ida.zellige.gui.controller;

import fr.pasteur.ida.zellige.gui.ParameterSliderDouble;
import fr.pasteur.ida.zellige.gui.ParameterSliderInteger;
import fr.pasteur.ida.zellige.gui.*;
import fr.pasteur.ida.zellige.gui.exception.NoParameterChangeException;
import fr.pasteur.ida.zellige.gui.exception.NoPixelSelectionException;
import fr.pasteur.ida.zellige.gui.interactor.ConstructionInteractor;
import fr.pasteur.ida.zellige.gui.model.ConstructionModel;
import fr.pasteur.ida.zellige.gui.parameter.ZelligeParameters;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import fr.pasteur.ida.zellige.gui.task.*;
import javafx.beans.property.*;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.image.ImageView;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import org.slf4j.Logger;
@@ -44,12 +48,17 @@ import org.slf4j.LoggerFactory;
import java.net.URL;
import java.util.ResourceBundle;

import static fr.pasteur.ida.zellige.gui.MainAppFrame.GUI_MARKER;
import static fr.pasteur.ida.zellige.gui.controller.MainController.showError;
import static fr.pasteur.ida.zellige.gui.controller.MainController.showInfo;
import static fr.pasteur.ida.zellige.gui.controller.SelectionController.setNextOutputToNull;

public class ConstructionController< T extends RealType< T > & NativeType< T > > implements Initializable
{
    private final static Logger LOGGER = LoggerFactory.getLogger( ConstructionController.class );

    private final SimpleBooleanProperty changedParameters = new SimpleBooleanProperty();
    private ConstructionModel< T > constructionModel;
    private MainController< T > parentController;

    @FXML
    private ParameterSliderDouble c1;
    @FXML
@@ -64,102 +73,233 @@ public class ConstructionController< T extends RealType< T > & NativeType< T > >
    private ParameterSliderDouble st2;
    @FXML
    private ParameterSliderInteger surfaceSize;
    @FXML
    private ConstructionDisplay constructionDisplay;
    @FXML
    private Button run;

    private final ConstructionInteractor< T > interactor = new ConstructionInteractor<>( new ConstructionModel< T >() );

    @Override
    public void initialize( URL url, ResourceBundle resourceBundle )
    {
        // model
        constructionModel = new ConstructionModel<>();

        //link Model with View
        constructionModel.c1Property().bind( c1.sliderProperty() );
        constructionModel.r1Property().bind( r1.sliderProperty() );
        constructionModel.st1Property().bind( st1.sliderProperty() );
        constructionModel.c2Property().bind( c2.sliderProperty() );
        constructionModel.r2Property().bind( r2.sliderProperty() );
        constructionModel.st2Property().bind( st2.sliderProperty() );
        constructionModel.surfaceSizeProperty().bind( surfaceSize.sliderProperty() );

        /* Component */
        ChangeListener< ? super Number > firstRoundListener = ( observable, oldValue, newValue ) ->
        {
            constructionModel.firstRoundSurfacesProperty().setValue( null );
            changedParameters.setValue( true );
        };
        c1.sliderProperty().addListener( firstRoundListener );
        r1.sliderProperty().addListener( firstRoundListener );
        st1.sliderProperty().addListener( firstRoundListener );
        surfaceSize.sliderProperty().addListener( firstRoundListener );
        ChangeListener< ? super Number > secondRoundListener = ( observable, oldValue, newValue ) ->
        {
            changedParameters.setValue( true );
            constructionModel.secondRoundSurfacesProperty().setValue( null );
        };
        c2.sliderProperty().addListener( secondRoundListener );
        r2.sliderProperty().addListener( secondRoundListener );
        st2.sliderProperty().addListener( secondRoundListener );
        surfaceSize.sliderProperty().addListener( secondRoundListener );
        /* Component behaviour */
        constructionDisplay.getMinus().setOnAction( actionEvent ->
        {
            constructionDisplay.previous();
            setDisplay();
        } );
        constructionDisplay.getPlus().setOnAction( actionEvent ->
        {
            constructionDisplay.next();
            setDisplay();
        } );

        run.setOnAction( actionEvent ->
        {
            runConstruction();
        } );


        /* Results which depend on a parameter are set to null when modified*/
        resetResultFromChangedParameterValue( getModel().c1Property(), getModel().firstRoundSurfacesProperty(), "First round connexity" );
        resetResultFromChangedParameterValue( getModel().r1Property(), getModel().firstRoundSurfacesProperty(), "First round overlap" );
        resetResultFromChangedParameterValue( getModel().st1Property(), getModel().firstRoundSurfacesProperty(), "First round starting threshold" );
        resetResultFromChangedParameterValue( getModel().surfaceSizeProperty(), getModel().firstRoundSurfacesProperty(), "Surface minimum size" );

        resetResultFromChangedParameterValue( getModel().c2Property(), getModel().secondRoundSurfacesProperty(), "Second round connexity" );
        resetResultFromChangedParameterValue( getModel().r2Property(), getModel().secondRoundSurfacesProperty(), "Second round overlap" );
        resetResultFromChangedParameterValue( getModel().st2Property(), getModel().secondRoundSurfacesProperty(), "Second round starting threshold" );
        resetResultFromChangedParameterValue( getModel().surfaceSizeProperty(), getModel().secondRoundSurfacesProperty(), "Surface minimum size" );

        /* Results that depend on another result are set to null when the latter is null */
        setNextOutputToNull( getModel().firstRoundSurfacesProperty(), getModel().secondRoundSurfacesProperty() );
        setNextOutputToNull( getModel().secondRoundSurfacesProperty(), getModel().referenceSurfacesProperty() );
        setNextOutputToNull( getModel().referenceSurfacesProperty(), getModel().getImageViews() );

        /* Properties*/
        constructionModel.maximumsProperty().addListener( ( observable, oldValue, newValue ) ->

        getModel().getDisableGUI().addListener( ( observable, oldValue, newValue ) ->
        {
            if ( newValue != null )
            if ( newValue )
            {
                LOGGER.debug( "Max is not null" );
                constructionModel.firstRound();
                disableParameters();
            }
            else
            {
                LOGGER.debug( "MAX is NULL" );
                constructionModel.firstRoundSurfacesProperty().setValue( null );
                enableParameters();
            }
        } );
        constructionModel.firstRoundSurfacesProperty().addListener( ( observableValue, surfaces, t1 ) ->

        getModel().firstRoundSurfacesProperty().addListener( ( observableValue, surfaces, newValue ) ->
        {
            if ( t1 == null )
            if ( newValue != null )
            {
                LOGGER.debug( "FIRST_ROUND_SURFACE  is NULL" );
                constructionModel.secondRoundSurfacesProperty().setValue( null );
                interactor.secondRound();
            }
        } );
        getModel().secondRoundSurfacesProperty().addListener( ( observableValue, surfaces, newValue ) ->
        {
            if ( newValue != null )
            {
                interactor.constructionCompletion();
            }
        } );

        getModel().referenceSurfacesProperty().addListener( ( observableValue, surfaces, newValue ) ->
        {
            if (newValue!= null && ! newValue.isEmpty() )
            {
                computeImageFXDisplay();
            }
            else
            {
                constructionModel.secondRound();
                LOGGER.debug( "There is no SURFACE!!!" );
            }
        } );
        constructionModel.secondRoundSurfacesProperty().addListener( ( observableValue, surfaces, t1 ) ->
    }

    private void checkParameters()
    {
        setParameterValue( c1, getModel().c1Property() );
        setParameterValue( r1, getModel().r1Property() );
        setParameterValue( st1, getModel().st1Property() );
        setParameterValue( c2, getModel().c2Property() );
        setParameterValue( r2, getModel().r2Property() );
        setParameterValue( st2, getModel().st2Property() );
        setParameterValue( surfaceSize, getModel().surfaceSizeProperty() );
    }


    private void setParameterValue( ParameterSlider slider, Property< Number > property )
    {
            if ( t1 == null )
        if ( ! property.getValue().equals( slider.getValue() ) )
        {
                LOGGER.debug( "SECOND_ROUND_SURFACE  is NULL" );
                constructionModel.referenceSurfacesProperty().setValue( null );
            LOGGER.debug( "model has changed with parameter {}, old value: {}, new value: {}", slider.getName(), property.getValue().doubleValue(), slider.getValue().doubleValue() );
            property.setValue( slider.getValue() );
            getModel().getParameterChanged().set( true );
        }
    }


    public void runConstruction()
    {
        checkParameters();
        if ( getModel().maximumsProperty().getValue() == null )
        {
            showError( new NoPixelSelectionException() );
        }
        else if ( ! getModel().getParameterChanged().getValue() && getModel().firstRoundSurfacesProperty().getValue() != null )
        {
            showInfo( new NoParameterChangeException() );
        }
        else
        {
                constructionModel.constructionCompletion();
            disableGUI( true );

            LOGGER.info(GUI_MARKER, "Running construction" );
            if ( getModel().maximumsProperty().getValue() != null )
            {
                if ( getModel().firstRoundSurfacesProperty().getValue() == null )
                {
                    interactor.firstRound();
                }
                else if ( getModel().secondRoundSurfacesProperty().get() == null )
                {
                    interactor.secondRound();
                }
            }
        }
    }


    public void computeImageFXDisplay()
    {
        ConstructionDisplayTask< T > task = new ConstructionDisplayTask<>( getModel().referenceSurfacesProperty().getValue() );
        task.setOnSucceeded( workerStateEvent ->
        {
            LOGGER.info(GUI_MARKER, "Construction display completed." );
            getModel().getImageViews().setValue( task.getValue() );
            ImageView[] imageViews = ImageFXDisplay.copyImageViewArray( task.getValue() );
            parentController.getProjectionController().getModel().getImageViews().set( imageViews );
            setDisplay();
            disableGUI( false );
        } );
        task.start();
    }

    public void setDisplay()
    {
        constructionDisplay.setNbOfSurfaces( getModel().referenceSurfacesProperty().get().size() );
        constructionDisplay.getDisplay().getChildren().clear();
        int index = constructionDisplay.getSurfaceNumber();
        ImageView i = getModel().getImageViews().getValue()[ index - 1 ];
        constructionDisplay.set( i, index );
        // setting of ZSlider

        disableGUI( false );
    }


    public ConstructionModel< T > getConstructionModel()
    public void resetResultFromChangedParameterValue( Property< Number > property, SimpleObjectProperty< ? > result, String parameterName )
    {
        property.addListener( ( observable, oldValue, newValue ) ->
        {
            if ( newValue != null )
            {
                LOGGER.info( "The {} parameter has been changed, old value:{}, new value: {}.", parameterName, oldValue, newValue );
            }
            if ( result.getValue() != null )
            {
        return constructionModel;
                result.set( null );
            }
        } );
    }

    public SimpleBooleanProperty changedParametersProperty()
    public void enableParameters()
    {
        return changedParameters;
        this.c1.enable();
        this.r1.enable();
        this.st1.enable();
        this.c2.enable();
        this.r2.enable();
        this.st2.enable();
        this.surfaceSize.enable();
    }

    public void disableParameters()
    {
        this.c1.disable();
        this.r1.disable();
        this.st1.disable();
        this.c2.disable();
        this.r2.disable();
        this.st2.disable();
        this.surfaceSize.disable();
    }


    public void setParameters( ZelligeParameters parameters )
    {
        st1.setValue( parameters.getSt1() );
        r1.setValue( parameters.getR1() );
        c1.setValue( parameters.getC1() );
        st2.setValue( parameters.getSt2() );
        r2.setValue( parameters.getR2() );
        c2.setValue( parameters.getC2() );
        surfaceSize.setValue( parameters.getSurfaceSize() );
        st1.setValue( parameters.getConstructionParameters()[0].getStartingSizeThreshold() );
        r1.setValue(  parameters.getConstructionParameters()[0].getOverlap());
        c1.setValue(  parameters.getConstructionParameters()[0].getConnexityRate() );
        st2.setValue( parameters.getConstructionParameters()[1].getStartingSizeThreshold() );
        r2.setValue(  parameters.getConstructionParameters()[1].getOverlap());
        c2.setValue(  parameters.getConstructionParameters()[1].getConnexityRate() );
        surfaceSize.setValue( parameters.getConstructionParameters()[0].getSurfaceMinSizeFactor() );
    }

    public ConstructionModel< T > getModel()
    {
        return interactor.getModel();
    }
    public void setParent( MainController< T > mainController )
    {
        parentController = mainController;
    }
    private void disableGUI( boolean value )
    {
        getModel().getDisableGUI().set( value );
    }
}
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui.controller;

import fr.pasteur.ida.zellige.gui.ReferenceSurfacePanel;
import fr.pasteur.ida.zellige.gui.exception.NoA3DStackException;
import fr.pasteur.ida.zellige.gui.exception.NoInputException;
import fr.pasteur.ida.zellige.gui.exception.TimeLapseException;
import fr.pasteur.ida.zellige.gui.interactor.PreprocessingInteractor;
import fr.pasteur.ida.zellige.gui.model.PreprocessingModel;
import fr.pasteur.ida.zellige.gui.parameter.ZelligeParameters;
import fr.pasteur.ida.zellige.gui.task.DisplayDatasetChoicesTask;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import net.imagej.Dataset;
import net.imagej.display.DatasetView;
import net.imagej.display.ImageDisplayService;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.display.ColorTable;
import net.imglib2.img.ImgFactory;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.view.Views;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;

import static fr.pasteur.ida.zellige.gui.controller.MainController.showError;
import static fr.pasteur.ida.zellige.utils.Util.create4dimImage;


public class PreprocessingController< T extends RealType< T > & NativeType< T > > implements Initializable
{

    private final static Logger LOGGER = LoggerFactory.getLogger( PreprocessingController.class );

    private MainController< T > parentController;

    @FXML
    private ComboBox< Dataset > activeDatasets;

    @FXML
    private Spinner< Integer > binValue;

    @FXML
    private Spinner< Integer > channelValue;

    @FXML
    private Label fileInfo;

    @FXML
    private Label userAdvice;


    private final BooleanProperty disableGUI = new SimpleBooleanProperty( false );

    private final PreprocessingInteractor< T > interactor;

    public PreprocessingController()
    {
        PreprocessingModel< T > model = new PreprocessingModel<>();
        this.interactor = new PreprocessingInteractor<>( model );
    }

    @Override
    @SuppressWarnings( "unchecked" )
    public void initialize( URL url, ResourceBundle resourceBundle )
    {
        /* Controls */
        // Bin Spinner*/
        SpinnerValueFactory< Integer > valueFactory = new SpinnerValueFactory.IntegerSpinnerValueFactory( 1, 10, 5 );
        binValue.setValueFactory( valueFactory );

        // Channel spinner
        SpinnerValueFactory< Integer > valueFactory2 = new SpinnerValueFactory.IntegerSpinnerValueFactory( 1, 5, 1, 1 );
        channelValue.setValueFactory( valueFactory2 );
        //TODO : remove not necessary
        channelValue.valueProperty().addListener( ( observable, oldValue, newValue ) -> LOGGER.debug( "The Channel spinner has changed!" ) );

        // Control of the files comboBox*/
        activeDatasets.setOnMousePressed( event -> setAndDisplayDatasetChoices() );// Update of the list of opened Fiji images

        // If a new dataset is selected...
        activeDatasets.getSelectionModel().selectedItemProperty().addListener( ( observableValue, oldValue, newValue ) ->
        {
            LOGGER.debug( "selectedItemProperty : old value = {}, new value = {} ", oldValue, newValue );
            if ( newValue != null && checkFile( newValue ) )
            {
                int index = activeDatasets.getSelectionModel().getSelectedIndex();
                setColorTable( index );

                // Set number of channels
                getModel().getNbOfChannels().set( ( int ) newValue.getChannels() );
                //Set the channel spinner behaviour
                final SpinnerValueFactory< Integer > valueFactory3 = new SpinnerValueFactory.IntegerSpinnerValueFactory( 1, getModel().getNbOfChannels().get() );
                channelValue.setValueFactory( valueFactory3 );

                //set the input
                if ( getModel().getNbOfChannels().get() == 1 )
                {
                    try
                    {
                        getModel().getInput().set( create4dimImage( newValue ) );
                    }
                    catch ( Exception e )
                    {
                        throw new RuntimeException( e );
                    }
                }
                else
                {
                    getModel().getInput().set( ( RandomAccessibleInterval< T > ) newValue.getImgPlus() );
                }
                // Set the input factory
                getModel().getFactory().setValue( ( ImgFactory< T > ) newValue.getImgPlus().factory() );

                // Sets the properties
                getModel().getParameterChanged().set( true );
                getModel().pretreatedImgProperty().setValue( null );

                // Update the default projection panel view
                StackPane stackPane = parentController.getProjectionController().getStackPane();
                stackPane.getChildren().clear();
                parentController.getProjectionController().getModel().getNumberOfChannels().set( getModel().getNbOfChannels().get() );
                ReferenceSurfacePanel panel = new ReferenceSurfacePanel( getModel().getNbOfChannels().get() );
                stackPane.getChildren().add( panel );
            }
            else
            {
                activeDatasets.getSelectionModel().selectLast(); //empty slot
            }
        } );

        disableGUI.addListener( ( observable, oldValue, newValue ) ->
        {
            if ( newValue )
            {
                disableParameters();
            }
            else
            {
                enableParameters();
            }
        } );

        /* Properties */
        getModel().getInput().addListener( ( observable, oldValue, newValue ) ->
        {
            if ( newValue != oldValue && newValue != null )
            {
                // Reset the input channel
                getModel().getInput_channel().set( null );
            }
        } );

        getModel().getInput_channel().addListener( ( observable, oldValue, newValue ) ->
        {
            if ( newValue != oldValue && newValue != null )
            {
                // Reset the input channel
                getModel().pretreatedImgProperty().set( null );
            }
        } );
    }

    public void setAndDisplayDatasetChoices()
    {
        DisplayDatasetChoicesTask displayTask = new DisplayDatasetChoicesTask( parentController.getMainAppFrame().getImage() );
        displayTask.setOnSucceeded( workerStateEvent ->
        {
            LOGGER.debug( "Datasets displayed successfully" );
            ObservableList< Dataset > list = FXCollections.observableArrayList( displayTask.getValue() );
//            list.add( null );
            activeDatasets.setItems( list );
            LOGGER.debug( "item selected : list size = {}", list.size() );
            if ( list.isEmpty() )
            {
                interactor.getModel().getInput().setValue( null );
                interactor.getModel().getFactory().setValue( null );
                LOGGER.debug( "CURRENT_DATASET is NULL" );
                showError( new NoInputException() );
            }
        } );
        displayTask.start();
    }

    /**
     * Finds and sets the input color tables.
     *
     * @param index the position of the input in the list of displayed datasets
     */
    public void setColorTable( int index )
    {
        ImageDisplayService imageDisplayService = parentController.getMainAppFrame().getImage();
        DatasetView datasetView = ( DatasetView ) imageDisplayService.getImageDisplays().get( index ).get( 0 );
        ArrayList< ColorTable > colorTables = new ArrayList<>( datasetView.getColorTables() );
        getModel().getColors().set( colorTables );
    }


    private boolean checkFile( Dataset dataset )
    {
        int nbDim = dataset.numDimensions();
        int nbSlices = ( int ) dataset.getDepth();
        int nbFrames = ( int ) dataset.getFrames();
        int nbChannels = ( int ) dataset.getChannels();
//        int pixelNb = (int) 0; //TODO set the pixel nb and add user advice for binning ?

        // Set the file info label
        String advice = "You go girl!";
        fileInfo.setText( "Nb Channels:   " + nbChannels + "      Nb z-slices:   " + nbSlices + "     Nb time-points: " + nbFrames );
        userAdvice.setText( advice );
        userAdvice.setTextFill( Color.RED );
        LOGGER.debug( "NUmber of dimensions: {}", nbDim );
        LOGGER.debug( "NUmber of channels: {}", getModel().getNbOfChannels().get() );
        LOGGER.debug( "Number of frames: {}", nbFrames );

        if ( nbFrames > 1 )
        {
            LOGGER.debug( "TimeLapseException" );
            showError( new TimeLapseException() );
            return false;
        }
        if ( nbSlices == 1 )
        {
            LOGGER.debug( "NoA3DStackException" );
            showError( new NoA3DStackException() );
            return false;
        }
        return true;
    }

    public void checkParameters()
    {
        if ( ! ( getModel().binProperty().get() == binValue.valueProperty().get() ) )
        {
            getModel().getInput_channel().set( null );
            getModel().getParameterChanged().setValue( true );
            getModel().binProperty().set( binValue.getValue() );

        }
        if ( ! ( interactor.getModel().getChannel().get() == channelValue.valueProperty().get() ) )
        {
            getModel().getParameterChanged().setValue( true );
            getModel().getChannel().set( channelValue.getValue() - 1 );
        }
        // Set the input channel
        if ( getModel().getInput().get() == null )
        {
            showError( new NoInputException() );
        }
        else
        {
            getModel().getInput_channel().set( Views.hyperSlice( getModel().getInput().get(), 2, getModel().getChannel().get() ) );
        }
    }

    private void disableParameters()
    {
        binValue.setDisable( true );
        channelValue.setDisable( true );
    }

    private void enableParameters()
    {
        binValue.setDisable( false );
        channelValue.setDisable( false );
    }

    public PreprocessingInteractor< T > getInteractor()
    {
        return interactor;
    }

    public void setParent( MainController< T > mainController )
    {
        parentController = mainController;
    }

    public BooleanProperty getDisableGUI()
    {
        return disableGUI;
    }

    public PreprocessingModel< T > getModel()
    {
        return interactor.getModel();
    }

    public void setParameters( ZelligeParameters parameters )
    {
        binValue.getValueFactory().setValue( parameters.getPretreatmentParameters().getBin() );
        channelValue.getValueFactory().setValue( parameters.getPretreatmentParameters().getChannel() );
    }
}
 No newline at end of file
Original line number Diff line number Diff line
@@ -28,226 +28,193 @@
 */
package fr.pasteur.ida.zellige.gui.controller;

import fr.pasteur.ida.zellige.gui.CheckBoxDisplay;
import fr.pasteur.ida.zellige.gui.ChannelPanel;
import fr.pasteur.ida.zellige.gui.ChannelToolProperty;
import fr.pasteur.ida.zellige.gui.ProjectionProperties;
import fr.pasteur.ida.zellige.gui.ReferenceSurfacePanel;
import fr.pasteur.ida.zellige.gui.interactor.ProjectionInteractor;
import fr.pasteur.ida.zellige.gui.model.ProjectionModel;
import fr.pasteur.ida.zellige.gui.parameter.ZelligeParameters;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import fr.pasteur.ida.zellige.steps.projection.ProjectionParameters;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
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.ArrayList;
import java.util.ResourceBundle;

public class ProjectionController< T extends RealType< T > & NativeType< T > > implements Initializable
{

    private final static Logger LOGGER = LoggerFactory.getLogger( ProjectionController.class );
    private final SimpleBooleanProperty changedParameters = new SimpleBooleanProperty();
    @FXML
    private Spinner< Integer > delta1;
    @FXML
    private ComboBox< String > methodComboBox;
    @FXML
    private CheckBoxDisplay extractedHeightMap;
    @FXML
    private CheckBoxDisplay segmentedSurface;

    private MainController< T > parentController;


    @FXML
    private CheckBoxDisplay reduced3DSpace;
    private StackPane stackPane;

    @FXML
    private CheckBoxDisplay segmentedSurfaceMask;
    private FlowPane display;

    @FXML
    private CheckBoxDisplay projection;
    private Button displayRS;

    @FXML
    private CheckBoxDisplay rawHeightMap;
    private Label log;

    @FXML
    private Spinner< Integer > delta2;
    private ChoiceBox< String > referenceSurfacesList;

    private ProjectionModel< T > model;
    private final SimpleIntegerProperty currentIndex = new SimpleIntegerProperty( 0 );
    private final ProjectionInteractor< T > interactor;

    @Override
    public void initialize( URL url, ResourceBundle resourceBundle )
    public ProjectionController()
    {
        // Model
        model = new ProjectionModel<>();

        //link Model with View
        model.methodProperty().bind( methodComboBox.valueProperty() );
        model.delta1Property().bind( delta1.valueProperty() );
        model.delta2Property().bind( delta2.valueProperty() );
        bindCheckBox( model.rawHMProperty(), model.rawHMDisplayProperty(), rawHeightMap );
        bindCheckBox( model.projectionProperty(), model.projectionDisplayProperty(), projection );
        bindCheckBox( model.extractedHMProperty(), model.extractedHMDisplayProperty(), extractedHeightMap );
        bindCheckBox( model.reduced3DspaceProperty(), model.reduced3DspaceDisplayProperty(), reduced3DSpace );
        bindCheckBox( model.segmentedSurfaceProperty(), model.segmentedSurfaceDisplayProperty(), segmentedSurface );
        bindCheckBox( model.segmentedSurfaceMaskProperty(), model.segmentedSurfaceMaskDisplayProperty(), segmentedSurfaceMask );


        /* Components*/
        SpinnerValueFactory< Integer > valueFactory =
                new SpinnerValueFactory.IntegerSpinnerValueFactory( 1, 30, 0 );
        delta1.setValueFactory( valueFactory );
        ObservableList< String > list = FXCollections.observableArrayList( "MIP", "Mean" );
        methodComboBox.setItems( list );
        methodComboBox.getSelectionModel().selectFirst();
        SpinnerValueFactory< Integer > valueFactory2 =
                new SpinnerValueFactory.IntegerSpinnerValueFactory( 1, 30, 0 );
        delta2.setValueFactory( valueFactory2 );

        delta1.valueProperty().addListener( ( observableValue, integer, t1 ) ->
        {
            model.delta1FunctionsProperty().setValue( false );
            resetDisplayMode();
            changedParameters.setValue( true );
        } );
        ProjectionModel< T > model = new ProjectionModel<>();
        this.interactor = new ProjectionInteractor<>( model );
    }

        delta2.valueProperty().addListener( ( observableValue, integer, t1 ) ->
    @Override
    public void initialize( URL url, ResourceBundle resourceBundle )
    {
            model.delta2FunctionsProperty().setValue( false );
            segmentedSurfaceMask.enable();
            changedParameters.setValue( true );
        } );


        projection.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
        getModel().getImageViews().addListener( ( observableValue, number, newValue ) ->
                {
            if ( model.delta1FunctionsProperty().getValue() && t1 && projection.isNotDisplayed() )
                    if ( newValue != null )
                    {

                model.showProjections();
                        getModel().getReferenceSurfaces().
                                set( parentController.getConstructionController().getModel().referenceSurfacesProperty().get() );
                    }
        } );
                }
        );

        rawHeightMap.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
        // Listening of the reference surface choiceBox
        referenceSurfacesList.getSelectionModel().selectedIndexProperty().addListener( ( observableValue, number, newValue ) ->
        {
            if ( model.delta1FunctionsProperty().getValue() && t1 && rawHeightMap.isNotDisplayed() )
            if ( newValue.intValue() != -1 )
            {
                model.showRawHeightMap();

                currentIndex.set( newValue.intValue() );
                LOGGER.debug( "Checking Reference surface n°{}", currentIndex.get() );
                setDisplay();
                setProjectionPane();
            }
        } );
        extractedHeightMap.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
        {
            if ( model.delta1FunctionsProperty().getValue() && t1 && extractedHeightMap.isNotDisplayed() )
            {

                model.showExtractedHeightMaps();
            }
        } );
        reduced3DSpace.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
        getModel().getReferenceSurfaces().addListener( ( observableValue, number, newValue ) ->
        {
            if ( model.delta1FunctionsProperty().getValue() && t1 && reduced3DSpace.isNotDisplayed() )
            if ( newValue != null )
            {

                model.showReduced3DSpace();
            }
        } );
        segmentedSurface.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
                listsInitialization();
                // Removes default projection pane
                stackPane.getChildren().clear();
                int channels = parentController.getPreprocessingController().getModel().getNbOfChannels().get();
                for ( int i = 0; i < getModel().getReferenceSurfaces().get().size(); i++ )
                {
            if ( model.delta1FunctionsProperty().getValue() && t1 && segmentedSurface.isNotDisplayed() )
                    // sets a new projection panel according to the input channel number.
                    ReferenceSurfacePanel< T > panel = new ReferenceSurfacePanel<>( channels );
                    // Adding properties to each reference surfaces
                    getModel().getProjectionProperties().get().add( panel.getProjectionProperties() );
                    stackPane.getChildren().add( panel );
                    panel.getRun().setOnAction( actionEvent ->
                    {

                model.showSegmentedSurface();
            }
                        interactor.setParameters( panel );
                        interactor.runProjection( currentIndex.get() );
                    } );
        segmentedSurfaceMask.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
                    for ( int j = 0; j < panel.getChannelTools().getTabs().size(); j++ )
                    {
            if ( model.delta2FunctionsProperty().getValue() && t1 && segmentedSurfaceMask.isNotDisplayed() )
                        final int channel = j;
                        ChannelPanel channelPanel = ( ChannelPanel ) panel.getChannelTools().getTabs().get( j ).getContent();
                        channelPanel.getView().setOnAction( actionEvent ->
                        {

                model.showSegmentedSurfaceMask();
                            LOGGER.debug( "The view button has been pressed" );
                            interactor.setParameters( currentIndex.intValue(),
                                    channel, channelPanel.getDeltaZ().getValue(),
                                    channelPanel.getOffset().getValue(), channelPanel.getMethod().getValue() );
                            interactor.runSubVolume( currentIndex.intValue(), channel );
                        } );
                    }
                }
                referenceSurfacesList.getSelectionModel().selectFirst();
            }
        });

        // Model Properties
        model.referenceSurfacesProperty().addListener( ( observableValue, referenceSurfaces1, t1 ) ->
        {
            if ( t1 == null )
            {
                model.delta1FunctionsProperty().setValue( false );
                LOGGER.debug( "REFERENCE_SURFACES  is NULL" );

        /* Components*/
        displayRS.setOnAction( actionEvent -> interactor.displayHM( currentIndex.intValue() ) );
    }
            else

    public void setDisplay()
    {
                LOGGER.info( "Extraction of {} surfaces", model.referenceSurfacesProperty().getValue().size() );
                LOGGER.debug( "Compute output delta1" );
                model.setOutputDelta1();
                resetDisplayMode();
        display.getChildren().clear();
        ImageView i = getModel().getImageViews().getValue()[ currentIndex.get() ];
        display.getChildren().add( i );
        // setting of ZSlider
    }
        } );

        model.delta1FunctionsProperty().addListener( ( observableValue, aBoolean, t1 ) ->
    public void setProjectionPane()
    {
            if ( ! t1 )
        int length = stackPane.getChildren().size();
        for ( int i = 0; i < length; i++ )
        {
                LOGGER.debug( "DELTA1_FUNCTIONS is NULL" );
                model.delta2FunctionsProperty().setValue( false );
            Node node = stackPane.getChildren().get( i );
            node.setVisible( i == currentIndex.get() );
        }
            else
            {
                LOGGER.debug( "Compute output delta2" );
                model.setOutputDelta2();
        LOGGER.debug( "Displaying channel panel n°{}\n", ( currentIndex.get() + 1 ) );
    }
        } );

        model.delta2FunctionsProperty().addListener( ( observable, oldValue, newValue ) ->

    private void listsInitialization()
    {
            if ( newValue )
        ArrayList< String > names = new ArrayList<>();
        if ( ! getModel().getReferenceSurfaces().get().isEmpty() )
        {
                model.showOutput();
            }
            else
            getModel().getReferenceSurfaces().get().forEach( rf ->
            {
                LOGGER.debug( "DELTA2_FUNCTIONS is NULL" );
            }
                // Creates the names
                names.add( rf.getName() );
            } );
            // Clears the ChoiceBox
            referenceSurfacesList.getItems().clear();
            // Fills the ChoiceBox
            referenceSurfacesList.getItems().addAll( names );
            // Display the first reference surface
//            display.getChildren().clear();
//            display.getChildren().add( getModel().getImageViews().get()[ 0 ] );


        }
    }


    private void resetDisplayMode()
    public void setParent( MainController< T > mainController )
    {
        extractedHeightMap.enable();
        projection.enable();
        segmentedSurface.enable();
        rawHeightMap.enable();
        reduced3DSpace.enable();
        segmentedSurfaceMask.enable();


        parentController = mainController;
    }

    public SimpleBooleanProperty changedParametersProperty()
    {
        return changedParameters;
    }

    public ProjectionModel< T > getModel()
    {
        return model;
        return interactor.getModel();
    }


    private void bindCheckBox( BooleanProperty selected, BooleanProperty notDisplayed, CheckBoxDisplay checkBox )
    public StackPane getStackPane()
    {
        selected.bind( checkBox.selectedProperty() );
        notDisplayed.bindBidirectional( checkBox.notDisplayedProperty() );
        return stackPane;
    }

    public void setParameters( ZelligeParameters parameters )
    {
        delta1.getValueFactory().setValue( parameters.getDelta1() );
        delta2.getValueFactory().setValue( parameters.getDelta2() );
        methodComboBox.getSelectionModel().select( parameters.getMethod() );
        ArrayList< ProjectionParameters > projectionParameters = parameters.getProjectionParameters();
        //TODO Dynamic loading ?
    }
}
Original line number Diff line number Diff line
@@ -28,21 +28,25 @@
 */
package fr.pasteur.ida.zellige.gui.controller;

import fr.pasteur.ida.zellige.gui.ParameterSlider;
import fr.pasteur.ida.zellige.gui.ParameterSliderInteger;
import fr.pasteur.ida.zellige.gui.ZSlicesSlider;
import fr.pasteur.ida.zellige.gui.exception.NoParameterChangeException;
import fr.pasteur.ida.zellige.gui.interactor.SelectionInteractor;
import fr.pasteur.ida.zellige.gui.model.SelectionModel;
import fr.pasteur.ida.zellige.gui.parameter.ZelligeParameters;
import fr.pasteur.ida.zellige.gui.task.ImageFXDisplayTask;
import fr.pasteur.ida.zellige.gui.task.*;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.image.ImageView;
import javafx.scene.layout.FlowPane;
import net.imglib2.img.Img;
import net.imglib2.type.NativeType;
import net.imglib2.type.logic.BitType;
import net.imglib2.type.numeric.RealType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,14 +54,19 @@ import org.slf4j.LoggerFactory;
import java.net.URL;
import java.util.ResourceBundle;

import static fr.pasteur.ida.zellige.gui.MainAppFrame.GUI_MARKER;
import static fr.pasteur.ida.zellige.gui.controller.MainController.showInfo;


public class SelectionController< T extends RealType< T > & NativeType< T > > implements Initializable
{
    private final static Logger LOGGER = LoggerFactory.getLogger( SelectionController.class );


    private final SimpleBooleanProperty changedParameters = new SimpleBooleanProperty();
    //private final SimpleBooleanProperty changedParameters = new SimpleBooleanProperty();
    private final SimpleBooleanProperty disableGUI = new SimpleBooleanProperty();
    private SelectionModel selectionModel;

    private MainController< T > parentController;

    @FXML
    private ParameterSliderInteger amplitude;
@@ -73,180 +82,234 @@ public class SelectionController< T extends RealType< T > & NativeType< T > > im
    private ParameterSliderInteger zBlur;
    @FXML
    private ZSlicesSlider zSlices;
    @FXML
    private Button run;

    private final SelectionInteractor interactor = new SelectionInteractor( new SelectionModel() );


    @Override
    public void initialize( URL url, ResourceBundle resourceBundle )
    {
        // model
        selectionModel = new SelectionModel();

        //link Model with View
        selectionModel.amplitudeProperty().bind( amplitude.sliderProperty() );
        selectionModel.otsuProperty().bind( otsu.sliderProperty() );
        selectionModel.islandProperty().bind( island.sliderProperty() );
        selectionModel.xyBlurProperty().bind( xyBlur.sliderProperty() );
        selectionModel.zBlurProperty().bind( zBlur.sliderProperty() );
        selectionModel.disableGUIProperty().bindBidirectional( disableGUI );
                /* JavaFx Components */

        /* Amplitude slider initialization */
        // Update the log when a slider is used
        parameterListening( amplitude, "Amplitude" );
        parameterListening( otsu, "Otsu" );
        parameterListening(island, "Island Search" );
        parameterListening( xyBlur, "XY Blur" );
        parameterListening( zBlur, "Z Blur" );

        amplitude.sliderProperty().addListener( ( observableValue, number, newValue ) ->
        stack.setAlignment( Pos.CENTER );

        // section Slider initialization
        zSlices.getSlider().valueProperty().addListener( ( observableValue, number, newValue ) ->
        {
            if ( amplitude.hasChanged( newValue ) && selectionModel.selectedAmplitudeProperty().getValue() != null )
            int newZValue = newValue.intValue();
            if ( zSlices.hasChanged( newZValue ) )
            {
                disableGUI.setValue( true );
                selectionModel.runAmplitudeTask();
                changedParameters.setValue( true );
                LOGGER.debug( "Slice n° {} is displayed.", newZValue );
                refreshDisplay( newZValue );
            }
        } );

        /* Otsu slider initialization */
        otsu.sliderProperty().addListener( ( observableValue, number, newValue ) ->
        run.setOnAction( actionEvent ->
        {
            if ( otsu.hasChanged( newValue ) && selectionModel.selectedOtsuProperty().getValue() != null )

            run();
        } );

        /* Properties */
        // Set the linked output to null when the related parameter value has changed.
        resetOutputFromParameter( getModel().selectedAmplitudeProperty(), getModel().amplitudeProperty() );
        resetOutputFromParameter( getModel().selectedOtsuProperty(), getModel().otsuProperty() );
        resetOutputFromParameter( getModel().islandSearchImageProperty(), getModel().islandProperty() );
        resetOutputFromParameter( getModel().selectedPixelsProperty(), getModel().zBlurProperty() );
        resetOutputFromParameter( getModel().selectedPixelsProperty(), getModel().xyBlurProperty() );


        disableGUI.addListener( ( observable, oldValue, newValue ) ->
        {
                disableGUI.setValue( true );
                selectionModel.runOtsuTask();
                changedParameters.setValue( true );
            if ( newValue )
            {
                disableParameters();
            }
            else
            {
                enableParameters();
            }
        } );

        island.getSlider().valueProperty().addListener( ( observableValue, number, t1 ) ->
        /* Chain reaction : if one parameter value is changed the following outputs are reset. */
        setNextOutputToNull( getModel().pretreatedImgProperty(), getModel().imagesProperty() );

        setNextOutputToNull( getModel().imagesProperty(), getModel().selectedAmplitudeProperty() );
        setNextOutputToNull( getModel().imagesProperty(), getModel().selectedOtsuProperty() );

        setNextOutputToNull( getModel().selectedAmplitudeProperty(), getModel().interClassifiedImageProperty() );
        setNextOutputToNull( getModel().selectedOtsuProperty(), getModel().interClassifiedImageProperty() );

        setNextOutputToNull( getModel().interClassifiedImageProperty(), getModel().islandSearchImageProperty() );


        setNextOutputToNull( getModel().islandSearchImageProperty(), getModel().selectedPixelsProperty() );

        setNextOutputToNull( getModel().selectedPixelsProperty(), getModel().imageViewsProperty() );

        getModel().pretreatedImgProperty().addListener( ( observableValue, number, newValue ) ->
        {
            if ( island.hasChanged( t1 ) )
            LOGGER.debug( "Pretreated image value update." );
            if ( getModel().pretreatedImgProperty().getValue() != null )
            {
                selectionModel.setIslandSearchImage( null );
                changedParameters.setValue( true );
                LOGGER.debug( " Update value is valid : starting computing classified images" );
                interactor.computeClassifiedImages();
            }
        } );

        xyBlur.sliderProperty().addListener( ( observable, oldValue, newValue ) ->
        getModel().imagesProperty().addListener( ( observableValue, number, newValue ) ->
        {
            if ( xyBlur.hasChanged( newValue ) )
            if ( newValue != null )
            {
                selectionModel.setSelectedPixels( null );
                changedParameters.setValue( true );

                interactor.runAmplitudeTask();
                interactor.runOtsuTask();
            }
        } );
        zBlur.sliderProperty().addListener( ( observable, oldValue, newValue ) ->

        getModel().selectedAmplitudeProperty().addListener( ( observableValue, number, newValue ) ->
        {
            if ( zBlur.hasChanged( newValue ) )
            if ( newValue != null && getModel().selectedOtsuProperty().getValue() != null )
            {
                selectionModel.setSelectedPixels( null );
                changedParameters.setValue( true );
                interactor.runInterClassification();
            }
        } );
        stack.setAlignment( Pos.CENTER );

        // section Slider initialization
        zSlices.getSlider().valueProperty().addListener( ( observableValue, number, newValue ) ->
        getModel().selectedOtsuProperty().addListener( ( observableValue, number, newValue ) ->
        {
            int newZValue = newValue.intValue();
            if ( zSlices.hasChanged( newZValue ) )
            if ( newValue != null && getModel().selectedAmplitudeProperty().getValue() != null )
            {
                refreshDisplay( newZValue );
                interactor.runInterClassification();
            }
        } );

        /* Properties */

        disableGUI.addListener( ( observable, oldValue, newValue ) ->
        getModel().interClassifiedImageProperty().addListener( ( observableValue, number, newValue ) ->
        {
            if ( newValue )
            if ( newValue != null )
            {
                disableParameters();
                interactor.runIslandSearch();
            }
            else
        } );

        getModel().islandSearchImageProperty().addListener( ( observableValue, number, newValue ) ->
        {
                enableParameters();
            if ( newValue != null )
            {
                interactor.runSmoothing();
            }
        } );
        selectionModel.imagesProperty().addListener( ( observableValue, classifiedImages, t1 ) ->

        getModel().selectedPixelsProperty().addListener( ( observableValue, number, newValue ) ->
        {
            if ( t1 != null )
            if ( newValue != null )
            {
                selectionModel.runAmplitudeTask();
                selectionModel.runOtsuTask();
                computeImageFXDisplay();
            }
            else
            {
                LOGGER.debug( "IMAGES is NULL" );
                selectionModel.selectedAmplitudeProperty().setValue( null );
                selectionModel.selectedOtsuProperty().setValue( null );
                selectionModel.interClassifiedImageProperty().setValue( null );
        } );
    }

        } );
        ChangeListener< Img< BitType > > listener = ( observableValue, bitTypeClassifiedImages, t1 ) ->


    public void run()
    {
            if ( selectionModel.selectedAmplitudeProperty().getValue() != null && selectionModel.selectedOtsuProperty().getValue() != null )
        parentController.getPreprocessingController().checkParameters();
        checkParameters();
        if (! parentController.getPreprocessingController().getInteractor().getModel().getParameterChanged().get() && ! getModel().getParameterChanged().get())
        {
                selectionModel.runInterClassification();
                LOGGER.debug( "Inter classification" );
            showInfo( new NoParameterChangeException() );
        }
        else
        {
                LOGGER.debug( "SELECTED_AMPLITUDE or SELECTED_OTSU is NULL" );
                selectionModel.interClassifiedImageProperty().setValue( null );
            if ( getModel().pretreatedImgProperty().getValue() == null  )
            {
                disableGUI.setValue( true );
                parentController.getPreprocessingController().getInteractor().runPreprocessing();
            }

        };

        selectionModel.selectedAmplitudeProperty().addListener( listener );
        selectionModel.selectedOtsuProperty().addListener( listener );


        selectionModel.interClassifiedImageProperty().addListener( ( observable, oldValue, newValue ) ->
            else if ( getModel().selectedAmplitudeProperty().getValue() == null || getModel().selectedOtsuProperty().getValue() == null )
            {
            LOGGER.info( "Computing double classification..." );
            if ( newValue != null )
                disableGUI.setValue( true );
                if ( getModel().selectedAmplitudeProperty().getValue() == null )
                {
                computeImageFXDisplay();
                    interactor.runAmplitudeTask();
                }
            selectionModel.islandSearchImageProperty().setValue( null );
        } );

        selectionModel.islandSearchImageProperty().addListener( ( observableValue, bitTypes, t1 ) ->
                if ( getModel().selectedOtsuProperty().getValue() == null )
                {
            if ( t1 == null )
                    interactor.runOtsuTask();
                }
            }
            else if (getModel().islandSearchImageProperty().getValue() == null )
            {
                LOGGER.debug( "ISLAND_SEARCH is NULL" );
                selectionModel.selectedPixelsProperty().setValue( null );
                disableGUI.setValue( true );
                interactor.runIslandSearch();
            }
            else
            else if ( getModel().selectedPixelsProperty().getValue() == null )
            {
                selectionModel.runSmoothing();
                disableGUI.setValue( true );
                interactor.runSmoothing();
            }
        }
        } );
    }

    private void checkParameters()
    {
        setParameterValue( amplitude, getModel().amplitudeProperty() );
        setParameterValue( otsu, getModel().otsuProperty() ) ;
        setParameterValue( island, getModel().islandProperty() );
        setParameterValue( xyBlur, getModel().xyBlurProperty() );
        setParameterValue( zBlur, getModel().zBlurProperty() ) ;
    }




    private void setParameterValue( ParameterSlider slider, IntegerProperty property)
    {
        if ( !property.getValue().equals( slider.getValue()))
        {
            LOGGER.debug( "model has changed with parameter {}", slider.getName() );
            property.setValue( slider.getValue() );
           getModel().getParameterChanged().set( true );
        }
    }

    public void computeImageFXDisplay()
    {
        ImageFXDisplayTask imageFXDisplayTask = new ImageFXDisplayTask( selectionModel.interClassifiedImageProperty() );
        imageFXDisplayTask.setOnSucceeded( workerStateEvent ->
        SelectionDisplayTask selectionDisplayTask = new SelectionDisplayTask( getModel().selectedPixelsProperty().getValue() );
        selectionDisplayTask.setOnSucceeded( workerStateEvent ->
        {
            LOGGER.info( "Double classification done." );
            selectionModel.imageViewsProperty().setValue( imageFXDisplayTask.getValue() );
            LOGGER.info( GUI_MARKER,"Double classification done!!!!!." );
            getModel().imageViewsProperty().setValue( selectionDisplayTask.getValue() );
            setDisplay();
        } );
        imageFXDisplayTask.start();
        selectionDisplayTask.start();
    }

    public void setDisplay()
    {
        stack.getChildren().clear();
        ImageView i = selectionModel.imageViewsProperty().getValue()[ zSlices.getUserValue() ];
        ImageView i = getModel().imageViewsProperty().getValue()[ zSlices.getUserValue() ];

        stack.getChildren().add( i );

        // setting of ZSlider
        this.setSliceNumber( ( int ) selectionModel.pretreatedImgProperty().getValue().dimension( 2 ) );
        this.setSliceNumber( ( int ) getModel().pretreatedImgProperty().getValue().dimension( 2 ) );
        int width = ( int ) i.boundsInParentProperty().get().getWidth();
        this.zSlices.getSlider().setMaxWidth( width );
        this.zSlices.getSlider().setVisible( true );

        // reset everything
        disableGUI.setValue( false );
        getModel().getParameterChanged().set( false );
        parentController.getPreprocessingController().getModel().getParameterChanged().set( false );
    }


@@ -258,7 +321,7 @@ public class SelectionController< T extends RealType< T > & NativeType< T > > im
    public void refreshDisplay( int value )
    {
        this.stack.getChildren().clear();// Removal of previous slice
        ImageView i = selectionModel.imageViewsProperty().getValue()[ value ];
        ImageView i = getModel().imageViewsProperty().getValue()[ value ];
        stack.getChildren().add( i ); // display of selected z slice
    }

@@ -269,20 +332,27 @@ public class SelectionController< T extends RealType< T > & NativeType< T > > im

    public void set()
    {
        this.setSliceNumber( ( int ) selectionModel.pretreatedImgProperty().getValue().dimension( 2 ) );
        this.setSliceNumber( ( int ) getModel().pretreatedImgProperty().getValue().dimension( 2 ) );
    }

    public void enableParameters()
    {
        this.amplitude.enable();
        this.otsu.enable();

        this.island.enable();
        this.zBlur.enable();
        this.xyBlur.enable();
        this.stack.setVisible( true );
    }

    public void disableParameters()
    {
        this.amplitude.disable();
        this.otsu.disable();
        this.island.disable();
        this.zBlur.disable();
        this.xyBlur.disable();
        this.stack.setVisible( false );
    }


@@ -301,42 +371,66 @@ public class SelectionController< T extends RealType< T > & NativeType< T > > im
        return otsu;
    }

    public ParameterSliderInteger getXyBlur()
    public SimpleBooleanProperty disableGUIProperty()
    {
        return xyBlur;
        return disableGUI;
    }

    public ParameterSliderInteger getzBlur()
    public SelectionModel getModel()
    {
        return zBlur;
        return interactor.getModel();
    }

    public boolean isChangedParameters()



    public void setParameters( ZelligeParameters parameters )
    {
        return changedParameters.get();
        amplitude.setValue( parameters.getSelectionParameters().getAmplitude() );
        otsu.setValue( parameters.getSelectionParameters().getOtsu() );
        island.setValue( parameters.getSelectionParameters().getIsland() );
        xyBlur.setValue( parameters.getSelectionParameters().getXyBlur() );
        zBlur.setValue( parameters.getSelectionParameters().getzBlur() );
    }

    public SimpleBooleanProperty changedParametersProperty()
    public void setParent( MainController< T > mainController )
    {
        return changedParameters;
        parentController = mainController;
    }

    public SimpleBooleanProperty disableGUIProperty()
    public static void setNextOutputToNull( SimpleObjectProperty< ? > property, SimpleObjectProperty< ? > nextOutput )
    {
        return disableGUI;
        property.addListener( ( observable, oldValue, newValue ) ->
        {
            if ( newValue != oldValue && newValue == null )
            {
                LOGGER.debug( "Next output set to null...." );
                nextOutput.set( null );
            }
        } );
    }

    public SelectionModel getSelectionModel()
    private void parameterListening( ParameterSlider slider, String parameterName )
    {
        return selectionModel;
        slider.sliderProperty().addListener( ( observable, oldValue, newValue ) ->
        {
            if ( slider.hasChanged( newValue ) && newValue != null )
            {
                LOGGER.debug( "The {} parameter has been changed, new value: {}.", parameterName, newValue );
            }
        } );
        }

    public void setParameters( ZelligeParameters parameters )

    public void resetOutputFromParameter( SimpleObjectProperty< ? > result, IntegerProperty property )
    {
        amplitude.setValue( parameters.getAmplitude() );
        otsu.setValue( parameters.getOtsu() );
        island.setValue( parameters.getIsland() );
        xyBlur.setValue( parameters.getXyBlur() );
        zBlur.setValue( parameters.getzBlur() );
        property.addListener( ( observable, oldValue, newValue ) ->
                result.set( null ) );
    }


    public SimpleBooleanProperty getDisableGUI()
    {
        return disableGUI;
    }
}
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui.controller;

import javafx.beans.property.Property;

public class Utils
{

    public static void setPropertyValue ( Property<Number> controllerProperty, Property<Number> modelProperty )
    {
        modelProperty.setValue( controllerProperty.getValue());
    }
}
Original line number Diff line number Diff line
@@ -31,7 +31,9 @@ package fr.pasteur.ida.zellige.gui.exception;
public class NoInputException extends Exception
{

    final String message = " No 3D stack loaded on ImageJ";
    final String message = "Oops! No Image Loaded\n" +
            "Before running the program, please load an image on Zellige (Input File) .\n" +
            "We need it to work our magic! ✨ ";

    @Override
    public String getMessage()
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui.exception;

public class NoPixelSelectionException extends Exception
{

    final String message = " No Pixel Selection previously performed, please select pixels first (//TODO : new message) ";

    @Override
    public String getMessage()
    {
        return message;
    }
}
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui.interactor;

import fr.pasteur.ida.zellige.element.ReferenceSurface;
import fr.pasteur.ida.zellige.element.Surface;
import fr.pasteur.ida.zellige.gui.model.ConstructionModel;
import fr.pasteur.ida.zellige.gui.task.AbstractTask;
import fr.pasteur.ida.zellige.gui.task.ConstructionCompletionTask;
import fr.pasteur.ida.zellige.gui.task.RunFirstConstructionTask;
import fr.pasteur.ida.zellige.gui.task.RunSecondConstructionTask;
import fr.pasteur.ida.zellige.steps.construction.exception.FirstRoundConstructionException;
import fr.pasteur.ida.zellige.steps.construction.exception.SecondRoundConstructionException;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;

import static fr.pasteur.ida.zellige.gui.MainAppFrame.GUI_MARKER;
import static fr.pasteur.ida.zellige.gui.controller.MainController.showError;

public class ConstructionInteractor< T extends RealType< T > & NativeType< T > >

{

    Logger LOGGER = LoggerFactory.getLogger( ConstructionInteractor.class );

    private final ConstructionModel< T > model;

    public ConstructionInteractor( ConstructionModel< T > model )
    {
        this.model = model;
    }

    public void firstRound()
    {
        AbstractTask< ArrayList< Surface > > firstRoundTask =
                new RunFirstConstructionTask(
                        model.maximumsProperty().get(),
                        model.st1Property().get(),
                        model.r1Property().get(),
                        model.c1Property().get(),
                        model.surfaceSizeProperty().get() / 100.0 );
        firstRoundTask.setOnSucceeded( workerStateEvent ->
        {
            model.firstRoundSurfacesProperty().setValue( firstRoundTask.getValue() );
            if ( firstRoundTask.getValue() == null )
            {
                model.getDisableGUI().set( false );
                showError( new FirstRoundConstructionException() );
            }
        } );
        firstRoundTask.start();
    }

    public void secondRound()
    {
        LOGGER.info( GUI_MARKER,"Computing second round construction..." );
        if ( model.firstRoundSurfacesProperty().getValue() != null )
        {
            AbstractTask< ArrayList< Surface > > secondRoundTask = new RunSecondConstructionTask(
                    model.firstRoundSurfacesProperty().getValue(),
                    model.st2Property().get(),
                    model.r2Property().get(),
                    model.c2Property().get(),
                    model.surfaceSizeProperty().get() / 100.0 );
            secondRoundTask.setOnSucceeded( workerStateEvent ->
            {
                model.secondRoundSurfacesProperty().setValue( secondRoundTask.getValue() );
                if ( secondRoundTask.getValue() == null )
                {
                    model.getDisableGUI().set( false );
                    showError( new SecondRoundConstructionException() );
                }
                else
                {
                    LOGGER.info(GUI_MARKER, "Second round construction done." );
                }
            } );

            secondRoundTask.start();
        }
    }


    public void constructionCompletion()
    {

        AbstractTask< ArrayList< ReferenceSurface< T > > > constructionCompletionTask = new ConstructionCompletionTask<>( model.getInput().getValue(), model.getFactory().getValue(), model.secondRoundSurfacesProperty().get() , model.getBin().get());
        constructionCompletionTask.setOnSucceeded( workerStateEvent ->
                model.referenceSurfacesProperty().setValue( constructionCompletionTask.getValue() ) );
        constructionCompletionTask.start();
    }

    public ConstructionModel< T > getModel()
    {
        return model;
    }
}
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui.interactor;

import fr.pasteur.ida.zellige.gui.exception.NoSelectedInputException;
import fr.pasteur.ida.zellige.gui.model.PreprocessingModel;
import fr.pasteur.ida.zellige.gui.task.AbstractTask;
import fr.pasteur.ida.zellige.gui.task.PreprocessingTask;
import net.imglib2.img.Img;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.numeric.real.FloatType;

import static fr.pasteur.ida.zellige.gui.controller.MainController.showError;

public class PreprocessingInteractor < T extends RealType< T > & NativeType< T > >
{
    private final PreprocessingModel<T> model;

    public PreprocessingInteractor( PreprocessingModel<T> model )
    {
        this.model = model;
    }


    public boolean runPreprocessing()
    {
        if (model.getInput_channel() == null )
        {
            showError( new NoSelectedInputException() );
            return false;
        }
        else
        {
//            if (  model.getParameterChanged().get() ) // if parameters has been modified
            {
                AbstractTask< Img< FloatType > > task = new PreprocessingTask<>(model.getInput_channel().getValue(), 2, model.binProperty().get() );
                task.setOnSucceeded( workerStateEvent ->
                        model.pretreatedImgProperty().set( task.getValue() ) );
                task.start();
                return true;
            }
        }
//        return true;
    }

    public PreprocessingModel <T> getModel()
    {
        return model;
    }
}
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui.interactor;

import fr.pasteur.ida.zellige.element.ReferenceSurface;
import fr.pasteur.ida.zellige.gui.ChannelPanel;
import fr.pasteur.ida.zellige.gui.ChannelToolProperty;
import fr.pasteur.ida.zellige.gui.ProjectionProperties;
import fr.pasteur.ida.zellige.gui.ReferenceSurfacePanel;
import fr.pasteur.ida.zellige.gui.model.ProjectionModel;
import fr.pasteur.ida.zellige.gui.task.ProjectionTask;
import fr.pasteur.ida.zellige.gui.task.SubVolumeTask;
import fr.pasteur.ida.zellige.steps.projection.ReferenceSurfaceProjection;
import ij.IJ;
import net.imagej.ImgPlus;
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.view.Views;
import org.scijava.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ProjectionInteractor< T extends RealType< T > & NativeType< T > >
{
    private final static Logger LOGGER = LoggerFactory.getLogger( ProjectionInteractor.class );
    private final ProjectionModel< T > model;

    public ProjectionInteractor( ProjectionModel< T > model )
    {
        this.model = model;
    }

    public void runProjection( int index )
    {
        ReferenceSurface< T > referenceSurface = model.getReferenceSurfaces().get().get( index );
        ProjectionProperties< T > properties = model.getProjectionProperties().get().get( index );
        ProjectionTask< T > task = new ProjectionTask<>( referenceSurface, properties );
        task.setOnSucceeded( workerStateEvent ->
        {
            LOGGER.debug( "The projection has succeed!" );
            // Wraps the projection inside an ImgPlus to display the colors if necessary.
            ImgPlus< T > imgPlus = ReferenceSurfaceProjection.setColorsAndName( task.getValue(), getModel().getColors().get(), "" );
            Context context = ( Context ) IJ.runPlugIn( "org.scijava.Context", "" );
            net.imagej.ImageJ ij = new net.imagej.ImageJ( context );
            ij.ui().show( imgPlus );
            //TODO find a way to retrieve ij instance
        } );
        task.setOnFailed( workerStateEvent -> LOGGER.debug( "The projection has failed!" ) );
        task.start();
    }

    public void runSubVolume( int index, int channel )
    {
        // Selection of the reference surface
        ReferenceSurface< T > referenceSurface = model.getReferenceSurfaces().get().get( index );
        // Selection of the properties associated
        ProjectionProperties< T > properties = model.getProjectionProperties().get().get( index );
        RandomAccessibleInterval< T > input = Views.hyperSlice( referenceSurface.getInput(), 2, channel );
        ChannelToolProperty< T > channelToolProperty = properties.getProperties().get().get( channel );
        if ( channelToolProperty.getSubVolume().get() == null )
        {
            int delta = channelToolProperty.getDeltaZ().get();
            int offset = channelToolProperty.getOffset().get();
            SubVolumeTask< T > task = new SubVolumeTask<>( input, referenceSurface.getFactory(), referenceSurface.getzMap(), delta, offset );
            task.setOnSucceeded( workerStateEvent ->
            {
                Img< T > subVolume = task.getValue();
                channelToolProperty.getSubVolume().set( subVolume );
                LOGGER.debug( "SubVolume dimensions:{}.", subVolume.dimensionsAsLongArray() );
                String title = String.format( "SubVolume_RS_%d_channel_%d", ( index + 1 ), ( channel + 1 ) );
                ImageJFunctions.show( subVolume, title );
            } );
            task.setOnFailed( workerStateEvent -> LOGGER.debug( "The subVolume task has failed!" ) );
            task.start();
        }
    }

    public void displayHM( int index )
    {
        ReferenceSurface< T > referenceSurface = model.getReferenceSurfaces().get().get( index );
        ImageJFunctions.show( referenceSurface.getzMap() );
    }

    public void setParameters( ReferenceSurfacePanel< T > panel )
    {
        for ( int channel = 0; channel < panel.getChannelTools().getTabs().size(); channel++ )
        {
            ChannelPanel channelPanel = ( ChannelPanel ) panel.getChannelTools().getTabs().get( channel ).getContent();
            ChannelToolProperty< T > channelToolProperty = panel.getProjectionProperties().getProperties().get().get( channel );
            setParameters( channelToolProperty, channelPanel.getDeltaZ().getValue(), channelPanel.getOffset().getValue(), channelPanel.getMethod().getValue() );
        }
    }


    public void setParameters( ChannelToolProperty< T > channelToolProperty, int delta, int offset, String method )
    {

        if ( delta != channelToolProperty.getDeltaZ().get() )
        {
            channelToolProperty.getDeltaZ().set( delta );
        }
        if ( offset != channelToolProperty.getOffset().get() )
        {
            channelToolProperty.getOffset().set( offset );
        }
        if ( ! method.equals( channelToolProperty.getMethod().get() ) )
        {
            channelToolProperty.getMethod().set( method );
        }
    }

    public void setParameters( final int index, int channel, int delta, int offset, String method )
    {
        ProjectionProperties< T > projectionProperties = getModel().getProjectionProperties().get().get( index );
        ChannelToolProperty< T > channelToolProperty = projectionProperties.getProperties().get().get( channel );
       setParameters( channelToolProperty, delta, offset, method );
    }


    public ProjectionModel< T > getModel()
    {
        return model;
    }


}
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui.interactor;

import fr.pasteur.ida.zellige.gui.model.SelectionModel;
import fr.pasteur.ida.zellige.gui.task.*;

public class SelectionInteractor
{

    private final SelectionModel model;

    public SelectionInteractor( SelectionModel model )
    {
        this.model = model;
    }

    public void computeClassifiedImages()
    {
        ComputeClassificationImagesTask classifiedImagesTask = new ComputeClassificationImagesTask( model.pretreatedImgProperty().getValue() );
        classifiedImagesTask.setOnSucceeded( workerStateEvent -> model.imagesProperty().set( classifiedImagesTask.getValue() ) );
        classifiedImagesTask.start();
    }

    public void runAmplitudeTask()
    {
        AmplitudeThresholdingTask amplitudeTask = new AmplitudeThresholdingTask( model.imagesProperty().get().getAmplitudeImg(), model.amplitudeProperty().getValue().intValue() );
        amplitudeTask.setOnSucceeded( workerStateEvent ->
                model.selectedAmplitudeProperty().setValue( amplitudeTask.getValue() ) );
//        amplitudeTask.setOnFailed( workerStateEvent -> LOGGER.debug( "Amplitude classification has failed." ) );
        amplitudeTask.start();
    }

    public void runOtsuTask()
    {
        OtsuThresholdingTask otsuTask = new OtsuThresholdingTask( model.pretreatedImgProperty().get(), model.imagesProperty().get().getOtsuImg(), model.otsuProperty().getValue().intValue() );
        otsuTask.setOnSucceeded( workerStateEvent ->
                model.selectedOtsuProperty().setValue( otsuTask.getValue() ) );
//        otsuTask.setOnFailed( workerStateEvent -> LOGGER.debug( "Otsu classification has failed." ) );
        otsuTask.start();
    }

    public void runInterClassification()
    {
        InterClassificationTask interClassificationTask = new InterClassificationTask( model.selectedAmplitudeProperty().get(), model.selectedOtsuProperty().get() );
        interClassificationTask.setOnSucceeded( event -> model.interClassifiedImageProperty().setValue( interClassificationTask.getValue() ) );
        interClassificationTask.start();
    }

    public void runIslandSearch()
    {
        IslandSearchTask islandSearchTask = new IslandSearchTask( model.interClassifiedImageProperty().get(), model.islandProperty().get() );
        islandSearchTask.setOnSucceeded( workerStateEvent ->
                model.islandSearchImageProperty().setValue( islandSearchTask.getValue() ) );
//        islandSearchTask.setOnFailed( workerStateEvent -> LOGGER.debug( "FAILED" ) );
        islandSearchTask.start();
    }

    public void runSmoothing()
    {
        SmoothingTask smoothingTask = new SmoothingTask(
                model.islandSearchImageProperty().get(),
                model.xyBlurProperty().get(),
                model.zBlurProperty().get() );
        smoothingTask.setOnSucceeded( event ->
                model.selectedPixelsProperty().setValue( smoothingTask.getValue() ) );
        smoothingTask.start();
    }

    public SelectionModel getModel()
    {
        return model;
    }
}
Original line number Diff line number Diff line
@@ -28,24 +28,20 @@
 */
package fr.pasteur.ida.zellige.gui.model;

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.ZDoubleProperty;
import fr.pasteur.ida.zellige.gui.controller.MainController;
import fr.pasteur.ida.zellige.gui.task.AbstractTask;
import fr.pasteur.ida.zellige.gui.task.ConstructionCompletionTask;
import fr.pasteur.ida.zellige.gui.task.RunFirstConstructionTask;
import fr.pasteur.ida.zellige.gui.task.RunSecondConstructionTask;
import fr.pasteur.ida.zellige.steps.construction.exception.FirstRoundConstructionException;
import fr.pasteur.ida.zellige.steps.construction.exception.SecondRoundConstructionException;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.image.ImageView;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.img.Img;
import net.imglib2.img.ImgFactory;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.numeric.real.FloatType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@@ -56,6 +52,7 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > >

    private final static Logger LOGGER = LoggerFactory.getLogger( ConstructionModel.class );

    private final IntegerProperty bin;
    private final ZDoubleProperty c1;
    private final ZDoubleProperty c2;
    private final IntegerProperty r1;
@@ -65,13 +62,18 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > >
    private final ZDoubleProperty surfaceSize;
    private final SimpleObjectProperty< ArrayList< Surface > > firstRoundSurfaces = new SimpleObjectProperty<>();
    private final SimpleObjectProperty< ArrayList< Surface > > secondRoundSurfaces = new SimpleObjectProperty<>();
    private final SimpleObjectProperty< ArrayList< ReferenceSurface< T > > > referenceSurfaces = new SimpleObjectProperty<>();
    private final SimpleObjectProperty< Pixels[][] > maximums = new SimpleObjectProperty<>();
    private RandomAccessibleInterval< T > input;
    private ImgFactory< T > factory;
    private final SimpleObjectProperty< ArrayList< ReferenceSurface< T > > > referenceSurfaces = new SimpleObjectProperty<>(new ArrayList<>());
    private final SimpleObjectProperty< Img< FloatType > >maximums = new SimpleObjectProperty<>();
    private final SimpleObjectProperty< RandomAccessibleInterval <T> > channelInput = new SimpleObjectProperty<>();
    private final SimpleObjectProperty< RandomAccessibleInterval <T> > input = new SimpleObjectProperty<>();
    private final SimpleObjectProperty< ImgFactory< T >> factory = new SimpleObjectProperty<>();
    private final SimpleObjectProperty< ImageView[] > imageViews = new SimpleObjectProperty<>();
    private final SimpleBooleanProperty parameterChanged = new SimpleBooleanProperty(false);
    private final SimpleBooleanProperty disableGUI = new SimpleBooleanProperty();

    public ConstructionModel()
    {
        bin = new SimpleIntegerProperty();
        c1 = new ZDoubleProperty();
        c2 = new ZDoubleProperty();
        r1 = new SimpleIntegerProperty();
@@ -81,64 +83,12 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > >
        surfaceSize = new ZDoubleProperty();
    }

    public void firstRound()
    {
        LOGGER.info( "Computing first round construction..." );
        AbstractTask< ArrayList< Surface > > firstRoundTask = new RunFirstConstructionTask( maximums.getValue(), st1.doubleValue(), r1.intValue(), c1.doubleValue(), surfaceSize.doubleValue() / 100.0 );
        firstRoundTask.setOnSucceeded( workerStateEvent ->
        {
            firstRoundSurfaces.setValue( firstRoundTask.getValue() );
            if ( firstRoundTask.getValue() == null )
            {
                LOGGER.info( "" ); //TODO write right message
                MainController.showError( new FirstRoundConstructionException() );
            }
        } );
        LOGGER.info( "First round construction done." );
        firstRoundTask.start();
    }


    public void secondRound()
    {
        LOGGER.info( "Computing second round construction..." );
        AbstractTask< ArrayList< Surface > > secondRoundTask = new RunSecondConstructionTask( firstRoundSurfacesProperty().getValue(), st2.getValue(), r2.intValue(), c2.doubleValue(), surfaceSize.doubleValue() / 100.0 );
        secondRoundTask.setOnSucceeded( workerStateEvent ->
        {
            secondRoundSurfacesProperty().setValue( secondRoundTask.getValue() );
            if ( secondRoundTask.getValue() == null )
            {
                LOGGER.info( "" ); //TODO write right message
                MainController.showError( new SecondRoundConstructionException() );
            }
        } );
        LOGGER.info( "Second round construction done." );
        secondRoundTask.start();
    }

    public void runConstruction()
    {
        LOGGER.debug( "Run construction" );
        if ( firstRoundSurfacesProperty().getValue() == null )
        {
            firstRound();
        }
        else if ( secondRoundSurfaces.getValue() == null )
        {
            secondRound();
        }
    }


    public void constructionCompletion()
    public IntegerProperty getBin()
    {
        AbstractTask< ArrayList< ReferenceSurface< T > > > constructionCompletionTask = new ConstructionCompletionTask<>( input, factory, secondRoundSurfaces.getValue() );
        constructionCompletionTask.setOnSucceeded( workerStateEvent ->
                referenceSurfacesProperty().setValue( constructionCompletionTask.getValue() ) );
        constructionCompletionTask.start();
        return bin;
    }


    public ZDoubleProperty c1Property()
    {
        return c1;
@@ -189,34 +139,43 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > >
        return referenceSurfaces;
    }

    public void setInput( RandomAccessibleInterval< T > input )
    public SimpleBooleanProperty getParameterChanged()
    {
        return parameterChanged;
    }

    public SimpleObjectProperty< RandomAccessibleInterval< T > > getChannelInput()
    {
        this.input = input;
        return channelInput;
    }

    public SimpleObjectProperty< RandomAccessibleInterval< T > > getInput()
    {
        return input;
    }

    public void setFactory( ImgFactory< T > factory )
    public SimpleObjectProperty< ImgFactory< T > > getFactory()
    {
        this.factory = factory;
        return factory;
    }

    public double getC1()
    public SimpleObjectProperty< Img<FloatType> > maximumsProperty()
    {
        return c1.get();
        return maximums;
    }

    public RandomAccessibleInterval< T > getInput()
    public SimpleObjectProperty< ImageView[] > getImageViews()
    {
        return input;
        return imageViews;
    }

    public ImgFactory< T > getFactory()
    public SimpleBooleanProperty getDisableGUI()
    {
        return factory;
        return disableGUI;
    }

    public SimpleObjectProperty< Pixels[][] > maximumsProperty()
    public int getSurfaceMax()
    {
        return maximums;
        return ( int ) (input.get().dimension( 0 )* input.get().dimension( 1 )/ (bin.get() * bin.get()));
    }
}
Original line number Diff line number Diff line
@@ -33,18 +33,26 @@ import net.imglib2.type.numeric.RealType;

public class MainModel< T extends RealType< T > & NativeType< T > >
{

    private final PreprocessingModel< T > preprocessingModel;
    private final SelectionModel selectionModel;
    private final ConstructionModel< T > constructionModel;
    private final ProjectionModel< T > projectionModel;

    public MainModel( SelectionModel selectionModel, ConstructionModel< T > constructionModel, ProjectionModel< T > projectionModel )

    public MainModel( PreprocessingModel< T > preprocessingModel, SelectionModel selectionModel, ConstructionModel< T > constructionModel, ProjectionModel< T > projectionModel )
    {
        this.preprocessingModel = preprocessingModel;
        this.selectionModel = selectionModel;
        this.constructionModel = constructionModel;
        this.projectionModel = projectionModel;
    }


    public PreprocessingModel< T > getPreprocessingModel()
    {
        return preprocessingModel;
    }

    public SelectionModel getSelectionModel()
    {
        return selectionModel;
Original line number Diff line number Diff line
package fr.pasteur.ida.zellige.gui.model;

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.display.ColorTable;
import net.imglib2.img.Img;
import net.imglib2.img.ImgFactory;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.numeric.real.FloatType;

import java.util.ArrayList;

public class PreprocessingModel< T extends RealType< T > & NativeType< T > >
{

    private final IntegerProperty  bin = new SimpleIntegerProperty();

    private final IntegerProperty channel =  new SimpleIntegerProperty();

    private final IntegerProperty nbOfChannels = new SimpleIntegerProperty();

    private final SimpleObjectProperty< RandomAccessibleInterval<T> > input = new SimpleObjectProperty<>();

    private final SimpleObjectProperty< RandomAccessibleInterval<T> > input_channel = new SimpleObjectProperty<>();

    private final SimpleObjectProperty< ImgFactory< T > > factory = new SimpleObjectProperty<>();

    private final SimpleObjectProperty< Img< FloatType > > pretreatedImg = new SimpleObjectProperty<>();

    private final SimpleBooleanProperty parameterChanged = new SimpleBooleanProperty(false);

    private final SimpleObjectProperty< ArrayList< ColorTable > > colors = new SimpleObjectProperty<>(new ArrayList<>());

    public IntegerProperty binProperty()
    {
        return bin;
    }

    public SimpleObjectProperty< Img< FloatType > > pretreatedImgProperty()
    {
        return pretreatedImg;
    }

    public IntegerProperty getChannel()
    {
        return channel;
    }

    public SimpleBooleanProperty getParameterChanged()
    {
        return parameterChanged;
    }

    public SimpleObjectProperty< ImgFactory< T > > getFactory()
    {
        return factory;
    }

    public SimpleObjectProperty< RandomAccessibleInterval< T > > getInput()
    {
        return input;
    }

    public IntegerProperty getNbOfChannels()
    {
        return nbOfChannels;
    }

    public SimpleObjectProperty< ArrayList<ColorTable > > getColors()
    {
        return colors;
    }

    public SimpleObjectProperty< RandomAccessibleInterval< T > > getInput_channel()
    {
        return input_channel;
    }


}
Original line number Diff line number Diff line
@@ -28,311 +28,48 @@
 */
package fr.pasteur.ida.zellige.gui.model;

import fr.pasteur.ida.zellige.element.Projection;
import fr.pasteur.ida.zellige.element.ReferenceSurface;
import fr.pasteur.ida.zellige.steps.projection.ReferenceSurfaceProjection;
import fr.pasteur.ida.zellige.gui.ProjectionProperties;
import javafx.beans.property.*;
import net.imglib2.img.Img;
import net.imglib2.img.display.imagej.ImageJFunctions;
import javafx.scene.image.ImageView;
import net.imglib2.display.ColorTable;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.numeric.integer.UnsignedShortType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;

public class ProjectionModel< T extends RealType< T > & NativeType< T > >
{
    private final static Logger LOGGER = LoggerFactory.getLogger( ProjectionModel.class );
    private final SimpleObjectProperty< ArrayList< ReferenceSurface< T > > > referenceSurfaces;
    private final SimpleBooleanProperty delta1Functions;
    private final SimpleBooleanProperty delta2Functions;
    private final IntegerProperty delta1;
    private final IntegerProperty delta2;

    private final StringProperty method;
    private final SimpleObjectProperty< ArrayList< ReferenceSurface< T > > > referenceSurfaces = new SimpleObjectProperty<>( new ArrayList<>() );
    private final SimpleObjectProperty< ArrayList< ProjectionProperties< T > > > projectionProperties = new SimpleObjectProperty<>( new ArrayList<>() );
    private final SimpleObjectProperty< ImageView[] > imageViews = new SimpleObjectProperty<>();

    private final SimpleIntegerProperty numberOfChannels = new SimpleIntegerProperty();

    private final BooleanProperty rawHM;
    private final BooleanProperty projection;
    private final BooleanProperty extractedHM;
    private final BooleanProperty reduced3Dspace;
    private final BooleanProperty segmentedSurface;
    private final BooleanProperty segmentedSurfaceMask;

    private final BooleanProperty rawHMDisplay;
    private final BooleanProperty projectionDisplay;
    private final BooleanProperty extractedHMDisplay;
    private final BooleanProperty reduced3DspaceDisplay;
    private final BooleanProperty segmentedSurfaceDisplay;
    private final BooleanProperty segmentedSurfaceMaskDisplay;

    public ProjectionModel()
    {
        this.referenceSurfaces = new SimpleObjectProperty<>();
        this.delta1Functions = new SimpleBooleanProperty( false );
        this.delta2Functions = new SimpleBooleanProperty( false );
        this.method = new SimpleStringProperty();
        this.delta1 = new SimpleIntegerProperty();
        this.delta2 = new SimpleIntegerProperty();
        this.rawHM = new SimpleBooleanProperty();
        this.projection = new SimpleBooleanProperty();
        this.extractedHM = new SimpleBooleanProperty();
        this.reduced3Dspace = new SimpleBooleanProperty();
        this.segmentedSurface = new SimpleBooleanProperty();
        this.segmentedSurfaceMask = new SimpleBooleanProperty();
        this.rawHMDisplay = new SimpleBooleanProperty( true );
        this.projectionDisplay = new SimpleBooleanProperty( true );
        this.extractedHMDisplay = new SimpleBooleanProperty( true );
        this.reduced3DspaceDisplay = new SimpleBooleanProperty( true );
        this.segmentedSurfaceDisplay = new SimpleBooleanProperty( true );