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

Target

Select target project
  • ida-public/zellige-core
1 result
Show changes
Showing
with 1713 additions and 686 deletions
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;
}
}
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;
}
}
package fr.pasteur.ida.zellige.gui;
public class ReferencesurfaceProjectionPane
{
}
...@@ -39,32 +39,25 @@ import java.io.IOException; ...@@ -39,32 +39,25 @@ import java.io.IOException;
public class StepPanel extends VBox public class StepPanel extends VBox
{ {
private final String name;
@FXML
Label Label2;
public StepPanel( @NamedArg( "name" ) String name )
{ // public StepPanel( @NamedArg( "name" ) String name )
this.name = name; // {
FXMLLoader fxmlLoader = new FXMLLoader( StepPanel.class.getClassLoader().getResource( // FXMLLoader fxmlLoader = new FXMLLoader( StepPanel.class.getClassLoader().getResource(
"fr.pasteur.ida.zellige.gui.view/StepPanel.fxml" ) ); // "fr.pasteur.ida.zellige.gui.view/StepPanel.fxml" ) );
fxmlLoader.setRoot( this ); // fxmlLoader.setRoot( this );
fxmlLoader.setController( this ); // fxmlLoader.setController( this );
try // try
{ // {
fxmlLoader.load(); // fxmlLoader.load();
} // }
catch ( IOException e ) // catch ( IOException e )
{ // {
e.printStackTrace(); // e.printStackTrace();
} // }
} // }
@FXML
public void initialize()
{
this.Label2.setText( name );
}
} }
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 );
}
} );
}
}
...@@ -6,13 +6,13 @@ ...@@ -6,13 +6,13 @@
* %% * %%
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
...@@ -28,14 +28,18 @@ ...@@ -28,14 +28,18 @@
*/ */
package fr.pasteur.ida.zellige.gui.controller; package fr.pasteur.ida.zellige.gui.controller;
import fr.pasteur.ida.zellige.gui.ParameterSliderDouble; import fr.pasteur.ida.zellige.gui.*;
import fr.pasteur.ida.zellige.gui.ParameterSliderInteger; 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.model.ConstructionModel;
import fr.pasteur.ida.zellige.gui.parameter.ZelligeParameters; import fr.pasteur.ida.zellige.gui.parameter.ZelligeParameters;
import javafx.beans.property.SimpleBooleanProperty; import fr.pasteur.ida.zellige.gui.task.*;
import javafx.beans.value.ChangeListener; import javafx.beans.property.*;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.image.ImageView;
import net.imglib2.type.NativeType; import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.RealType;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -44,12 +48,17 @@ import org.slf4j.LoggerFactory; ...@@ -44,12 +48,17 @@ import org.slf4j.LoggerFactory;
import java.net.URL; import java.net.URL;
import java.util.ResourceBundle; 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 public class ConstructionController< T extends RealType< T > & NativeType< T > > implements Initializable
{ {
private final static Logger LOGGER = LoggerFactory.getLogger( ConstructionController.class ); private final static Logger LOGGER = LoggerFactory.getLogger( ConstructionController.class );
private final SimpleBooleanProperty changedParameters = new SimpleBooleanProperty(); private MainController< T > parentController;
private ConstructionModel< T > constructionModel;
@FXML @FXML
private ParameterSliderDouble c1; private ParameterSliderDouble c1;
@FXML @FXML
...@@ -64,102 +73,233 @@ public class ConstructionController< T extends RealType< T > & NativeType< T > > ...@@ -64,102 +73,233 @@ public class ConstructionController< T extends RealType< T > & NativeType< T > >
private ParameterSliderDouble st2; private ParameterSliderDouble st2;
@FXML @FXML
private ParameterSliderInteger surfaceSize; private ParameterSliderInteger surfaceSize;
@FXML
private ConstructionDisplay constructionDisplay;
@FXML
private Button run;
private final ConstructionInteractor< T > interactor = new ConstructionInteractor<>( new ConstructionModel< T >() );
@Override @Override
public void initialize( URL url, ResourceBundle resourceBundle ) public void initialize( URL url, ResourceBundle resourceBundle )
{ {
// model /* Component behaviour */
constructionModel = new ConstructionModel<>(); constructionDisplay.getMinus().setOnAction( actionEvent ->
//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 ); constructionDisplay.previous();
changedParameters.setValue( true ); setDisplay();
}; } );
c1.sliderProperty().addListener( firstRoundListener ); constructionDisplay.getPlus().setOnAction( actionEvent ->
r1.sliderProperty().addListener( firstRoundListener );
st1.sliderProperty().addListener( firstRoundListener );
surfaceSize.sliderProperty().addListener( firstRoundListener );
ChangeListener< ? super Number > secondRoundListener = ( observable, oldValue, newValue ) ->
{ {
changedParameters.setValue( true ); constructionDisplay.next();
constructionModel.secondRoundSurfacesProperty().setValue( null ); setDisplay();
}; } );
c2.sliderProperty().addListener( secondRoundListener );
r2.sliderProperty().addListener( secondRoundListener ); run.setOnAction( actionEvent ->
st2.sliderProperty().addListener( secondRoundListener ); {
surfaceSize.sliderProperty().addListener( secondRoundListener ); 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*/ /* Properties*/
constructionModel.maximumsProperty().addListener( ( observable, oldValue, newValue ) ->
getModel().getDisableGUI().addListener( ( observable, oldValue, newValue ) ->
{ {
if ( newValue != null ) if ( newValue )
{ {
LOGGER.debug( "Max is not null" ); disableParameters();
constructionModel.firstRound();
} }
else else
{ {
LOGGER.debug( "MAX is NULL" ); enableParameters();
constructionModel.firstRoundSurfacesProperty().setValue( null );
} }
} ); } );
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" ); interactor.secondRound();
constructionModel.secondRoundSurfacesProperty().setValue( null );
} }
else } );
getModel().secondRoundSurfacesProperty().addListener( ( observableValue, surfaces, newValue ) ->
{
if ( newValue != null )
{ {
constructionModel.secondRound(); interactor.constructionCompletion();
} }
} ); } );
constructionModel.secondRoundSurfacesProperty().addListener( ( observableValue, surfaces, t1 ) ->
getModel().referenceSurfacesProperty().addListener( ( observableValue, surfaces, newValue ) ->
{ {
if ( t1 == null ) if (newValue!= null && ! newValue.isEmpty() )
{ {
LOGGER.debug( "SECOND_ROUND_SURFACE is NULL" ); computeImageFXDisplay();
constructionModel.referenceSurfacesProperty().setValue( null );
} }
else else
{ {
constructionModel.constructionCompletion(); LOGGER.debug( "There is no SURFACE!!!" );
}
} );
}
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 ( ! property.getValue().equals( slider.getValue() ) )
{
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
{
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 )
{
result.set( null );
}
} );
}
public void enableParameters()
{ {
return constructionModel; this.c1.enable();
this.r1.enable();
this.st1.enable();
this.c2.enable();
this.r2.enable();
this.st2.enable();
this.surfaceSize.enable();
} }
public SimpleBooleanProperty changedParametersProperty() public void disableParameters()
{ {
return changedParameters; 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 ) public void setParameters( ZelligeParameters parameters )
{ {
st1.setValue( parameters.getSt1() ); st1.setValue( parameters.getConstructionParameters()[0].getStartingSizeThreshold() );
r1.setValue( parameters.getR1() ); r1.setValue( parameters.getConstructionParameters()[0].getOverlap());
c1.setValue( parameters.getC1() ); c1.setValue( parameters.getConstructionParameters()[0].getConnexityRate() );
st2.setValue( parameters.getSt2() ); st2.setValue( parameters.getConstructionParameters()[1].getStartingSizeThreshold() );
r2.setValue( parameters.getR2() ); r2.setValue( parameters.getConstructionParameters()[1].getOverlap());
c2.setValue( parameters.getC2() ); c2.setValue( parameters.getConstructionParameters()[1].getConnexityRate() );
surfaceSize.setValue( parameters.getSurfaceSize() ); 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 );
} }
} }
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
...@@ -6,13 +6,13 @@ ...@@ -6,13 +6,13 @@
* %% * %%
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
...@@ -28,226 +28,193 @@ ...@@ -28,226 +28,193 @@
*/ */
package fr.pasteur.ida.zellige.gui.controller; 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.model.ProjectionModel;
import fr.pasteur.ida.zellige.gui.parameter.ZelligeParameters; import fr.pasteur.ida.zellige.gui.parameter.ZelligeParameters;
import javafx.beans.property.BooleanProperty; import fr.pasteur.ida.zellige.steps.projection.ProjectionParameters;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox; import javafx.scene.Node;
import javafx.scene.control.Spinner; import javafx.scene.control.*;
import javafx.scene.control.SpinnerValueFactory; import javafx.scene.image.ImageView;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import net.imglib2.type.NativeType; import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.RealType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.net.URL; import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class ProjectionController< T extends RealType< T > & NativeType< T > > implements Initializable public class ProjectionController< T extends RealType< T > & NativeType< T > > implements Initializable
{ {
private final static Logger LOGGER = LoggerFactory.getLogger( ProjectionController.class ); private final static Logger LOGGER = LoggerFactory.getLogger( ProjectionController.class );
private final SimpleBooleanProperty changedParameters = new SimpleBooleanProperty();
@FXML private MainController< T > parentController;
private Spinner< Integer > delta1;
@FXML
private ComboBox< String > methodComboBox;
@FXML
private CheckBoxDisplay extractedHeightMap;
@FXML
private CheckBoxDisplay segmentedSurface;
@FXML @FXML
private CheckBoxDisplay reduced3DSpace; private StackPane stackPane;
@FXML @FXML
private CheckBoxDisplay segmentedSurfaceMask; private FlowPane display;
@FXML @FXML
private CheckBoxDisplay projection; private Button displayRS;
@FXML @FXML
private CheckBoxDisplay rawHeightMap; private Label log;
@FXML @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;
public ProjectionController()
{
ProjectionModel< T > model = new ProjectionModel<>();
this.interactor = new ProjectionInteractor<>( model );
}
@Override @Override
public void initialize( URL url, ResourceBundle resourceBundle ) public void initialize( URL url, ResourceBundle resourceBundle )
{ {
// Model getModel().getImageViews().addListener( ( observableValue, number, newValue ) ->
model = new ProjectionModel<>(); {
if ( newValue != null )
//link Model with View {
model.methodProperty().bind( methodComboBox.valueProperty() ); getModel().getReferenceSurfaces().
model.delta1Property().bind( delta1.valueProperty() ); set( parentController.getConstructionController().getModel().referenceSurfacesProperty().get() );
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 ); // Listening of the reference surface choiceBox
bindCheckBox( model.segmentedSurfaceProperty(), model.segmentedSurfaceDisplayProperty(), segmentedSurface ); referenceSurfacesList.getSelectionModel().selectedIndexProperty().addListener( ( observableValue, number, newValue ) ->
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 ); if ( newValue.intValue() != -1 )
resetDisplayMode();
changedParameters.setValue( true );
} );
delta2.valueProperty().addListener( ( observableValue, integer, t1 ) ->
{
model.delta2FunctionsProperty().setValue( false );
segmentedSurfaceMask.enable();
changedParameters.setValue( true );
} );
projection.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
{
if ( model.delta1FunctionsProperty().getValue() && t1 && projection.isNotDisplayed() )
{ {
currentIndex.set( newValue.intValue() );
model.showProjections(); LOGGER.debug( "Checking Reference surface n°{}", currentIndex.get() );
setDisplay();
setProjectionPane();
} }
} ); } );
rawHeightMap.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) -> getModel().getReferenceSurfaces().addListener( ( observableValue, number, newValue ) ->
{
if ( model.delta1FunctionsProperty().getValue() && t1 && rawHeightMap.isNotDisplayed() )
{
model.showRawHeightMap();
}
} );
extractedHeightMap.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
{ {
if ( model.delta1FunctionsProperty().getValue() && t1 && extractedHeightMap.isNotDisplayed() ) if ( newValue != null )
{ {
listsInitialization();
model.showExtractedHeightMaps(); // Removes default projection pane
stackPane.getChildren().clear();
int channels = parentController.getPreprocessingController().getModel().getNbOfChannels().get();
for ( int i = 0; i < getModel().getReferenceSurfaces().get().size(); i++ )
{
// 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 ->
{
interactor.setParameters( panel );
interactor.runProjection( currentIndex.get() );
} );
for ( int j = 0; j < panel.getChannelTools().getTabs().size(); j++ )
{
final int channel = j;
ChannelPanel channelPanel = ( ChannelPanel ) panel.getChannelTools().getTabs().get( j ).getContent();
channelPanel.getView().setOnAction( actionEvent ->
{
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();
} }
} ); });
reduced3DSpace.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
{
if ( model.delta1FunctionsProperty().getValue() && t1 && reduced3DSpace.isNotDisplayed() )
{
model.showReduced3DSpace();
}
} );
segmentedSurface.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
{
if ( model.delta1FunctionsProperty().getValue() && t1 && segmentedSurface.isNotDisplayed() )
{
model.showSegmentedSurface(); /* Components*/
} displayRS.setOnAction( actionEvent -> interactor.displayHM( currentIndex.intValue() ) );
} ); }
segmentedSurfaceMask.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
{
if ( model.delta2FunctionsProperty().getValue() && t1 && segmentedSurfaceMask.isNotDisplayed() )
{
model.showSegmentedSurfaceMask(); public void setDisplay()
} {
} ); display.getChildren().clear();
ImageView i = getModel().getImageViews().getValue()[ currentIndex.get() ];
display.getChildren().add( i );
// setting of ZSlider
}
// Model Properties public void setProjectionPane()
model.referenceSurfacesProperty().addListener( ( observableValue, referenceSurfaces1, t1 ) -> {
int length = stackPane.getChildren().size();
for ( int i = 0; i < length; i++ )
{ {
if ( t1 == null ) Node node = stackPane.getChildren().get( i );
{ node.setVisible( i == currentIndex.get() );
model.delta1FunctionsProperty().setValue( false ); }
LOGGER.debug( "REFERENCE_SURFACES is NULL" ); LOGGER.debug( "Displaying channel panel n°{}\n", ( currentIndex.get() + 1 ) );
} }
else
{
LOGGER.info( "Extraction of {} surfaces", model.referenceSurfacesProperty().getValue().size() );
LOGGER.debug( "Compute output delta1" );
model.setOutputDelta1();
resetDisplayMode();
}
} );
model.delta1FunctionsProperty().addListener( ( observableValue, aBoolean, t1 ) ->
{
if ( ! t1 )
{
LOGGER.debug( "DELTA1_FUNCTIONS is NULL" );
model.delta2FunctionsProperty().setValue( false );
}
else
{
LOGGER.debug( "Compute output delta2" );
model.setOutputDelta2();
}
} );
model.delta2FunctionsProperty().addListener( ( observable, oldValue, newValue ) -> private void listsInitialization()
{
ArrayList< String > names = new ArrayList<>();
if ( ! getModel().getReferenceSurfaces().get().isEmpty() )
{ {
if ( newValue ) getModel().getReferenceSurfaces().get().forEach( rf ->
{
model.showOutput();
}
else
{ {
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(); parentController = mainController;
projection.enable();
segmentedSurface.enable();
rawHeightMap.enable();
reduced3DSpace.enable();
segmentedSurfaceMask.enable();
} }
public SimpleBooleanProperty changedParametersProperty()
{
return changedParameters;
}
public ProjectionModel< T > getModel() public ProjectionModel< T > getModel()
{ {
return model; return interactor.getModel();
} }
public StackPane getStackPane()
private void bindCheckBox( BooleanProperty selected, BooleanProperty notDisplayed, CheckBoxDisplay checkBox )
{ {
selected.bind( checkBox.selectedProperty() ); return stackPane;
notDisplayed.bindBidirectional( checkBox.notDisplayedProperty() );
} }
public void setParameters( ZelligeParameters parameters ) public void setParameters( ZelligeParameters parameters )
{ {
delta1.getValueFactory().setValue( parameters.getDelta1() ); ArrayList< ProjectionParameters > projectionParameters = parameters.getProjectionParameters();
delta2.getValueFactory().setValue( parameters.getDelta2() ); //TODO Dynamic loading ?
methodComboBox.getSelectionModel().select( parameters.getMethod() );
} }
} }
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());
}
}
...@@ -31,7 +31,9 @@ package fr.pasteur.ida.zellige.gui.exception; ...@@ -31,7 +31,9 @@ package fr.pasteur.ida.zellige.gui.exception;
public class NoInputException extends 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 @Override
public String getMessage() public String getMessage()
......
package fr.pasteur.ida.zellige.gui.exception;
public class NoParameterChangeException extends Exception
{
final String message = " No parameter has been modify !";
@Override
public String getMessage()
{
return message;
}
}
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;
}
}
package fr.pasteur.ida.zellige.gui.exception;
public class NoSelectedInputException extends Exception
{
final String message = " Please select a file!";
@Override
public String getMessage()
{
return message;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
...@@ -28,24 +28,20 @@ ...@@ -28,24 +28,20 @@
*/ */
package fr.pasteur.ida.zellige.gui.model; 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.ReferenceSurface;
import fr.pasteur.ida.zellige.element.Surface; import fr.pasteur.ida.zellige.element.Surface;
import fr.pasteur.ida.zellige.gui.ZDoubleProperty; 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.IntegerProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.image.ImageView;
import net.imglib2.RandomAccessibleInterval; import net.imglib2.RandomAccessibleInterval;
import net.imglib2.img.Img;
import net.imglib2.img.ImgFactory; import net.imglib2.img.ImgFactory;
import net.imglib2.type.NativeType; import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.RealType;
import net.imglib2.type.numeric.real.FloatType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -56,6 +52,7 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > > ...@@ -56,6 +52,7 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > >
private final static Logger LOGGER = LoggerFactory.getLogger( ConstructionModel.class ); private final static Logger LOGGER = LoggerFactory.getLogger( ConstructionModel.class );
private final IntegerProperty bin;
private final ZDoubleProperty c1; private final ZDoubleProperty c1;
private final ZDoubleProperty c2; private final ZDoubleProperty c2;
private final IntegerProperty r1; private final IntegerProperty r1;
...@@ -65,13 +62,18 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > > ...@@ -65,13 +62,18 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > >
private final ZDoubleProperty surfaceSize; private final ZDoubleProperty surfaceSize;
private final SimpleObjectProperty< ArrayList< Surface > > firstRoundSurfaces = new SimpleObjectProperty<>(); private final SimpleObjectProperty< ArrayList< Surface > > firstRoundSurfaces = new SimpleObjectProperty<>();
private final SimpleObjectProperty< ArrayList< Surface > > secondRoundSurfaces = new SimpleObjectProperty<>(); private final SimpleObjectProperty< ArrayList< Surface > > secondRoundSurfaces = new SimpleObjectProperty<>();
private final SimpleObjectProperty< ArrayList< ReferenceSurface< T > > > referenceSurfaces = new SimpleObjectProperty<>(); private final SimpleObjectProperty< ArrayList< ReferenceSurface< T > > > referenceSurfaces = new SimpleObjectProperty<>(new ArrayList<>());
private final SimpleObjectProperty< Pixels[][] > maximums = new SimpleObjectProperty<>(); private final SimpleObjectProperty< Img< FloatType > >maximums = new SimpleObjectProperty<>();
private RandomAccessibleInterval< T > input; private final SimpleObjectProperty< RandomAccessibleInterval <T> > channelInput = new SimpleObjectProperty<>();
private ImgFactory< T > factory; 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() public ConstructionModel()
{ {
bin = new SimpleIntegerProperty();
c1 = new ZDoubleProperty(); c1 = new ZDoubleProperty();
c2 = new ZDoubleProperty(); c2 = new ZDoubleProperty();
r1 = new SimpleIntegerProperty(); r1 = new SimpleIntegerProperty();
...@@ -81,64 +83,12 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > > ...@@ -81,64 +83,12 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > >
surfaceSize = new ZDoubleProperty(); 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() public IntegerProperty getBin()
{ {
LOGGER.debug( "Run construction" ); return bin;
if ( firstRoundSurfacesProperty().getValue() == null )
{
firstRound();
}
else if ( secondRoundSurfaces.getValue() == null )
{
secondRound();
}
} }
public void constructionCompletion()
{
AbstractTask< ArrayList< ReferenceSurface< T > > > constructionCompletionTask = new ConstructionCompletionTask<>( input, factory, secondRoundSurfaces.getValue() );
constructionCompletionTask.setOnSucceeded( workerStateEvent ->
referenceSurfacesProperty().setValue( constructionCompletionTask.getValue() ) );
constructionCompletionTask.start();
}
public ZDoubleProperty c1Property() public ZDoubleProperty c1Property()
{ {
return c1; return c1;
...@@ -189,34 +139,43 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > > ...@@ -189,34 +139,43 @@ public class ConstructionModel< T extends RealType< T > & NativeType< T > >
return referenceSurfaces; return referenceSurfaces;
} }
public void setInput( RandomAccessibleInterval< T > input ) public SimpleBooleanProperty getParameterChanged()
{ {
this.input = input; return parameterChanged;
} }
public SimpleObjectProperty< RandomAccessibleInterval< T > > getChannelInput()
{
return channelInput;
}
public void setFactory( ImgFactory< T > factory ) public SimpleObjectProperty< RandomAccessibleInterval< T > > getInput()
{ {
this.factory = factory; return input;
} }
public double getC1() public SimpleObjectProperty< ImgFactory< T > > getFactory()
{ {
return c1.get(); return factory;
} }
public RandomAccessibleInterval< T > getInput() public SimpleObjectProperty< Img<FloatType> > maximumsProperty()
{ {
return input; return maximums;
} }
public ImgFactory< T > getFactory() public SimpleObjectProperty< ImageView[] > getImageViews()
{ {
return factory; return imageViews;
} }
public SimpleObjectProperty< Pixels[][] > maximumsProperty() public SimpleBooleanProperty getDisableGUI()
{ {
return maximums; return disableGUI;
}
public int getSurfaceMax()
{
return ( int ) (input.get().dimension( 0 )* input.get().dimension( 1 )/ (bin.get() * bin.get()));
} }
} }