numass-framework/numass-viewer/src/main/java/inr/numass/viewer/NumassLoaderViewComponent.java

434 lines
17 KiB
Java
Raw Normal View History

2015-12-18 16:20:47 +03:00
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.viewer;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
2016-08-26 19:21:43 +03:00
import hep.dataforge.computation.ProgressCallback;
import hep.dataforge.context.Context;
2015-12-18 16:20:47 +03:00
import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
2016-05-26 12:21:04 +03:00
import hep.dataforge.plots.PlotFrame;
2015-12-18 16:20:47 +03:00
import hep.dataforge.plots.XYPlotFrame;
import hep.dataforge.plots.data.*;
import hep.dataforge.plots.fx.PlotContainer;
2015-12-18 16:20:47 +03:00
import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import hep.dataforge.storage.commons.JSONMetaWriter;
import hep.dataforge.tables.*;
2016-05-02 18:23:03 +03:00
import inr.numass.storage.NMPoint;
import inr.numass.storage.NumassData;
2016-07-07 20:40:43 +03:00
import inr.numass.utils.TritiumUtils;
2015-12-27 18:04:05 +03:00
import javafx.application.Platform;
2015-12-21 16:40:21 +03:00
import javafx.beans.value.ChangeListener;
2015-12-18 16:20:47 +03:00
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.control.*;
2015-12-18 16:20:47 +03:00
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
2015-12-21 16:40:21 +03:00
import javafx.util.converter.NumberStringConverter;
2015-12-18 16:20:47 +03:00
import org.controlsfx.control.CheckListView;
2015-12-21 16:40:21 +03:00
import org.controlsfx.control.RangeSlider;
2015-12-27 18:04:05 +03:00
import org.controlsfx.validation.ValidationSupport;
import org.controlsfx.validation.Validator;
2015-12-18 16:20:47 +03:00
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
2015-12-18 16:20:47 +03:00
/**
* FXML Controller class
*
* @author darksnake
*/
public class NumassLoaderViewComponent extends AnchorPane implements Initializable {
2016-04-21 19:43:58 +03:00
private final Context context;
2015-12-21 16:40:21 +03:00
2015-12-18 16:20:47 +03:00
Logger logger = LoggerFactory.getLogger(NumassLoaderViewComponent.class);
private NumassData data;
private PlotContainer detectorPlot;
private PlotContainer spectrumPlot;
private PlotContainer hvPlot;
2015-12-21 16:40:21 +03:00
private ChangeablePlottableData spectrumData;
private List<NMPoint> points;
private ChoiceBox<Integer> detectorBinningSelector;
private CheckBox detectorNormalizeSwitch;
private Button detectorDataExportButton;
2015-12-18 16:20:47 +03:00
@FXML
private AnchorPane detectorPlotPane;
@FXML
private CheckListView<String> detectorPointListView;
@FXML
private Tab detectorTab;
@FXML
private Tab hvTab;
@FXML
private Tab spectrumTab;
@FXML
private TextArea infoTextBox;
@FXML
private AnchorPane spectrumPlotPane;
@FXML
private VBox spectrumOptionsPane;
@FXML
2015-12-21 16:40:21 +03:00
private TextField lowChannelField;
@FXML
private TextField upChannelField;
@FXML
private RangeSlider channelSlider;
2015-12-27 18:04:05 +03:00
@FXML
private Button spectrumExportButton;
@FXML
private TextField dTimeField;
@FXML
private AnchorPane hvPane;
2015-12-27 18:04:05 +03:00
2016-04-21 19:43:58 +03:00
public NumassLoaderViewComponent(Context context) {
this.context = context;
2015-12-27 18:04:05 +03:00
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/NumassLoaderView.fxml"));
loader.setRoot(this);
loader.setController(this);
try {
loader.load();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
2015-12-21 16:40:21 +03:00
2015-12-18 16:20:47 +03:00
/**
* Initializes the controller class.
2015-12-21 16:40:21 +03:00
*
2015-12-18 16:20:47 +03:00
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
//setup detector pane plot and sidebar
Label l = new Label("Bin size:");
l.setPadding(new Insets(5));
detectorBinningSelector = new ChoiceBox<>(FXCollections.observableArrayList(1, 2, 5, 10, 20, 50));
detectorBinningSelector.setMaxWidth(Double.MAX_VALUE);
2015-12-27 18:04:05 +03:00
detectorBinningSelector.getSelectionModel().select(4);
detectorNormalizeSwitch = new CheckBox("Normailize");
2015-12-18 16:20:47 +03:00
detectorNormalizeSwitch.setSelected(true);
detectorNormalizeSwitch.setPadding(new Insets(5));
detectorPlot = PlotContainer.anchorTo(detectorPlotPane);
detectorPlot.addToSideBar(0, l, detectorBinningSelector, detectorNormalizeSwitch, new Separator(Orientation.HORIZONTAL));
2015-12-18 16:20:47 +03:00
detectorDataExportButton = new Button("Export");
detectorDataExportButton.setMaxWidth(Double.MAX_VALUE);
2015-12-18 16:20:47 +03:00
detectorDataExportButton.setOnAction(this::onExportButtonClick);
detectorPlot.addToSideBar(detectorDataExportButton);
detectorPlot.setSideBarPosition(0.7);
//setup spectrum pane
spectrumPlot = PlotContainer.anchorTo(spectrumPlotPane);
Meta spectrumPlotMeta = new MetaBuilder("plot")
.setValue("xAxis.axisTitle", "U")
.setValue("xAxis.axisUnits", "V")
.setValue("yAxis.axisTitle", "count rate")
.setValue("yAxis.axisUnits", "Hz")
.setValue("legend.show", false);
spectrumPlot.setPlot(new JFreeChartFrame(spectrumPlotMeta));
2015-12-21 16:40:21 +03:00
lowChannelField.textProperty().bindBidirectional(channelSlider.lowValueProperty(), new NumberStringConverter());
upChannelField.textProperty().bindBidirectional(channelSlider.highValueProperty(), new NumberStringConverter());
2015-12-24 12:20:42 +03:00
2015-12-27 18:04:05 +03:00
channelSlider.setHighValue(1900d);
channelSlider.setLowValue(300d);
2015-12-24 12:20:42 +03:00
2015-12-21 16:40:21 +03:00
ChangeListener<? super Number> rangeChangeListener = (ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
setupSpectrumPane(points);
2015-12-21 16:40:21 +03:00
};
2015-12-24 12:20:42 +03:00
2015-12-27 18:04:05 +03:00
dTimeField.textProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
setupSpectrumPane(points);
2015-12-27 18:04:05 +03:00
});
2015-12-21 16:40:21 +03:00
channelSlider.lowValueProperty().addListener(rangeChangeListener);
channelSlider.highValueProperty().addListener(rangeChangeListener);
2015-12-27 18:04:05 +03:00
ValidationSupport validationSupport = new ValidationSupport();
Predicate<String> isNumber = (String t) -> {
try {
Double.parseDouble(t);
return true;
} catch (NumberFormatException | NullPointerException ex) {
return false;
}
};
validationSupport.registerValidator(dTimeField, Validator.createPredicateValidator(isNumber, "Must be number"));
//setup HV plot
hvPlot = PlotContainer.anchorTo(hvPane);
Meta hvPlotMeta = new MetaBuilder("plot")
.setValue("xAxis.axisTitle", "time")
.setValue("xAxis.type", "time")
.setValue("yAxis.axisTitle", "HV");
hvPlot.setPlot(new JFreeChartFrame(hvPlotMeta));
2015-12-18 16:20:47 +03:00
}
public NumassData getData() {
return data;
}
2015-12-27 18:04:05 +03:00
public void loadData(NumassData data) {
2015-12-18 16:20:47 +03:00
this.data = data;
if (data != null) {
2016-08-26 19:21:43 +03:00
context.workManager().<List<NMPoint>>submit("viewer.numass.load", (ProgressCallback callback) -> {
2016-04-21 19:43:58 +03:00
callback.updateTitle("Load numass data (" + data.getName() + ")");
points = data.getNMPoints();
2016-04-21 19:43:58 +03:00
Platform.runLater(() -> {
//setup detector data
setupDetectorPane(points);
//setup spectrum plot
setupSpectrumPane(points);
2016-04-21 19:43:58 +03:00
});
});
//setup hv plot
Supplier<Table> hvData = data.getHVData();
if (hvData != null) {
setupHVPane(hvData);
}
setupInfo(data);
2015-12-18 16:20:47 +03:00
} else {
logger.error("The data model is null");
}
2015-12-27 18:04:05 +03:00
detectorTab.getTabPane().getSelectionModel().select(detectorTab);
}
private void setupHVPane(Supplier<Table> hvData) {
2016-08-26 19:21:43 +03:00
context.workManager().submit("viewer.numass.hv", (ProgressCallback callback) -> {
Table t = hvData.get();
2015-12-27 18:04:05 +03:00
Platform.runLater(() -> {
if (t != null) {
hvPlot.getPlot().plottables().clear();
DynamicPlottableSet set = new DynamicPlottableSet();
for (DataPoint dp : t) {
String block = dp.getString("block", "default");
if (!set.hasPlottable(block)) {
set.addPlottable(new DynamicPlottable(block, block));
}
set.getPlottable(block).put(dp.getValue("timestamp").timeValue(), dp.getValue("value"));
}
hvPlot.getPlot().addAll(set);
}
2015-12-27 18:04:05 +03:00
});
});
2015-12-18 16:20:47 +03:00
}
/**
* setup detector pane
*
* @param points
*/
private void setupDetectorPane(List<NMPoint> points) {
boolean normalize = detectorNormalizeSwitch.isSelected();
int binning = detectorBinningSelector.getValue();
2016-05-26 12:21:04 +03:00
updateDetectorPane(points, binning, normalize);
2015-12-18 16:20:47 +03:00
detectorBinningSelector.getSelectionModel().selectedItemProperty()
.addListener((ObservableValue<? extends Integer> observable, Integer oldValue, Integer newValue) -> {
boolean norm = detectorNormalizeSwitch.isSelected();
2016-05-26 12:21:04 +03:00
updateDetectorPane(NumassLoaderViewComponent.this.points, newValue, norm);
2015-12-18 16:20:47 +03:00
});
detectorNormalizeSwitch.selectedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
int bin = detectorBinningSelector.getValue();
2016-05-26 12:21:04 +03:00
updateDetectorPane(NumassLoaderViewComponent.this.points, bin, newValue);
2015-12-18 16:20:47 +03:00
});
detectorDataExportButton.setDisable(false);
}
private void setupInfo(NumassData loader) {
2016-05-30 16:55:36 +03:00
Meta info = loader.meta();
2015-12-18 16:20:47 +03:00
infoTextBox.setText(new JSONMetaWriter().writeString(info, null).
2015-12-27 18:04:05 +03:00
replace("\\r", "\r\t").replace("\\n", "\n\t"));
2015-12-18 16:20:47 +03:00
}
private void setupSpectrumPane(List<NMPoint> points) {
2015-12-21 16:40:21 +03:00
if (spectrumData == null) {
2016-02-15 17:00:27 +03:00
spectrumData = new ChangeablePlottableData("spectrum");
spectrumPlot.getPlot().add(spectrumData);
2015-12-21 16:40:21 +03:00
}
2015-12-18 16:20:47 +03:00
2015-12-21 16:40:21 +03:00
int lowChannel = (int) channelSlider.getLowValue();
int highChannel = (int) channelSlider.getHighValue();
if (points == null || points.isEmpty()) {
spectrumData.clear();
} else {
spectrumData.fillData(points.stream()
2015-12-27 18:04:05 +03:00
.<DataPoint>map((NMPoint point) -> getSpectrumPoint(point, lowChannel, highChannel, getDTime()))
2015-12-21 16:40:21 +03:00
.collect(Collectors.toList()));
}
}
2015-12-18 16:20:47 +03:00
2015-12-27 18:04:05 +03:00
private double getDTime() {
try {
return Double.parseDouble(dTimeField.getText()) * 1e-6;
} catch (NumberFormatException ex) {
return 0;
}
}
private DataPoint getSpectrumPoint(NMPoint point, int lowChannel, int upChannel, double dTime) {
2015-12-21 16:40:21 +03:00
double u = point.getUread();
2016-02-28 20:08:59 +03:00
return new MapPoint(new String[]{"x", "y", "yErr"}, u,
2016-07-07 20:40:43 +03:00
TritiumUtils.countRateWithDeadTime(point,lowChannel, upChannel, dTime),
TritiumUtils.countRateWithDeadTimeErr(point,lowChannel, upChannel, dTime));
2015-12-18 16:20:47 +03:00
}
/**
* update detector pane with new data
*/
2016-05-26 12:21:04 +03:00
private void updateDetectorPane(List<NMPoint> points, int binning, boolean normalize) {
PlotFrame detectorPlotFrame;
if (detectorPlot.getPlot() == null) {
2015-12-27 18:04:05 +03:00
Meta frameMeta = new MetaBuilder("frame")
2016-05-26 12:21:04 +03:00
.setValue("title", "Detector response plot")
2015-12-27 18:04:05 +03:00
.setNode(new MetaBuilder("xAxis")
.setValue("axisTitle", "ADC")
.setValue("axisUnits", "channels")
.build())
.setNode(new MetaBuilder("yAxis")
.setValue("axisTitle", "count rate")
.setValue("axisUnits", "Hz")
.build())
.setNode(new MetaBuilder("legend")
.setValue("show", false))
2015-12-27 18:04:05 +03:00
.build();
2016-05-26 12:21:04 +03:00
detectorPlotFrame = new JFreeChartFrame(frameMeta);
} else {
detectorPlotFrame = detectorPlot.getPlot();
2016-05-29 15:19:42 +03:00
detectorPlotFrame.clear();
2016-05-26 12:21:04 +03:00
detectorPlot.removePlot();
}
2015-12-27 18:04:05 +03:00
2016-08-26 19:21:43 +03:00
context.workManager().submit("viewer.numass.load.detector", (ProgressCallback callback) -> {
2016-05-26 12:21:04 +03:00
Meta plottableConfig = new MetaBuilder("plot")
.setValue("connectionType", "step")
.setValue("thickness", 2)
.setValue("showLine", true)
.setValue("showSymbol", false)
.setValue("showErrors", false)
2016-05-29 15:19:42 +03:00
.setValue("JFreeChart.cache", true)
2016-05-26 12:21:04 +03:00
.build();
2015-12-27 18:04:05 +03:00
2016-05-26 12:21:04 +03:00
callback.setMaxProgress(points.size());
callback.setProgress(0);
for (NMPoint point : points) {
String seriesName = String.format("%d: %.2f", points.indexOf(point), point.getUset());
PlottableData datum = PlottableData.plot(seriesName, new XYAdapter("chanel", "count"), point.getData(binning, normalize));
datum.configure(plottableConfig);
detectorPlotFrame.add(datum);
callback.increaseProgress(1d);
//TODO add update instead of replace action
2015-12-27 18:04:05 +03:00
}
detectorPlot.setPlot(detectorPlotFrame);
2016-05-29 15:19:42 +03:00
callback.setProgressToMax();
2015-12-27 18:04:05 +03:00
});
2015-12-18 16:20:47 +03:00
}
2015-12-27 18:04:05 +03:00
@FXML
private void onSpectrumExportClick(ActionEvent event) {
if (points != null && !points.isEmpty()) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Choose text export destination");
fileChooser.setInitialFileName(data.getName() + "_spectrum.onComplete");
2015-12-27 18:04:05 +03:00
File destination = fileChooser.showSaveDialog(spectrumPlotPane.getScene().getWindow());
if (destination != null) {
String[] names = new String[]{"Uset", "Uread", "Length", "Total", "Window", "CR", "CRerr", "Timestamp"};
int loChannel = (int) channelSlider.getLowValue();
int upChannel = (int) channelSlider.getHighValue();
double dTime = getDTime();
ListTable.Builder spectrumDataSet = new ListTable.Builder(names);
2015-12-27 18:04:05 +03:00
for (NMPoint point : points) {
2016-07-11 17:03:50 +03:00
spectrumDataSet.row(new MapPoint(names, new Object[]{
2015-12-27 18:04:05 +03:00
point.getUset(),
point.getUread(),
point.getLength(),
point.getEventsCount(),
point.getCountInWindow(loChannel, upChannel),
2016-07-07 20:40:43 +03:00
TritiumUtils.countRateWithDeadTime(point,loChannel, upChannel, dTime),
TritiumUtils.countRateWithDeadTimeErr(point,loChannel, upChannel, dTime),
2015-12-27 18:04:05 +03:00
point.getStartTime()
}
));
}
try {
String comment = String.format("Numass data viewer spectrum data export for %s%n"
+ "Window: (%d, %d)%n"
+ "Dead time per event: %g%n",
data.getName(), loChannel, upChannel, dTime);
ColumnedDataWriter
.writeDataSet(destination, spectrumDataSet.build(), comment, false);
2015-12-27 18:04:05 +03:00
} catch (IOException ex) {
LoggerFactory.getLogger(getClass()).error("Destination file not found", ex);
}
}
}
}
2015-12-18 16:20:47 +03:00
private void onExportButtonClick(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Choose text export destination");
fileChooser.setInitialFileName(data.getName() + "_detector.onComplete");
2015-12-18 16:20:47 +03:00
File destination = fileChooser.showSaveDialog(detectorPlotPane.getScene().getWindow());
if (destination != null) {
Table detectorData = PlotDataUtils.collectXYDataFromPlot((XYPlotFrame) detectorPlot.getPlot(), true);
2015-12-18 16:20:47 +03:00
try {
ColumnedDataWriter
.writeDataSet(destination, detectorData, "Numass data viewer detector data export for " + data.getName(),
false);
} catch (IOException ex) {
LoggerFactory.getLogger(getClass()).error("Destination file not found", ex);
}
}
}
}