Search in sources :

Example 1 with FitParams

use of flimlib.flimj.FitParams in project flimj-ui by flimlib.

the class SettingsCtrl method initialize.

@Override
public void initialize() {
    paramLabels = new ArrayList<>();
    paramValues = new ArrayList<>();
    paramFixed = new ArrayList<>();
    paramIndices = new ArrayList<>();
    presentDatasets = new HashMap<>();
    // keep only the table header (remove the preview parameters)
    paramPane.getChildren().removeIf(child -> GridPane.getRowIndex(child) > 0);
    // numerical fields
    iThreshSpinner.setMin(0.0);
    iThreshSpinner.setStepSize(1.0);
    iThreshSpinner.getNumberProperty().addListener((obs, oldVal, newVal) -> {
        FitParams<FloatType> params = getParams();
        params.iThresh = newVal.floatValue();
        ObjectProperty<Double> binSizeProperty = binSizeSpinner.getNumberProperty();
        if (binSizeProperty.get() == 0.0) {
            threshBinZero = newVal.floatValue();
        }
        // recalculate global trans for pixels above threshold
        fp.invalidateGlobalTrans();
        // turn off estimate based on percentage
        // otherwise user's setting iThresh = 0 triggers that
        params.iThreshPercent = params.iThresh >= 0 ? -1 : 5;
        requestUpdate();
    });
    HashMap<String, Double> kwMap = new HashMap<>();
    kwMap.put("FULL", -1.0);
    binSizeSpinner.setKwMap(kwMap);
    binSizeSpinner.setIntOnly(true);
    binSizeSpinner.setMin(0.0);
    binSizeSpinner.setMax(255.0);
    binSizeSpinner.setStepSize(1.0);
    binSizeSpinner.getNumberProperty().addListener((obs, oldVal, newVal) -> {
        MainCtrl mainCtrl = (MainCtrl) parentCtrl;
        // display pending state
        mainCtrl.setProgress(-1.0);
        // binning will freeze the JFX thread and not allow the +/- event to be consumed
        // which causes indefinite +/- and resulting calls to setBinning()
        fp.submitRunnable(() -> {
            fp.setBinning(newVal.intValue());
            // update of UI components should be run from JFX thread
            Platform.runLater(() -> {
                binSizeSpinner.setDisable(fullBinningCheckBox.isSelected());
                // restore from pending state
                mainCtrl.setProgress(null);
                requestUpdate();
            });
        });
    });
    fullBinningCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() {

        private double lastSize;

        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
            ObjectProperty<Double> binSizeProperty = binSizeSpinner.getNumberProperty();
            ObjectProperty<Double> iThreshProperty = iThreshSpinner.getNumberProperty();
            if (newValue) {
                lastSize = binSizeProperty.get();
                binSizeProperty.set(-1.0);
                iThreshProperty.set(threshBinZero);
                iThreshSpinner.setDisable(true);
            } else {
                binSizeSpinner.setDisable(false);
                binSizeProperty.set(lastSize);
                iThreshSpinner.setDisable(false);
                iThreshProperty.set(threshBinZero);
            }
        }
    });
    // CB's
    noiseChoiceBox.setConverter(new StringConverter<NoiseType>() {

        @Override
        public String toString(NoiseType noiseType) {
            switch(noiseType) {
                case NOISE_GAUSSIAN_FIT:
                    return "Gaussian (Fit)";
                case NOISE_POISSON_FIT:
                    return "Poisson (Fit)";
                case NOISE_POISSON_DATA:
                    return "Poisson (Data)";
                case NOISE_MLE:
                    return "MLE";
                default:
                    return "";
            }
        }

        @Override
        public NoiseType fromString(String string) {
            switch(string) {
                case "Gaussian (Fit)":
                    return NoiseType.NOISE_GAUSSIAN_FIT;
                case "Poisson (Fit)":
                    return NoiseType.NOISE_POISSON_FIT;
                case "Poisson (Data)":
                    return NoiseType.NOISE_POISSON_DATA;
                case "MLE":
                    return NoiseType.NOISE_MLE;
                default:
                    return null;
            }
        }
    });
    // kept separate from numerical fields because they don't have onChange
    ChangeListener<Object> paramPaneUpdateHandler = (obs, oldVal, newVal) -> {
        final Integer nComp = nCompChoiceBox.getValue();
        final FitType algo = algoChoiceBox.getValue();
        FitParams<FloatType> params = getParams();
        params.nComp = nComp;
        fp.setAlgo(algo);
        setupParams(algo, nComp);
        // https://github.com/flimlib/flimj-ui/issues/9
        if (algo == FitType.Bayes) {
            nCompChoiceBox.setValue(1);
            nCompChoiceBox.setDisable(true);
            noiseChoiceBox.setDisable(true);
        } else {
            nCompChoiceBox.setDisable(false);
            noiseChoiceBox.setDisable(false);
        }
        // resize and initialize the two arrays
        int nParam = fp.getNParam();
        int fillStart = params.paramFree.length;
        params.param = Arrays.copyOf(params.param, nParam);
        params.paramMap = ArrayImgs.floats(params.param, FitProcessor.swapInLtAxis(new long[] { 1, 1, nParam }, params.ltAxis));
        params.paramFree = Arrays.copyOf(params.paramFree, nParam);
        for (int i = fillStart; i < params.paramFree.length; i++) params.paramFree[i] = true;
        requestUpdate();
    };
    algoChoiceBox.valueProperty().addListener(paramPaneUpdateHandler);
    nCompChoiceBox.valueProperty().addListener(paramPaneUpdateHandler);
    noiseChoiceBox.valueProperty().addListener((obs, oldVal, newVal) -> {
        getParams().noise = noiseChoiceBox.getValue();
        requestUpdate();
    });
    irfChoiceBox.getItems().add("From file");
    irfChoiceBox.valueProperty().addListener((obs, oldVal, newVal) -> {
        // if no item is now selected, select the previously selected item
        if (newVal == null) {
            irfChoiceBox.setValue(oldVal);
            return;
        }
        // this happens when we recover from the above situation
        if (oldVal == null) {
            return;
        }
        FitParams<FloatType> chosenIRF;
        if ("From file".equals(newVal)) {
            // the name of selected dataset
            String currentSelection = oldVal;
            // choose from file
            File irfFile = getUIs().chooseFile("Choose IRF transient file", null, FileWidget.OPEN_STYLE);
            if (irfFile != null) {
                // not cancelled
                String irfPath = irfFile.getPath();
                if (irfPath.endsWith("asc") || getDss().canOpen(irfPath)) {
                    try {
                        chosenIRF = IRFDatasetFromFile(irfPath);
                        // throw away if canceled by user
                        if (chosenIRF != null) {
                            // use file name as irf name
                            currentSelection = irfPath.substring(irfPath.lastIndexOf(File.separator) + 1);
                            // add to options if not present ([0] = "None")
                            if (!presentDatasets.containsKey(currentSelection)) {
                                irfChoiceBox.getItems().add(1, currentSelection);
                            }
                            // remember/update IRF
                            presentDatasets.put(currentSelection, chosenIRF);
                        }
                    } catch (Exception e) {
                        getUIs().showDialog(String.format("Error occurred during opening %s\nSee Console log.", irfPath), "FLIMJ", MessageType.ERROR_MESSAGE, OptionType.OK_CANCEL_OPTION);
                        getLogs().error(e.getMessage());
                    }
                } else
                    getUIs().showDialog(String.format("%s cannot be opened as a Dataset or an ASCII number list.", irfPath), "FLIMJ", MessageType.ERROR_MESSAGE, OptionType.OK_CANCEL_OPTION);
            }
            // either set to the new, valid dataset or stick to the old one
            irfChoiceBox.setValue(currentSelection);
            return;
        } else if (!"None".equals(newVal)) {
            // locate the chosen dataset
            chosenIRF = presentDatasets.get(newVal);
        } else
            chosenIRF = null;
        // update IRF information and notify fp
        fp.setIRF(chosenIRF);
        requestUpdate();
    });
    fitButton.setOnAction(event -> {
        MainCtrl mainCtrl = (MainCtrl) parentCtrl;
        // check fit status every 0.1s untill stopped
        Timeline fittingBusyAnimTL = new Timeline(new KeyFrame(Duration.seconds(0.1), e -> mainCtrl.setProgress(fp.getFitProgress())));
        fittingBusyAnimTL.setCycleCount(Timeline.INDEFINITE);
        // do heavy lifting on a separate thread
        fp.submitRunnable(() -> {
            fittingBusyAnimTL.play();
            fp.fitDataset();
            // update UI when done
            Platform.runLater(() -> {
                // show "Done" for a brief moment
                fittingBusyAnimTL.stop();
                fittingBusyAnimTL.getKeyFrames().setAll(new KeyFrame(Duration.seconds(0.1), e -> mainCtrl.setProgress(null)));
                fittingBusyAnimTL.setCycleCount(1);
                fittingBusyAnimTL.play();
                // set new options
                List<String> previewOptions = new ArrayList<>();
                for (Text label : paramLabels) previewOptions.add(label.getText());
                previewOptions.add("τₘ");
                fp.setPreviewOptions(previewOptions);
                requestUpdate();
            });
        });
    });
}
Also used : EventHandler(javafx.event.EventHandler) Button(javafx.scene.control.Button) FitProcessor(flimlib.flimj.ui.FitProcessor) Arrays(java.util.Arrays) Point(net.imglib2.Point) Scanner(java.util.Scanner) HashMap(java.util.HashMap) FileWidget(org.scijava.widget.FileWidget) FitType(flimlib.flimj.ui.FitProcessor.FitType) ArrayList(java.util.ArrayList) FitResults(flimlib.flimj.FitResults) FloatType(net.imglib2.type.numeric.real.FloatType) Utils(flimlib.flimj.ui.Utils) Intervals(net.imglib2.util.Intervals) FitParamsPrompter(flimlib.flimj.ui.FitParamsPrompter) ArrayImgs(net.imglib2.img.array.ArrayImgs) NumericTextField(flimlib.flimj.ui.controls.NumericTextField) Dataset(net.imagej.Dataset) Views(net.imglib2.view.Views) GridPane(javafx.scene.layout.GridPane) Localizable(net.imglib2.Localizable) KeyFrame(javafx.animation.KeyFrame) ObjectProperty(javafx.beans.property.ObjectProperty) TextField(javafx.scene.control.TextField) MessageType(org.scijava.ui.DialogPrompt.MessageType) NoiseType(flimlib.NoiseType) CheckBox(javafx.scene.control.CheckBox) Font(javafx.scene.text.Font) Timeline(javafx.animation.Timeline) IOException(java.io.IOException) FitParams(flimlib.flimj.FitParams) StringConverter(javafx.util.StringConverter) File(java.io.File) ChoiceBox(javafx.scene.control.ChoiceBox) Platform(javafx.application.Platform) FXML(javafx.fxml.FXML) Text(javafx.scene.text.Text) List(java.util.List) ActionEvent(javafx.event.ActionEvent) Duration(javafx.util.Duration) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) NumericSpinner(flimlib.flimj.ui.controls.NumericSpinner) ObservableValue(javafx.beans.value.ObservableValue) ObservableList(javafx.collections.ObservableList) ChangeListener(javafx.beans.value.ChangeListener) OptionType(org.scijava.ui.DialogPrompt.OptionType) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) NoiseType(flimlib.NoiseType) FloatType(net.imglib2.type.numeric.real.FloatType) ObjectProperty(javafx.beans.property.ObjectProperty) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) FitType(flimlib.flimj.ui.FitProcessor.FitType) FitParams(flimlib.flimj.FitParams) Text(javafx.scene.text.Text) IOException(java.io.IOException) Timeline(javafx.animation.Timeline) KeyFrame(javafx.animation.KeyFrame) File(java.io.File)

