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();
});
});
});
}
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;
}
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;
}
Aggregations