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

Target

Select target project
  • ida-public/zellige-core
1 result
Select Git revision
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 );
}
} );
}
}
......@@ -6,13 +6,13 @@
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
......@@ -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 ) ->
/* Component behaviour */
constructionDisplay.getMinus().setOnAction( actionEvent ->
{
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 ) ->
constructionDisplay.previous();
setDisplay();
} );
constructionDisplay.getPlus().setOnAction( actionEvent ->
{
changedParameters.setValue( true );
constructionModel.secondRoundSurfacesProperty().setValue( null );
};
c2.sliderProperty().addListener( secondRoundListener );
r2.sliderProperty().addListener( secondRoundListener );
st2.sliderProperty().addListener( secondRoundListener );
surfaceSize.sliderProperty().addListener( secondRoundListener );
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();
}
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" );
constructionModel.referenceSurfacesProperty().setValue( null );
computeImageFXDisplay();
}
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 )
{
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 );
}
}
......@@ -6,13 +6,13 @@
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
......@@ -28,49 +28,38 @@
*/
package fr.pasteur.ida.zellige.gui.controller;
import fr.pasteur.ida.zellige.gui.ClassifiedImages;
import fr.pasteur.ida.zellige.gui.ChannelToolProperty;
import fr.pasteur.ida.zellige.gui.LogAppender;
import fr.pasteur.ida.zellige.gui.MainAppFrame;
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.model.ConstructionModel;
import fr.pasteur.ida.zellige.gui.model.MainModel;
import fr.pasteur.ida.zellige.gui.model.ProjectionModel;
import fr.pasteur.ida.zellige.gui.ProjectionProperties;
import fr.pasteur.ida.zellige.gui.model.*;
import fr.pasteur.ida.zellige.gui.model.SelectionModel;
import fr.pasteur.ida.zellige.gui.parameter.ConstructionParameter;
import fr.pasteur.ida.zellige.gui.parameter.ProjectionParameter;
import fr.pasteur.ida.zellige.gui.parameter.SelectionParameter;
import fr.pasteur.ida.zellige.gui.parameter.ZelligeParameters;
import fr.pasteur.ida.zellige.gui.task.AbstractTask;
import fr.pasteur.ida.zellige.gui.task.ComputeClassificationImagesTask;
import fr.pasteur.ida.zellige.gui.task.DisplayDatasetChoicesTask;
import fr.pasteur.ida.zellige.gui.task.PretreatmentTask;
import fr.pasteur.ida.zellige.gui.parameter.*;
import fr.pasteur.ida.zellige.steps.construction.rounds.ConstructionParameters;
import fr.pasteur.ida.zellige.steps.projection.ChannelProjectionParameter;
import fr.pasteur.ida.zellige.steps.projection.ProjectionParameters;
import fr.pasteur.ida.zellige.steps.selection.SelectionParameters;
import fr.pasteur.ida.zellige.steps.selection.pretreatment.PretreatmentParameters;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.stage.FileChooser;
import net.imagej.Dataset;
import net.imagej.ImgPlus;
import net.imglib2.img.Img;
import javafx.stage.Modality;
import javafx.stage.Stage;
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;
import java.io.File;
import java.io.IOException;
import java.awt.*;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.ResourceBundle;
......@@ -78,25 +67,22 @@ public class MainController< T extends RealType< T > & NativeType< T > > impleme
{
private final static Logger LOGGER = LoggerFactory.getLogger( MainController.class );
private final SimpleObjectProperty< Dataset > currentDataset = new SimpleObjectProperty<>();
private final SimpleObjectProperty< ClassifiedImages< FloatType > > images = new SimpleObjectProperty<>();
private final SimpleObjectProperty< Img< FloatType > > pretreatedImg = new SimpleObjectProperty<>();
private final SimpleBooleanProperty disableGUI = new SimpleBooleanProperty();
private final SimpleBooleanProperty changedParameters = new SimpleBooleanProperty();
@FXML
ComboBox< Dataset > activeDatasets;
private PreprocessingController< T > preprocessingController;
@FXML
private Button runButton;
private SelectionController< T > selectionController;
@FXML
private ConstructionController< T > constructionController;
@FXML
private ProjectionController< T > projectionController;
@FXML
private TabPane tabPane;
@FXML
private Label logInfo;
private MainAppFrame mainAppFrame;
@FXML
private ProjectionController< T > projectionController;
@FXML
private SelectionController< T > selectionController;
MainModel< T > model;
......@@ -107,89 +93,44 @@ public class MainController< T extends RealType< T > & NativeType< T > > impleme
alert.setTitle( "Error alert" );
alert.setHeaderText( exception.getMessage() );
alert.showAndWait();
// throw new RuntimeException(exception);
// throw new RuntimeException(exception);
}
public static void showInfo( Exception exception )
{
Alert alert = new Alert( Alert.AlertType.INFORMATION );
alert.setTitle( "Info !" );
alert.setHeaderText( exception.getMessage() );
alert.showAndWait();
}
@Override
public void initialize( URL url, ResourceBundle resourceBundle )
{
model = new MainModel<>( selectionController.getSelectionModel(), constructionController.getConstructionModel(), projectionController.getModel() );
/* Control of the files comboBox*/
activeDatasets.setOnMousePressed( event ->
setAndDisplayDatasetChoices() );// Update of the list of opened Fiji images
activeDatasets.getSelectionModel().selectedItemProperty().addListener( ( observableValue, oldValue, newValue ) ->
{
LOGGER.debug( "selectedItemProperty : old value = {}, new value = {} ", oldValue, newValue );
if(newValue!= null && isValid( newValue ))
{
setCurrentDataset( newValue );
}
else
{
activeDatasets.getSelectionModel().selectLast();
}
} );
currentDataset.addListener( ( observableValue, dataset, t1 ) ->
{
if ( t1 != null )
{
selectionController.disableParameters();
disableGUI.setValue( true );
runPretreatment( currentDataset.getValue() );
}
else
{
pretreatedImg.setValue( null );
LOGGER.debug( "PRETREATED_IMAGE is NULL" );
}
} );
pretreatedImg.addListener( ( observable, oldValue, newValue ) ->
{
if ( newValue != null )
{
computeClassifiedImages();
}
else
{
images.setValue( null );
LOGGER.debug( "IMAGES is NULL" );
}
} );
disableGUI.addListener( ( observable, oldValue, newValue ) ->
runButton.setDisable( newValue ) );
// run button initialization
runButton.setOnAction( actionEvent ->
{
disableGUI.setValue( true );
changedParameters.setValue( false );
run2();
} );
model = new MainModel<>( preprocessingController.getModel(), selectionController.getModel(), constructionController.getModel(), projectionController.getModel() );
preprocessingController.setParent( this );
selectionController.setParent( this );
constructionController.setParent( this );
projectionController.setParent( this );
/* Binding properties*/
selectionController.getSelectionModel().pretreatedImgProperty().bind( pretreatedImg );
selectionController.getSelectionModel().imagesProperty().bind( images );
constructionController.getConstructionModel().maximumsProperty().bind( selectionController.getSelectionModel().selectedPixelsProperty() );
projectionController.getModel().referenceSurfacesProperty().bind( constructionController.getConstructionModel().referenceSurfacesProperty() );
changedParameters.bindBidirectional( selectionController.changedParametersProperty() );
selectionController.changedParametersProperty().bindBidirectional( constructionController.changedParametersProperty() );
constructionController.changedParametersProperty().bindBidirectional( projectionController.changedParametersProperty() );
disableGUI.bindBidirectional( selectionController.disableGUIProperty() );
changedParameters.addListener( ( observable, oldValue, newValue ) ->
preprocessingController.getDisableGUI().bindBidirectional( selectionController.disableGUIProperty() );
selectionController.getModel().pretreatedImgProperty().bind( preprocessingController.getModel().pretreatedImgProperty() );
constructionController.getModel().maximumsProperty().bind( selectionController.getModel().selectedPixelsProperty() );
constructionController.getModel().getBin().bind( preprocessingController.getModel().binProperty() );
constructionController.getModel().getChannelInput().bind( preprocessingController.getModel().getInput_channel() );
constructionController.getModel().getInput().bind( preprocessingController.getModel().getInput() );
constructionController.getModel().getFactory().bind( preprocessingController.getModel().getFactory() );
projectionController.getModel().getColors().bind( preprocessingController.getModel().getColors() );
// Sets the projection display when the projection tab is clicked on.
tabPane.getTabs().get( 2 ).selectedProperty().addListener( ( observableValue, number, newValue ) ->
{
LOGGER.debug( "Parameter change" );
if ( newValue )
if ( projectionController.getModel().getImageViews().get() != null )// if the reference surface have been generated
{
LOGGER.debug( "Active button" );
disableGUI.setValue( false );
projectionController.setDisplay();
}
LOGGER.debug( "the projection tab has been clicked on" );
} );
// Update of the program status using LOG.INFO outputs
......@@ -199,155 +140,184 @@ public class MainController< T extends RealType< T > & NativeType< T > > impleme
logInfo.setText( LogAppender.getLogMessage() ) ) );
}
public void initExtraction()
public void setMainApp( MainAppFrame mainAppFrame )
{
this.mainAppFrame = mainAppFrame;
}
LOGGER.debug( "Init Extraction" );
Dataset dataset = mainAppFrame.getImage().getActiveDataset();
LOGGER.debug( dataset.getImgPlus().firstElement().getClass().toGenericString() );
LOGGER.debug( "Function getFrames() :{}", dataset.getFrames() );
LOGGER.debug( "Properties :{}", dataset.getImgPlus().getProperties() );
if ( dataset == null )
@FXML
public void loadParameters() throws IOException
{
File f = chooseFile();
LOGGER.debug( "The file has been choose" );
if ( f != null )
{
showError( new NoInputException() );
return;
ZelligeParameters parameters = ZelligeParameters.deserialize( f );
setParameters( parameters );
}
activeDatasets.getItems().add( dataset );
LOGGER.debug( "Init Extraction completed" );
}
@FXML
private void openFileDialog()
{
BatchModeDialog dialog = new BatchModeDialog();
// Create a new Stage for the dialog
Stage dialogStage = new Stage();
dialogStage.setTitle( "Batch Mode" );
dialogStage.initModality( Modality.APPLICATION_MODAL ); // Blocks interaction with main window
dialogStage.setScene( new Scene( dialog ) );
// Show the dialog window
dialogStage.showAndWait(); // Use showAndWait() to wait until the dialog is closed
}
public void run2()
/**
* Prompts the user to save the embedded CSV file wherever they want.
* Opens the file after saving, if possible.
*/
@FXML
public void saveCSVExample()
{
// Create FileChooser in SAVE mode
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle( "Save Example CSV File" );
fileChooser.getExtensionFilters().add( new FileChooser.ExtensionFilter( "CSV Files", "*.csv" ) );
fileChooser.setInitialFileName( "batch_mode_csv_example.csv" );
if ( selectionController.getSelectionModel().selectedPixelsProperty().getValue() != null )
// Show the save dialog
File selectedFile = fileChooser.showSaveDialog( null );
if ( selectedFile != null )
{
if ( constructionController.getConstructionModel().referenceSurfacesProperty().getValue() != null )
// Try extracting the embedded file to the chosen location
try ( InputStream inputStream = getClass().getResourceAsStream( "/batch_mode_csv_example.csv" );
OutputStream outputStream = Files.newOutputStream( selectedFile.toPath() ) )
{
projectionController.getModel().runProjection();
if ( inputStream == null )
{
throw new FileNotFoundException( "Embedded resource 'batch_mode_csv_example.csv' not found." );
}
// Copy contents from resource to selected file
byte[] buffer = new byte[ 1024 ];
int length;
while ( ( length = inputStream.read( buffer ) ) != - 1 )
{
outputStream.write( buffer, 0, length );
}
LOGGER.debug( "File saved to: {}", selectedFile.getAbsolutePath() );
// Optionally open the file
openFile( selectedFile );
}
else
catch ( IOException e )
{
constructionController.getConstructionModel().runConstruction();
LOGGER.debug("Something went wrong with the batch-mode CSV example");
}
}
else
{
selectionController.getSelectionModel().runPixelSelection();
System.out.println( "Save cancelled by user." );
}
LOGGER.debug( "###########################################---NEW RUN---###########################################" );
}
private void runPretreatment( Dataset dataset )
/**
* Opens the file in the system's default app (e.g. Notepad, Excel).
*
* @param file The file to open.
*/
private void openFile( File file )
{
AbstractTask< Img< FloatType > > task = new PretreatmentTask<>( dataset );
task.setOnSucceeded( workerStateEvent ->
pretreatedImg.setValue( task.getValue() ) );
task.start();
}
public void setAndDisplayDatasetChoices()
{
DisplayDatasetChoicesTask displayTask = new DisplayDatasetChoicesTask( mainAppFrame.getImage() );
displayTask.setOnSucceeded( workerStateEvent ->
if ( Desktop.isDesktopSupported() )
{
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() )
try
{
currentDataset.setValue( null );
LOGGER.debug( "CURRENT_DATASET is NULL" );
showError( new NoInputException() );
Desktop.getDesktop().open( file );
}
} );
displayTask.start();
}
@SuppressWarnings( "unchecked" )
public void setCurrentDataset( Dataset dataset )
{
currentDataset.setValue( dataset );
Img< T > input = ( ImgPlus< T > ) dataset.getImgPlus();
constructionController.getConstructionModel().setInput( input );
constructionController.getConstructionModel().setFactory( input.factory() );
}
public void computeClassifiedImages()
{
ComputeClassificationImagesTask classifiedImagesTask = new ComputeClassificationImagesTask( pretreatedImg.getValue() );
classifiedImagesTask.setOnSucceeded( workerStateEvent -> images.set( classifiedImagesTask.getValue() ) );
classifiedImagesTask.start();
}
public void setMainApp( MainAppFrame mainAppFrame )
{
this.mainAppFrame = mainAppFrame;
}
public int getAmplitude()
{
return ( int ) selectionController.getAmplitude().getSlider().getValue();
}
public int getOtsu()
{
return ( int ) selectionController.getOtsu().getSlider().getValue();
catch ( IOException e )
{
LOGGER.debug( "Failed to open file: {}", file.getAbsolutePath() );
}
}
}
public int getIsland()
{
return ( int ) selectionController.getIsland().getSlider().getValue();
}
@FXML
public void saveParameters() throws IOException
{
SimpleDateFormat dtf = new SimpleDateFormat( "yyyyMMdd_HHmmss" );
FileChooser fileChooser = chooseAFile( dtf.format( new Date() ) + "_zellige_param", "Sava Parameters..." );
FileChooser fileChooser = chooseAFile( dtf.format( new Date() ) + "_zellige_param", "Save Parameters..." );
File file = fileChooser.showSaveDialog( null );
if ( file != null )
{
SelectionParameter sp = build( model.getSelectionModel() );
ConstructionParameter cp = build( model.getConstructionModel() );
ProjectionParameter pp = build( model.getProjectionModel() );
ZelligeParameters.serialize( new ZelligeParameters( sp, cp, pp ), file );
PretreatmentParameters prp = build( model.getPreprocessingModel() );
SelectionParameters sp = build( model.getSelectionModel() );
ConstructionParameters[] cp = build( model.getConstructionModel() );
ArrayList< ProjectionParameters > pp = build( model.getProjectionModel() );
ZelligeParameters.serialize( new ZelligeParameters( prp, sp, cp, pp ), file );
}
}
private SelectionParameter build( SelectionModel model )
private PretreatmentParameters build( PreprocessingModel< T > model )
{
return new SelectionParameter( model.amplitudeProperty(), model.otsuProperty(), model.islandProperty(), model.xyBlurProperty(), model.zBlurProperty() );
return new PretreatmentParameters( model.getChannel().get(), model.binProperty().get() );
}
private ConstructionParameter build( ConstructionModel< T > model )
private SelectionParameters build( SelectionModel model )
{
return new ConstructionParameter( model.c1Property(), model.r1Property(), model.st1Property(), model.c2Property(), model.r2Property(), model.st2Property(), model.surfaceSizeProperty() );
return new SelectionParameters(
model.amplitudeProperty().getValue(),
model.otsuProperty().getValue(),
model.xyBlurProperty().intValue(),
model.zBlurProperty().intValue(),
model.islandProperty().intValue() );
}
private ProjectionParameter build( ProjectionModel< T > model )
private ConstructionParameters[] build( ConstructionModel< T > model )
{
return new ProjectionParameter( model.delta1Property(), model.delta2Property(), model.methodProperty() );
ConstructionParameters[] parameters = new ConstructionParameters[ 2 ];
parameters[ 0 ] = new ConstructionParameters(
model.c1Property().value(),
model.r1Property().getValue(),
model.st1Property().value(),
model.surfaceSizeProperty().get() );
parameters[ 1 ] = new ConstructionParameters(
model.c2Property().value(),
model.r2Property().getValue(),
model.st2Property().value(),
model.surfaceSizeProperty().get() );
return parameters;
}
@FXML
public void loadParameters() throws IOException
private ArrayList< ProjectionParameters > build( ProjectionModel< T > model )
{
File f = chooseFile();
LOGGER.debug( "The file has been choose" );
if ( f != null )
ArrayList< ProjectionParameters > list = new ArrayList<>();
for ( int i = 0; i < getProjectionController().getModel().getReferenceSurfaces().get().size(); i++ )
{
ZelligeParameters parameters = ZelligeParameters.deserialize( f );
setParameters( parameters );
ProjectionProperties< T > projectionProperties = model.getProjectionProperties().get().get( i );
ArrayList< ChannelProjectionParameter > channelProjectionParameters = new ArrayList<>();
for ( int j = 0; j < projectionProperties.getProperties().get().size(); j++ )
{
ChannelToolProperty< T > channelToolProperty = projectionProperties.getProperties().get().get( j );
ChannelProjectionParameter cpp = new ChannelProjectionParameter(
channelToolProperty.getDeltaZ().get(),
channelToolProperty.getOffset().get(),
channelToolProperty.getMethod().get() );
channelProjectionParameters.add( cpp );
}
ProjectionParameters projectionParameter = new ProjectionParameters( channelProjectionParameters );
list.add( projectionParameter );
}
return list;
}
private File chooseFile()
{
FileChooser fileChooser = chooseAFile( null, "Select a Zellige parameter file"
......@@ -367,31 +337,31 @@ public class MainController< T extends RealType< T > & NativeType< T > > impleme
private void setParameters( ZelligeParameters parameters )
{
preprocessingController.setParameters( parameters );
selectionController.setParameters( parameters );
constructionController.setParameters( parameters );
projectionController.setParameters( parameters );
}
private boolean isValid(Dataset dataset)
public MainAppFrame getMainAppFrame()
{
int numZ = ( int ) dataset.getDepth();
int numFrames = ( int ) dataset.getFrames();
LOGGER.debug( "NUmber of dimensions: {}", dataset.numDimensions() );
LOGGER.debug( "NUmber of channels: {}", dataset.getChannels() );
LOGGER.debug( "Number of frames: {}", dataset.getFrames() );
if ( numFrames > 1 )
{
LOGGER.debug( "TimeLapseException" );
showError( new TimeLapseException() );
return false;
}
if ( numZ == 1 )
{
LOGGER.debug( "NoA3DStackException" );
showError( new NoA3DStackException() );
return false;
}
return true;
return mainAppFrame;
}
public PreprocessingController< T > getPreprocessingController()
{
return preprocessingController;
}
public ProjectionController< T > getProjectionController()
{
return projectionController;
}
public ConstructionController< T > getConstructionController()
{
return constructionController;
}
}
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 @@
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
......@@ -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;
public ProjectionController()
{
ProjectionModel< T > model = new ProjectionModel<>();
this.interactor = new ProjectionInteractor<>( model );
}
@Override
public void initialize( URL url, ResourceBundle resourceBundle )
{
// 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 ) ->
getModel().getImageViews().addListener( ( observableValue, number, newValue ) ->
{
if ( newValue != null )
{
getModel().getReferenceSurfaces().
set( parentController.getConstructionController().getModel().referenceSurfacesProperty().get() );
}
}
);
// Listening of the reference surface choiceBox
referenceSurfacesList.getSelectionModel().selectedIndexProperty().addListener( ( observableValue, number, newValue ) ->
{
model.delta1FunctionsProperty().setValue( false );
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() )
if ( newValue.intValue() != -1 )
{
model.showProjections();
currentIndex.set( newValue.intValue() );
LOGGER.debug( "Checking Reference surface n°{}", currentIndex.get() );
setDisplay();
setProjectionPane();
}
} );
rawHeightMap.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
{
if ( model.delta1FunctionsProperty().getValue() && t1 && rawHeightMap.isNotDisplayed() )
{
model.showRawHeightMap();
}
} );
extractedHeightMap.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
getModel().getReferenceSurfaces().addListener( ( observableValue, number, newValue ) ->
{
if ( model.delta1FunctionsProperty().getValue() && t1 && extractedHeightMap.isNotDisplayed() )
if ( newValue != null )
{
model.showExtractedHeightMaps();
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++ )
{
// 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();
}
} );
segmentedSurfaceMask.selectedProperty().addListener( ( observableValue, aBoolean, t1 ) ->
{
if ( model.delta2FunctionsProperty().getValue() && t1 && segmentedSurfaceMask.isNotDisplayed() )
{
/* Components*/
displayRS.setOnAction( actionEvent -> interactor.displayHM( currentIndex.intValue() ) );
}
model.showSegmentedSurfaceMask();
}
} );
public void setDisplay()
{
display.getChildren().clear();
ImageView i = getModel().getImageViews().getValue()[ currentIndex.get() ];
display.getChildren().add( i );
// setting of ZSlider
}
// Model Properties
model.referenceSurfacesProperty().addListener( ( observableValue, referenceSurfaces1, t1 ) ->
public void setProjectionPane()
{
int length = stackPane.getChildren().size();
for ( int i = 0; i < length; i++ )
{
if ( t1 == null )
{
model.delta1FunctionsProperty().setValue( false );
LOGGER.debug( "REFERENCE_SURFACES is NULL" );
}
else
{
LOGGER.info( "Extraction of {} surfaces", model.referenceSurfacesProperty().getValue().size() );
LOGGER.debug( "Compute output delta1" );
model.setOutputDelta1();
resetDisplayMode();
}
} );
Node node = stackPane.getChildren().get( i );
node.setVisible( i == currentIndex.get() );
}
LOGGER.debug( "Displaying channel panel n°{}\n", ( currentIndex.get() + 1 ) );
}
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 )
{
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 ?
}
}
......@@ -6,13 +6,13 @@
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
......@@ -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();
/* JavaFx Components */
//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 */
// 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 slider initialization */
stack.setAlignment( Pos.CENTER );
amplitude.sliderProperty().addListener( ( observableValue, number, newValue ) ->
// 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 )
{
disableGUI.setValue( true );
selectionModel.runOtsuTask();
changedParameters.setValue( true );
}
run();
} );
island.getSlider().valueProperty().addListener( ( observableValue, number, t1 ) ->
/* 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 ) ->
{
if ( island.hasChanged( t1 ) )
if ( newValue )
{
selectionModel.setIslandSearchImage( null );
changedParameters.setValue( true );
disableParameters();
}
else
{
enableParameters();
}
} );
xyBlur.sliderProperty().addListener( ( observable, oldValue, newValue ) ->
/* 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 ( xyBlur.hasChanged( newValue ) )
LOGGER.debug( "Pretreated image value update." );
if ( getModel().pretreatedImgProperty().getValue() != null )
{
selectionModel.setSelectedPixels( null );
changedParameters.setValue( true );
LOGGER.debug( " Update value is valid : starting computing classified images" );
interactor.computeClassifiedImages();
}
} );
zBlur.sliderProperty().addListener( ( observable, oldValue, newValue ) ->
getModel().imagesProperty().addListener( ( observableValue, number, newValue ) ->
{
if ( zBlur.hasChanged( newValue ) )
if ( newValue != null )
{
selectionModel.setSelectedPixels( null );
changedParameters.setValue( true );
interactor.runAmplitudeTask();
interactor.runOtsuTask();
}
} );
stack.setAlignment( Pos.CENTER );
// section Slider initialization
zSlices.getSlider().valueProperty().addListener( ( observableValue, number, newValue ) ->
getModel().selectedAmplitudeProperty().addListener( ( observableValue, number, newValue ) ->
{
int newZValue = newValue.intValue();
if ( zSlices.hasChanged( newZValue ) )
if ( newValue != null && getModel().selectedOtsuProperty().getValue() != null )
{
refreshDisplay( newZValue );
interactor.runInterClassification();
}
} );
/* Properties */
disableGUI.addListener( ( observable, oldValue, newValue ) ->
getModel().selectedOtsuProperty().addListener( ( observableValue, number, newValue ) ->
{
if ( newValue )
{
disableParameters();
}
else
if ( newValue != null && getModel().selectedAmplitudeProperty().getValue() != null )
{
enableParameters();
interactor.runInterClassification();
}
} );
selectionModel.imagesProperty().addListener( ( observableValue, classifiedImages, t1 ) ->
getModel().interClassifiedImageProperty().addListener( ( observableValue, number, newValue ) ->
{
if ( t1 != null )
{
selectionModel.runAmplitudeTask();
selectionModel.runOtsuTask();
}
else
if ( newValue != null )
{
LOGGER.debug( "IMAGES is NULL" );
selectionModel.selectedAmplitudeProperty().setValue( null );
selectionModel.selectedOtsuProperty().setValue( null );
selectionModel.interClassifiedImageProperty().setValue( null );
interactor.runIslandSearch();
}
} );
ChangeListener< Img< BitType > > listener = ( observableValue, bitTypeClassifiedImages, t1 ) ->
getModel().islandSearchImageProperty().addListener( ( observableValue, number, newValue ) ->
{
if ( selectionModel.selectedAmplitudeProperty().getValue() != null && selectionModel.selectedOtsuProperty().getValue() != null )
{
selectionModel.runInterClassification();
LOGGER.debug( "Inter classification" );
}
else
if ( newValue != null )
{
LOGGER.debug( "SELECTED_AMPLITUDE or SELECTED_OTSU is NULL" );
selectionModel.interClassifiedImageProperty().setValue( null );
interactor.runSmoothing();
}
} );
};
selectionModel.selectedAmplitudeProperty().addListener( listener );
selectionModel.selectedOtsuProperty().addListener( listener );
selectionModel.interClassifiedImageProperty().addListener( ( observable, oldValue, newValue ) ->
getModel().selectedPixelsProperty().addListener( ( observableValue, number, newValue ) ->
{
LOGGER.info( "Computing double classification..." );
if ( newValue != null )
{
computeImageFXDisplay();
}
selectionModel.islandSearchImageProperty().setValue( null );
} );
}
selectionModel.islandSearchImageProperty().addListener( ( observableValue, bitTypes, t1 ) ->
public void run()
{
parentController.getPreprocessingController().checkParameters();
checkParameters();
if (! parentController.getPreprocessingController().getInteractor().getModel().getParameterChanged().get() && ! getModel().getParameterChanged().get())
{
showInfo( new NoParameterChangeException() );
}
else
{
if ( t1 == null )
if ( getModel().pretreatedImgProperty().getValue() == null )
{
LOGGER.debug( "ISLAND_SEARCH is NULL" );
selectionModel.selectedPixelsProperty().setValue( null );
disableGUI.setValue( true );
parentController.getPreprocessingController().getInteractor().runPreprocessing();
}
else
else if ( getModel().selectedAmplitudeProperty().getValue() == null || getModel().selectedOtsuProperty().getValue() == null )
{
selectionModel.runSmoothing();
disableGUI.setValue( true );
if ( getModel().selectedAmplitudeProperty().getValue() == null )
{
interactor.runAmplitudeTask();
}
if ( getModel().selectedOtsuProperty().getValue() == null )
{
interactor.runOtsuTask();
}
}
} );
else if (getModel().islandSearchImageProperty().getValue() == null )
{
disableGUI.setValue( true );
interactor.runIslandSearch();
}
else if ( getModel().selectedPixelsProperty().getValue() == null )
{
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 )
{
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 resetOutputFromParameter( SimpleObjectProperty< ? > result, IntegerProperty property )
{
return selectionModel;
property.addListener( ( observable, oldValue, newValue ) ->
result.set( null ) );
}
public void setParameters( ZelligeParameters parameters )
public SimpleBooleanProperty getDisableGUI()
{
amplitude.setValue( parameters.getAmplitude() );
otsu.setValue( parameters.getOtsu() );
island.setValue( parameters.getIsland() );
xyBlur.setValue( parameters.getXyBlur() );
zBlur.setValue( parameters.getzBlur() );
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()
public IntegerProperty getBin()
{
LOGGER.debug( "Run construction" );
if ( firstRoundSurfacesProperty().getValue() == null )
{
firstRound();
}
else if ( secondRoundSurfaces.getValue() == null )
{
secondRound();
}
return bin;
}
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()
{
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()
{
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()));
}
}