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
  • 10-multi-channel-image-handling
  • 25-multithreads-heavy-tasks
  • 9-gui-features
  • dev
  • dev-batch-mode
  • dev-display
  • master
  • 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
  • 10-multi-channel-image-handling
  • 25-multithreads-heavy-tasks
  • 9-gui-features
  • dev
  • dev-batch-mode
  • dev-display
  • master
  • 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
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;
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 );
}
}
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 );
}
} );
}
}
......@@ -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 );
}
}
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
......@@ -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 ?
}
}
......@@ -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;
}
}
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;
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()
......
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 @@
*/
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()));
}
}