Example 2 with FitParams

use of flimlib.flimj.FitParams in project flimj-ui by flimlib.

the class FLIMJCommand method initFX.

/**
 * Initializes the GUI frame.
 *
 * @param fxPanel the embeded channel
 * @throws IOException if the fxml is not found
 * @return <code>true</code> - if the operation is successful
 * @see <a href=
 *      "https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/swing-fx-interoperability.htm">oracle
 *      doc</a>
 */
private boolean initFX(final JFXPanel fxPanel) throws IOException {
    // load scene
    final FXMLLoader loader = AbstractCtrl.getFXMLLoader("plugin-layout");
    final Scene scene = loader.<Scene>load();
    fxPanel.setScene(scene);
    // init fitting worker
    final FitParams<FloatType> params = new FitParams<>();
    if (!FitParamsPrompter.populate(params, datasetView.getData(), datasetView))
        return false;
    fp = new FitProcessor(datasetView.context(), params);
    // init controllers
    final MainCtrl mainCtrl = loader.<MainCtrl>getController();
    mainCtrl.setFitProcessor(fp);
    fp.refreshControllers();
    fp.updateFit();
    return true;
}
Also used : FitParams(flimlib.flimj.FitParams) MainCtrl(flimlib.flimj.ui.controller.MainCtrl) Scene(javafx.scene.Scene) FXMLLoader(javafx.fxml.FXMLLoader) FloatType(net.imglib2.type.numeric.real.FloatType)

Example 3 with FitParams

use of flimlib.flimj.FitParams in project flimj-ui by flimlib.

the class SettingsCtrl method IRFDatasetFromFile.

private FitParams<FloatType> IRFDatasetFromFile(String irfPath) throws IOException {
    FitParams<FloatType> irfParams = new FitParams<>();
    if (irfPath.endsWith(".asc")) {
        // read whitespace separated data
        ArrayList<Float> irfTrans = new ArrayList<>();
        Scanner sc = new Scanner(new File(irfPath));
        while (sc.hasNextBigDecimal()) irfTrans.add(sc.nextBigDecimal().floatValue());
        sc.close();
        // get origTrans' size and ltAxis
        int ltAxis = fp.getParams().ltAxis;
        long[] transDim = new long[3];
        fp.getOrigTrans().dimensions(transDim);
        float[] irfTransArr = new float[(int) transDim[ltAxis]];
        // place the data at the end so that the leading 0's can be used for shifting
        for (int i = Math.max(irfTransArr.length - irfTrans.size(), 0), j = 0; i < irfTransArr.length; i++, j++) irfTransArr[i] = irfTrans.get(j);
        // create a fake image out of a single array along the ltAxis
        irfParams.transMap = Views.interval(Views.extendBorder(ArrayImgs.floats(irfTransArr, new long[] { 1, 1, irfTransArr.length })), new long[] { 0, 0, 0 }, new long[] { transDim[0] - 1, transDim[1] - 1, transDim[2] - 1 });
        irfParams.ltAxis = ltAxis;
    } else if (getDss().canOpen(irfPath)) {
        final Dataset dataset = getDss().open(irfPath);
        final Localizable pos = new Point(Intervals.minAsLongArray(dataset));
        if (!FitParamsPrompter.populate(irfParams, dataset, pos))
            irfParams = null;
    }
    return irfParams;
}
Also used : Scanner(java.util.Scanner) FitParams(flimlib.flimj.FitParams) Dataset(net.imagej.Dataset) ArrayList(java.util.ArrayList) Point(net.imglib2.Point) Point(net.imglib2.Point) Localizable(net.imglib2.Localizable) FloatType(net.imglib2.type.numeric.real.FloatType) File(java.io.File)

Aggregations

FitParams (flimlib.flimj.FitParams)3 FloatType (net.imglib2.type.numeric.real.FloatType)3 File (java.io.File)2 ArrayList (java.util.ArrayList)2 Scanner (java.util.Scanner)2 NoiseType (flimlib.NoiseType)1 FitResults (flimlib.flimj.FitResults)1 FitParamsPrompter (flimlib.flimj.ui.FitParamsPrompter)1 FitProcessor (flimlib.flimj.ui.FitProcessor)1 FitType (flimlib.flimj.ui.FitProcessor.FitType)1 Utils (flimlib.flimj.ui.Utils)1 MainCtrl (flimlib.flimj.ui.controller.MainCtrl)1 NumericSpinner (flimlib.flimj.ui.controls.NumericSpinner)1 NumericTextField (flimlib.flimj.ui.controls.NumericTextField)1 IOException (java.io.IOException)1 Arrays (java.util.Arrays)1 HashMap (java.util.HashMap)1 List (java.util.List)1 KeyFrame (javafx.animation.KeyFrame)1 Timeline (javafx.animation.Timeline)1