From dbe93f546a348ef57435ab918ce3ecd533f3f32c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 31 Oct 2017 17:02:28 +0300 Subject: [PATCH] Partially fixed plot group visualization --- .../numass/control/cryotemp/PKT8Device.java | 4 +- .../inr/numass/control/msp/MspDevice.java | 4 +- .../inr/numass/control/StorageHelper.kt | 6 +- .../control/readvac/VacCollectorDevice.java | 4 +- .../data/legacy/NumassFileEnvelope.java | 6 +- .../numass/scripts/times/AnalyzePoint.groovy | 2 +- .../numass/server/NumassStorageHandler.java | 4 +- .../numass/viewer/TestDirectoryViewer.java | 67 --- .../main/kotlin/inr/numass/viewer/MainView.kt | 262 ----------- .../inr/numass/viewer/NumassLoaderView.kt | 421 ------------------ .../inr/numass/viewer/SlowControlView.kt | 57 ++- .../kotlin/inr/numass/viewer/StorageView.kt | 67 ++- .../inr/numass/viewer/test/NumassTest.kt | 27 -- 13 files changed, 102 insertions(+), 829 deletions(-) delete mode 100644 numass-viewer/src/main/java/inr/numass/viewer/TestDirectoryViewer.java delete mode 100644 numass-viewer/src/main/kotlin/inr/numass/viewer/MainView.kt delete mode 100644 numass-viewer/src/main/kotlin/inr/numass/viewer/NumassLoaderView.kt delete mode 100644 numass-viewer/src/main/kotlin/inr/numass/viewer/test/NumassTest.kt diff --git a/numass-control/cryotemp/src/main/java/inr/numass/control/cryotemp/PKT8Device.java b/numass-control/cryotemp/src/main/java/inr/numass/control/cryotemp/PKT8Device.java index 40b5ab91..5ba24280 100644 --- a/numass-control/cryotemp/src/main/java/inr/numass/control/cryotemp/PKT8Device.java +++ b/numass-control/cryotemp/src/main/java/inr/numass/control/cryotemp/PKT8Device.java @@ -31,8 +31,8 @@ import hep.dataforge.exceptions.ControlException; import hep.dataforge.exceptions.MeasurementException; import hep.dataforge.exceptions.StorageException; import hep.dataforge.meta.Meta; -import hep.dataforge.storage.api.PointLoader; import hep.dataforge.storage.api.Storage; +import hep.dataforge.storage.api.TableLoader; import hep.dataforge.storage.commons.LoaderFactory; import hep.dataforge.tables.TableFormat; import hep.dataforge.tables.TableFormatBuilder; @@ -85,7 +85,7 @@ public class PKT8Device extends PortSensor { setMeta(meta); } - private PointLoader buildLoader(StorageConnection connection) { + private TableLoader buildLoader(StorageConnection connection) { Storage storage = connection.getStorage(); String suffix = DateTimeUtils.fileSuffix(); diff --git a/numass-control/msp/src/main/java/inr/numass/control/msp/MspDevice.java b/numass-control/msp/src/main/java/inr/numass/control/msp/MspDevice.java index 95ff3564..33cb2119 100644 --- a/numass-control/msp/src/main/java/inr/numass/control/msp/MspDevice.java +++ b/numass-control/msp/src/main/java/inr/numass/control/msp/MspDevice.java @@ -36,8 +36,8 @@ import hep.dataforge.exceptions.MeasurementException; import hep.dataforge.exceptions.PortException; import hep.dataforge.exceptions.StorageException; import hep.dataforge.meta.Meta; -import hep.dataforge.storage.api.PointLoader; import hep.dataforge.storage.api.Storage; +import hep.dataforge.storage.api.TableLoader; import hep.dataforge.storage.commons.LoaderFactory; import hep.dataforge.tables.TableFormat; import hep.dataforge.tables.TableFormatBuilder; @@ -421,7 +421,7 @@ public class MspDevice extends Sensor implements PortHandler.PortControl this.meta = meta; } - private PointLoader makeLoader(StorageConnection connection) { + private TableLoader makeLoader(StorageConnection connection) { try { Storage storage = connection.getStorage(); diff --git a/numass-control/src/main/kotlin/inr/numass/control/StorageHelper.kt b/numass-control/src/main/kotlin/inr/numass/control/StorageHelper.kt index ed5ad324..3c34da65 100644 --- a/numass-control/src/main/kotlin/inr/numass/control/StorageHelper.kt +++ b/numass-control/src/main/kotlin/inr/numass/control/StorageHelper.kt @@ -3,7 +3,7 @@ package inr.numass.control import hep.dataforge.control.connections.StorageConnection import hep.dataforge.control.devices.AbstractDevice import hep.dataforge.exceptions.StorageException -import hep.dataforge.storage.api.PointLoader +import hep.dataforge.storage.api.TableLoader import hep.dataforge.values.Values import java.util.* import java.util.function.Function @@ -12,8 +12,8 @@ import java.util.function.Function * A helper to store points in multiple loaders * Created by darksnake on 16-May-17. */ -class StorageHelper(private val device: AbstractDevice, private val loaderFactory: Function) : AutoCloseable { - private val loaderMap = HashMap() +class StorageHelper(private val device: AbstractDevice, private val loaderFactory: Function) : AutoCloseable { + private val loaderMap = HashMap() fun push(point: Values) { if (!device.hasState("storing") || device.getState("storing").booleanValue()) { diff --git a/numass-control/vac/src/main/java/inr/numass/control/readvac/VacCollectorDevice.java b/numass-control/vac/src/main/java/inr/numass/control/readvac/VacCollectorDevice.java index 5fa20d8a..fed9c1de 100644 --- a/numass-control/vac/src/main/java/inr/numass/control/readvac/VacCollectorDevice.java +++ b/numass-control/vac/src/main/java/inr/numass/control/readvac/VacCollectorDevice.java @@ -19,7 +19,7 @@ import hep.dataforge.control.measurements.Measurement; import hep.dataforge.description.ValueDef; import hep.dataforge.exceptions.ControlException; import hep.dataforge.meta.Meta; -import hep.dataforge.storage.api.PointLoader; +import hep.dataforge.storage.api.TableLoader; import hep.dataforge.storage.commons.LoaderFactory; import hep.dataforge.tables.TableFormatBuilder; import hep.dataforge.tables.ValueMap; @@ -113,7 +113,7 @@ public class VacCollectorDevice extends Sensor { } } - private PointLoader buildLoader(StorageConnection connection) { + private TableLoader buildLoader(StorageConnection connection) { TableFormatBuilder format = new TableFormatBuilder().setType("timestamp", ValueType.TIME); getSensors().forEach((s) -> { format.setType(s.getName(), ValueType.NUMBER); diff --git a/numass-core/src/main/java/inr/numass/data/legacy/NumassFileEnvelope.java b/numass-core/src/main/java/inr/numass/data/legacy/NumassFileEnvelope.java index 11eda987..7ad51427 100644 --- a/numass-core/src/main/java/inr/numass/data/legacy/NumassFileEnvelope.java +++ b/numass-core/src/main/java/inr/numass/data/legacy/NumassFileEnvelope.java @@ -23,8 +23,8 @@ public class NumassFileEnvelope extends FileEnvelope { try (SeekableByteChannel channel = Files.newByteChannel(path, READ)) { ByteBuffer header = ByteBuffer.allocate(2); channel.read(header); - if(Arrays.equals(header.array(),LEGACY_START_SEQUENCE)){ - return new NumassFileEnvelope(path,readOnly); + if (Arrays.equals(header.array(), LEGACY_START_SEQUENCE)) { + return new NumassFileEnvelope(path, readOnly); } else { return FileEnvelope.open(path, readOnly); } @@ -38,7 +38,7 @@ public class NumassFileEnvelope extends FileEnvelope { } @Override - protected EnvelopeTag buildTag(){ + protected EnvelopeTag buildTag() { return new NumassEnvelopeType.LegacyTag(); } } diff --git a/numass-main/src/main/groovy/inr/numass/scripts/times/AnalyzePoint.groovy b/numass-main/src/main/groovy/inr/numass/scripts/times/AnalyzePoint.groovy index 9d1dfb8d..49c62a13 100644 --- a/numass-main/src/main/groovy/inr/numass/scripts/times/AnalyzePoint.groovy +++ b/numass-main/src/main/groovy/inr/numass/scripts/times/AnalyzePoint.groovy @@ -26,7 +26,7 @@ ctx.pluginManager().load(PlotManager) ctx.pluginManager().load(NumassPlugin.class) new GrindShell(ctx).eval { - File rootDir = new File("D:\\Work\\Numass\\data\\2017_05\\Fill_2") + File rootDir = new File("D:\\Work\\Numass\\data\\2017_05\\Fill_3") NumassStorage storage = NumassStorageFactory.buildLocal(rootDir); diff --git a/numass-server/src/main/java/inr/numass/server/NumassStorageHandler.java b/numass-server/src/main/java/inr/numass/server/NumassStorageHandler.java index a0da00c9..7f3caaf9 100644 --- a/numass-server/src/main/java/inr/numass/server/NumassStorageHandler.java +++ b/numass-server/src/main/java/inr/numass/server/NumassStorageHandler.java @@ -11,8 +11,8 @@ import hep.dataforge.server.ServerManager; import hep.dataforge.server.ServletUtils; import hep.dataforge.server.storage.StorageRatpackHandler; import hep.dataforge.storage.api.ObjectLoader; -import hep.dataforge.storage.api.PointLoader; import hep.dataforge.storage.api.Storage; +import hep.dataforge.storage.api.TableLoader; import inr.numass.data.api.NumassSet; import org.slf4j.LoggerFactory; import ratpack.handling.Context; @@ -73,7 +73,7 @@ public class NumassStorageHandler extends StorageRatpackHandler { } @Override - protected MetaBuilder pointLoaderPlotOptions(PointLoader loader) { + protected MetaBuilder pointLoaderPlotOptions(TableLoader loader) { MetaBuilder builder = super.pointLoaderPlotOptions(loader); if (loader.getName().startsWith("msp") || loader.getName().startsWith("vac") diff --git a/numass-viewer/src/main/java/inr/numass/viewer/TestDirectoryViewer.java b/numass-viewer/src/main/java/inr/numass/viewer/TestDirectoryViewer.java deleted file mode 100644 index 9347003c..00000000 --- a/numass-viewer/src/main/java/inr/numass/viewer/TestDirectoryViewer.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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; - -import hep.dataforge.storage.commons.StorageManager; -import inr.numass.data.storage.NumassDataLoader; -import javafx.application.Application; -import javafx.scene.Scene; -import javafx.stage.Stage; - -import java.io.IOException; -import java.nio.file.Paths; - -/** - * @author darksnake - */ -public class TestDirectoryViewer extends Application { - - @Override - public void start(Stage stage) throws IOException { - new StorageManager().startGlobal(); - - NumassDataLoader reader = NumassDataLoader.fromDir(null, Paths.get("C:\\Users\\darksnake\\Dropbox\\PlayGround\\data-test\\20150703143643_1\\"), null); -// NumassLoader reader = NumassLoader.fromZip(null, new File("C:\\Users\\darksnake\\Dropbox\\PlayGround\\data-test\\20150703143643_1.zip")); - - NumassLoaderView comp = new NumassLoaderView(); - comp.loadData(reader); -// FXMLLoader fxml = new FXMLLoader(getClass().getResource("/fxml/DirectoryViewer.fxml")); -// -// Parent parent = fxml.load(); -// -// NumassLoaderViewController controller = fxml.getController(); -// -// controller.setModel(reader); - - Scene scene = new Scene(comp.getRoot(), 800, 600); - - stage.setTitle("Detector Visualisation test"); - stage.setScene(scene); - stage.setMinHeight(600); - stage.setMinWidth(800); -// primaryStage.setResizable(false); - - stage.show(); - } - - /** - * @param args the command line arguments - */ - public static void main(String[] args) { - launch(args); - } - -} diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/MainView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/MainView.kt deleted file mode 100644 index 561c7421..00000000 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/MainView.kt +++ /dev/null @@ -1,262 +0,0 @@ -package inr.numass.viewer - -import hep.dataforge.context.Context -import hep.dataforge.context.Global -import hep.dataforge.exceptions.StorageException -import hep.dataforge.fx.fragments.FragmentWindow -import hep.dataforge.fx.fragments.LogFragment -import hep.dataforge.meta.Metoid -import hep.dataforge.names.AlphanumComparator -import hep.dataforge.names.Named -import hep.dataforge.storage.api.PointLoader -import hep.dataforge.storage.api.Storage -import hep.dataforge.storage.filestorage.FileStorageFactory -import inr.numass.NumassProperties -import inr.numass.data.api.NumassSet -import inr.numass.data.storage.NumassStorage -import javafx.application.Platform -import javafx.beans.property.SimpleObjectProperty -import javafx.geometry.Insets -import javafx.scene.control.* -import javafx.scene.control.TreeTableView.CONSTRAINED_RESIZE_POLICY -import javafx.scene.input.MouseEvent -import javafx.scene.layout.AnchorPane -import javafx.scene.layout.BorderPane -import javafx.scene.layout.GridPane -import javafx.stage.DirectoryChooser -import javafx.util.Pair -import org.controlsfx.control.StatusBar -import tornadofx.* -import java.io.File -import java.net.URI -import java.util.logging.Level - -/** - * Created by darksnake on 14-Apr-17. - */ -@Deprecated("obsolete") -class MainView : View("Numass data viewer") { - override val root: AnchorPane by fxml("/fxml/MainView.fxml"); - - private val numassLoaderView: NumassLoaderView by inject() - private val slowControlView: SlowControlView by inject() - - private val consoleButton: ToggleButton by fxid() -// private val processManagerButton: ToggleButton by fxid() - private val loadDirectoryButton: Button by fxid() - private val loadRemoteButton: Button by fxid() - private val storagePathLabel: Label by fxid() - - private val loaderPane: BorderPane by fxid() - private val treePane: BorderPane by fxid() - private val statusBar: StatusBar by fxid() - - private val logFragment = FragmentWindow.build(consoleButton) { - LogFragment().apply { - addRootLogHandler() - } - } - -// private val processFragment = FragmentWindow.builder(processManagerButton) { -// WorkManagerFragment(getWorkManager()) -// } - - private val storageProperty = SimpleObjectProperty(); - - init { - loadDirectoryButton.action { - val chooser = DirectoryChooser() - chooser.title = "Select numass storage root" - val storageRoot = NumassProperties.getNumassProperty("numass.storage.root") - try { - if (storageRoot == null) { - chooser.initialDirectory = File(".").absoluteFile - } else { - chooser.initialDirectory = File(storageRoot) - } - } catch (ex: Exception) { - NumassProperties.setNumassProperty("numass.storage.root", null) - } - - val rootDir = chooser.showDialog(primaryStage.scene.window) - - if (rootDir != null) { - NumassProperties.setNumassProperty("numass.storage.root", rootDir.absolutePath) - loadDirectory(rootDir.toURI()) - } - } - loadRemoteButton.action { onLoadRemote() } - - treePane.center { - treetableview { - val nameColumnt = column("name", Item::getName).apply { - sortType = TreeTableColumn.SortType.ASCENDING - } - - val timeColumn = column("time", Item::getTime).apply { - isVisible = false - } - - sortOrder.add(nameColumnt) - - addEventHandler(MouseEvent.MOUSE_CLICKED) { e: MouseEvent -> - if (e.clickCount == 2) { - val value = focusModel.focusedCell.treeItem.value - when (value.content) { - is NumassSet -> { - numassLoaderView.loadData(value.content) - loaderPane.center = numassLoaderView.root - } - is PointLoader -> { - val loader: PointLoader = value.content; - slowControlView.load(loader); - loaderPane.center = slowControlView.root - } - } - } - } - - isTableMenuButtonVisible = true - columnResizePolicy = CONSTRAINED_RESIZE_POLICY - - storageProperty.addListener { _, _, value -> - if (value != null) { - Platform.runLater { - root = TreeItem(Item(value)); - - root.isExpanded = true - - populate { parent -> - val storage = parent.value.content; - if (storage is Storage) { - //TODO add legacy loaders here? - storage.shelves().map(::Item).sorted() + storage.loaders().map(::Item).sorted() - } else { - null - } - } - } - } else { - // TODO clear - } - } - - } - } - - primaryStage.setOnCloseRequest { - log.info("Closing storage") - storageProperty.get()?.close() - } - } - - private fun loadDirectory(path: URI) { - runAsync { - updateTitle("Load storage ($path)") - updateProgress(-1.0, -1.0); - updateMessage("Building numass storage tree...") - val root = NumassStorage(context, FileStorageFactory.buildStorageMeta(path, true, true)); - setRootStorage(root) - Platform.runLater { storagePathLabel.text = "Storage: " + path } - updateProgress(1.0, 1.0) - } - } - - private val context: Context - get() = Global.instance() - - fun setRootStorage(root: NumassStorage) { - - runAsync { - updateTitle("Fill data to UI (" + root.name + ")") - updateProgress(-1.0, 1.0) - Platform.runLater { statusBar.progress = -1.0 } - - updateMessage("Loading numass storage tree...") - - try { - storageProperty.set(root) - } catch (ex: StorageException) { - log.log(Level.SEVERE, null, ex) - } - - // callback.setProgress(1, 1); - Platform.runLater { statusBar.progress = 0.0 } - updateMessage("Numass storage tree loaded.") - updateProgress(1.0, 1.0) - } - } - - private fun onLoadRemote() { - // Create the custom dialog. - val dialog = Dialog>() - dialog.title = "Remote storage selection" - dialog.headerText = "Select remote storage login options and run" - - val loginButtonType = ButtonType("Load", ButtonBar.ButtonData.OK_DONE) - dialog.dialogPane.buttonTypes.addAll(loginButtonType, ButtonType.CANCEL) - - // Create the username and password labels and fields. - val grid = GridPane() - grid.hgap = 10.0 - grid.vgap = 10.0 - grid.padding = Insets(20.0, 150.0, 10.0, 10.0) - - val storageText = TextField() - storageText.prefWidth = 350.0 - storageText.text = "sftp://trdat:Anomaly@192.168.111.1" - val runText = TextField() - runText.promptText = "Run name" - - grid.add(Label("Storage path:"), 0, 0) - grid.add(storageText, 1, 0) - grid.add(Label("Run name:"), 0, 1) - grid.add(runText, 1, 1) - - dialog.dialogPane.content = grid - - // Request focus on the username field by default. - storageText.requestFocus() - - // Convert the result to a username-password-pair when the login button is clicked. - dialog.setResultConverter { dialogButton -> - if (dialogButton == loginButtonType) { - Pair(storageText.text, runText.text) - } else { - null; - } - } - - val result = dialog.showAndWait() - - if (result.isPresent) { - val path = URI.create(result.get().key + "/data/" + result.get().value) - loadDirectory(path) - } - } - - class Item(val content: Named) : Comparable { - override fun compareTo(other: Item): Int { - return AlphanumComparator.INSTANCE.compare(this.getName(), other.getName()) - } - - fun getName(): String { - return content.name; - } - - fun getTime(): String { - if (content is NumassSet) { - if (content.startTime == null) { - return "" - } else { - return content.startTime.toString() - } - } else if (content is Metoid) { - return content.meta().getString("file.timeModified", "") - } else { - return ""; - } - } - - } -} diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/NumassLoaderView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/NumassLoaderView.kt deleted file mode 100644 index 53ee0917..00000000 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/NumassLoaderView.kt +++ /dev/null @@ -1,421 +0,0 @@ -package inr.numass.viewer - -import hep.dataforge.context.Context -import hep.dataforge.context.Global -import hep.dataforge.io.ColumnedDataWriter -import hep.dataforge.kodex.buildMeta -import hep.dataforge.kodex.fx.plots.PlotContainer -import hep.dataforge.meta.Meta -import hep.dataforge.meta.MetaBuilder -import hep.dataforge.plots.PlotGroup -import hep.dataforge.plots.XYPlotFrame -import hep.dataforge.plots.data.DataPlot -import hep.dataforge.plots.data.DataPlotUtils -import hep.dataforge.plots.data.TimePlot -import hep.dataforge.plots.jfreechart.JFreeChartFrame -import hep.dataforge.storage.commons.JSONMetaWriter -import hep.dataforge.tables.Table -import hep.dataforge.tables.ValueMap -import hep.dataforge.tables.XYAdapter -import inr.numass.data.NumassDataUtils -import inr.numass.data.analyzers.SimpleAnalyzer -import inr.numass.data.api.NumassAnalyzer -import inr.numass.data.api.NumassPoint -import inr.numass.data.api.NumassSet -import javafx.application.Platform -import javafx.beans.property.SimpleObjectProperty -import javafx.beans.value.ObservableValue -import javafx.collections.FXCollections -import javafx.event.ActionEvent -import javafx.event.EventHandler -import javafx.geometry.Insets -import javafx.geometry.Orientation -import javafx.scene.control.* -import javafx.scene.layout.AnchorPane -import javafx.scene.layout.BorderPane -import javafx.stage.FileChooser -import javafx.util.converter.NumberStringConverter -import org.controlsfx.control.RangeSlider -import org.controlsfx.validation.ValidationSupport -import org.controlsfx.validation.Validator -import org.slf4j.LoggerFactory -import tornadofx.* -import java.io.IOException -import java.util.concurrent.atomic.AtomicInteger -import java.util.logging.Level -import java.util.stream.Collectors - - -/** - * Numass loader view - * - * Created by darksnake on 14-Apr-17. - */ -@Deprecated("obsolete") -class NumassLoaderView : View() { - override val root: AnchorPane by fxml("/fxml/NumassLoaderView.fxml") -// lateinit var main: MainView - - private val detectorPlotPane: BorderPane by fxid(); - // private val tabPane: TabPane by fxid(); - private val infoTextBox: TextArea by fxid(); - private val spectrumPlotPane: BorderPane by fxid(); - private val lowChannelField: TextField by fxid(); - private val upChannelField: TextField by fxid(); - private val channelSlider: RangeSlider by fxid(); - private val dTimeField: TextField by fxid(); - private val hvPane: BorderPane by fxid(); - private val spectrumExportButton: Button by fxid(); - -// private val detectorPlot: PlotContainer = PlotContainer.centerIn(detectorPlotPane) -// private val spectrumPlot: PlotContainer = PlotContainer.centerIn(spectrumPlotPane) -// private val hvPlot: PlotContainer = PlotContainer.centerIn(hvPane) - - - private val detectorBinningSelector: ChoiceBox = ChoiceBox(FXCollections.observableArrayList(1, 2, 5, 10, 20, 50)) - private val detectorNormalizeSwitch: CheckBox = CheckBox("Normalize") - private val detectorDataExportButton: Button = Button("Export") - - val dataProperty = SimpleObjectProperty() - var data: NumassSet? by dataProperty - - val analyzerProperty = SimpleObjectProperty(SimpleAnalyzer()) - var analyzer: NumassAnalyzer by analyzerProperty - - private val spectra = HashMap();//spectra cache - - val spectrumData = DataPlot("spectrum") - val hvPlotData = PlotGroup("hv") - //private var points = FXCollections.observableArrayList() - - val detectorPlotFrame = JFreeChartFrame( - MetaBuilder("frame") - .setValue("title", "Detector response plot") - .setNode(MetaBuilder("xAxis") - .setValue("axisTitle", "ADC") - .setValue("axisUnits", "channels") - .build()) - .setNode(MetaBuilder("yAxis") - .setValue("axisTitle", "count rate") - .setValue("axisUnits", "Hz") - .build()) - .setNode(MetaBuilder("legend") - .setValue("show", false)) - .build() - ) - - val plottableConfig = MetaBuilder("plot") - .setValue("connectionType", "step") - .setValue("thickness", 2) - .setValue("showLine", true) - .setValue("showSymbol", false) - .setValue("showErrors", false) - .setValue("JFreeChart.cache", true) - .build() - - - private val detectorPlot: PlotContainer = PlotContainer(detectorPlotFrame); - private val spectrumPlot: PlotContainer; - private val hvPlot: PlotContainer; - - init { - //setup detector pane frame and sidebar - val l = Label("Bin size:") - l.padding = Insets(5.0) - detectorBinningSelector.maxWidth = java.lang.Double.MAX_VALUE - detectorBinningSelector.selectionModel.clearAndSelect(4) - - detectorNormalizeSwitch.isSelected = true - detectorNormalizeSwitch.padding = Insets(5.0) - - detectorPlotPane.center = detectorPlot.root - detectorPlot.addToSideBar(0, l, detectorBinningSelector, detectorNormalizeSwitch, Separator(Orientation.HORIZONTAL)) - - detectorDataExportButton.maxWidth = java.lang.Double.MAX_VALUE - detectorDataExportButton.onAction = EventHandler { this.onExportButtonClick(it) } - detectorPlot.addToSideBar(detectorDataExportButton) - - detectorPlot.sideBarPoistion = 0.7 - //setup spectrum pane - - spectrumExportButton.onAction = EventHandler { this.onSpectrumExportClick(it) } - - val spectrumPlotMeta = MetaBuilder("plot") - .setValue("xAxis.axisTitle", "U") - .setValue("xAxis.axisUnits", "V") - .setValue("yAxis.axisTitle", "count rate") - .setValue("yAxis.axisUnits", "Hz") - .setValue("legend.show", false) - spectrumPlot = PlotContainer(JFreeChartFrame(spectrumPlotMeta).apply { add(spectrumData) }) - spectrumPlotPane.center = spectrumPlot.root - - lowChannelField.textProperty().bindBidirectional(channelSlider.lowValueProperty(), NumberStringConverter()) - upChannelField.textProperty().bindBidirectional(channelSlider.highValueProperty(), NumberStringConverter()) - - channelSlider.highValue = 1900.0 - channelSlider.lowValue = 300.0 - - detectorBinningSelector.selectionModel.selectedItemProperty().addListener { observable, oldValue, newValue -> - if (data != null) { - updateDetectorPane(data!!) - } - } - - detectorNormalizeSwitch.selectedProperty().addListener { observable, oldValue, newValue -> - if (data != null) { - updateDetectorPane(data!!) - } - } - - - dTimeField.textProperty().addListener { _: ObservableValue, _: String, _: String -> - if (data != null) { - updateSpectrum(data!!) - } - } - - val rangeChangeListener = { _: ObservableValue, _: Number, _: Number -> - if (data != null) { - updateSpectrum(data!!) - } - } - - channelSlider.lowValueProperty().addListener(rangeChangeListener) - channelSlider.highValueProperty().addListener(rangeChangeListener) - - val validationSupport = ValidationSupport() - val isNumber = { t: String -> - try { - java.lang.Double.parseDouble(t) - true - } catch (ex: Exception) { - false - } - } - - validationSupport.registerValidator(dTimeField, Validator.createPredicateValidator(isNumber, "Must be number")) - - //setup HV frame - val hvPlotMeta = MetaBuilder("plot") - .setValue("xAxis.axisTitle", "time") - .setValue("xAxis.type", "time") - .setValue("yAxis.axisTitle", "HV") - hvPlot = PlotContainer(JFreeChartFrame(hvPlotMeta)) - hvPane.center = hvPlot.root - - dataProperty.addListener { observable, oldValue, newData -> - //clearing spectra cache - if (oldValue != newData) { - spectra.clear() - } - - if (newData != null) { - runAsync { - updateTitle("Load numass data (" + newData.name + ")") - - //setup info - updateInfo(newData) - //setup hv frame - updateHV(newData) - //setup spectrum frame - updateSpectrum(newData) - //setup detector data - updateDetectorPane(newData) - - } - } else { - spectrumData.clear() - hvPlotData.clear() - } - } - - - } - - fun getContext(): Context { - return Global.getDefaultContext(); - } - - - fun loadData(data: NumassSet?) { - this.data = data; -// this.data = if (data == null) { -// data -// } else { -// NumassDataCache(data) -// } - } - - private fun updateHV(data: NumassSet) { - hvPlotData.clear() - runAsync { - data.hvData - } ui { hvData -> - hvData.ifPresent { - for (dp in it) { - val block = dp.getString("block", "default").replace(".","_") - if (!hvPlotData.has(block)) { - hvPlotData.add(TimePlot(block)) - } - (hvPlotData.opt(block).orElseThrow{RuntimeException()} as TimePlot) - .put(dp.getValue("timestamp").timeValue(), dp.getValue("value")) - } - hvPlot.frame.add(hvPlotData) - } - } - - } - - - private fun updateInfo(data: NumassSet) { - val info = data.meta() - infoTextBox.text = JSONMetaWriter().writeString(info).replace("\\r", "\r\t").replace("\\n", "\n\t") - } - - /** - * Get energy spectrum for a specific point - */ - private fun getSpectrum(point: NumassPoint): Table { - synchronized(this) { - return spectra.computeIfAbsent(point.voltage) { analyzer.getSpectrum(point, Meta.empty()) } - } - } - - private fun updateSpectrum(data: NumassSet) { - runAsync { - val loChannel = channelSlider.lowValue.toShort() - val upChannel = channelSlider.highValue.toShort() - data.points.map { point -> - val count = NumassAnalyzer.countInWindow(getSpectrum(point), loChannel, upChannel); - val seconds = point.length.toMillis() / 1000.0; - runLater { spectrumPlot.progress = -1.0 } - ValueMap.ofMap( - mapOf( - XYAdapter.X_AXIS to point.voltage, - XYAdapter.Y_AXIS to (count / seconds), - XYAdapter.Y_ERROR_KEY to Math.sqrt(count.toDouble()) / seconds - ) - ) - }.collect(Collectors.toList()) - } ui { points -> - spectrumData.fillData(points) - spectrumPlot.progress = 1.0 - spectrumExportButton.isDisable = false - } - } - - private val dTime: Double - get() { - try { - return java.lang.Double.parseDouble(dTimeField.text) * 1e-6 - } catch (ex: NumberFormatException) { - return 0.0 - } - } - - /** - * update detector pane with new data - */ - private fun updateDetectorPane(data: NumassSet) { - Platform.runLater { detectorPlotFrame.clear() } - - val binning = detectorBinningSelector.value - - val valueAxis = if (detectorNormalizeSwitch.isSelected) { - NumassAnalyzer.COUNT_RATE_KEY - } else { - NumassAnalyzer.COUNT_KEY - } - - runAsync { - Platform.runLater { detectorPlot.progressProperty.bind(progressProperty()) } - val totalCount = data.points.count(); - val index = AtomicInteger(0); - data.points.map { point -> - val seriesName = String.format("%d: %.2f", index.incrementAndGet(), point.voltage) - DataPlot.plot( - seriesName, - XYAdapter(NumassAnalyzer.CHANNEL_KEY, valueAxis), - NumassDataUtils.spectrumWithBinning(getSpectrum(point), binning) - ).apply { - configure(plottableConfig) - }.also { - updateProgress(index.get().toLong(), totalCount); - } - }.collect(Collectors.toList()) - } ui { plots -> - detectorPlotFrame.setAll(plots) - detectorDataExportButton.isDisable = false - } - } - - private fun onSpectrumExportClick(event: ActionEvent) { - if (data != null) { - val fileChooser = FileChooser() - fileChooser.title = "Choose text export destination" - fileChooser.initialFileName = data!!.name + "_spectrum.onComplete" - val destination = fileChooser.showSaveDialog(spectrumPlotPane.scene.window) - if (destination != null) { - val names = arrayOf("Uset", "Uread", "Length", "Total", "Window", "CR", "CRerr", "Timestamp") - val loChannel = channelSlider.lowValue.toInt() - val upChannel = channelSlider.highValue.toInt() - val dTime = dTime -// val spectrumDataSet = ListTable.Builder(*names) -// -// for (point in points) { -// spectrumDataSet.row( -// point.voltage, -// point.voltage, -// point.length, -// point.totalCount, -// point.getCountInWindow(loChannel, upChannel), -// NumassDataUtils.countRateWithDeadTime(point, loChannel, upChannel, dTime), -// NumassDataUtils.countRateWithDeadTimeErr(point, loChannel, upChannel, dTime), -// point.startTime -// ) -// } - val spectrumDataSet = analyzer.analyzeSet(data, buildMeta { - "window.lo" to loChannel - "window.up" to upChannel - }) - - try { - val comment = String.format("Numass data viewer spectrum data export for %s%n" - + "Window: (%d, %d)%n" - + "Dead time per event: %g%n", - data!!.name, loChannel, upChannel, dTime) - - ColumnedDataWriter - .writeTable(destination, spectrumDataSet, comment, false) - } catch (ex: IOException) { - log.log(Level.SEVERE, "Destination file not found", ex) - } - - } - } - - } - - private fun onExportButtonClick(event: ActionEvent) { - val fileChooser = FileChooser() - fileChooser.title = "Choose text export destination" - fileChooser.initialFileName = data!!.name + "_detector.out" - val destination = fileChooser.showSaveDialog(detectorPlotPane.scene.window) - if (destination != null) { - val detectorData = DataPlotUtils.collectXYDataFromPlot(detectorPlot.frame as XYPlotFrame, true) - try { - ColumnedDataWriter.writeTable( - destination, - detectorData, - "Numass data viewer detector data export for " + data!!.name, - false - ) - } catch (ex: IOException) { - LoggerFactory.getLogger(javaClass).error("Destination file not found", ex) - } - - } - - } - -} diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/SlowControlView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/SlowControlView.kt index 4d7d0ee3..768959af 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/SlowControlView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/SlowControlView.kt @@ -3,16 +3,21 @@ package inr.numass.viewer import hep.dataforge.kodex.configure import hep.dataforge.kodex.fx.dfIcon import hep.dataforge.kodex.fx.plots.PlotContainer +import hep.dataforge.kodex.fx.runGoal +import hep.dataforge.kodex.fx.ui import hep.dataforge.meta.Meta -import hep.dataforge.plots.Plot +import hep.dataforge.plots.PlotGroup import hep.dataforge.plots.data.DataPlot import hep.dataforge.plots.jfreechart.JFreeChartFrame -import hep.dataforge.storage.api.PointLoader +import hep.dataforge.storage.api.TableLoader import hep.dataforge.storage.api.ValueIndex import hep.dataforge.tables.ListTable import hep.dataforge.tables.Table import hep.dataforge.tables.XYAdapter import hep.dataforge.values.Values +import javafx.collections.FXCollections +import javafx.collections.MapChangeListener +import javafx.collections.ObservableMap import javafx.scene.image.ImageView import tornadofx.* @@ -30,26 +35,39 @@ class SlowControlView : View(title = "Numass slow control view", icon = ImageVie center = PlotContainer(plot).root } - //TODO add multiple loaders - fun load(loader: PointLoader) { - runAsync { - val data = getData(loader) - ArrayList().apply { - loader.format.columns.filter { it.name != "timestamp" }.forEach { - val adapter = XYAdapter("timestamp", it.name); - this += DataPlot.plot(it.name, adapter, data).configure { - "showLine" to true - "showSymbol" to false - "showErrors" to false + val data: ObservableMap = FXCollections.observableHashMap(); + val isEmpty = booleanBinding(data) { data.isEmpty() } + + init { + data.addListener { change: MapChangeListener.Change -> + if (change.wasRemoved()) { + plot.remove(change.key) + } + if (change.wasAdded()) { + runGoal("loadTable[${change.key}]") { + val plotData = getData(change.valueAdded) + val names = plotData.format.namesAsArray().filter { it != "timestamp" } + + val group = PlotGroup(change.key) + + names.forEach { + val adapter = XYAdapter("timestamp", it); + val plot = DataPlot.plot(it, adapter, plotData).configure { + "showLine" to true + "showSymbol" to false + "showErrors" to false + } + group.add(plot) } + group + } ui { + plot.add(it); } } - } ui { - plot.setAll(it) } } - private fun getData(loader: PointLoader, query: Meta = Meta.empty()): Table { + private fun getData(loader: TableLoader, query: Meta = Meta.empty()): Table { val index: ValueIndex = if (query.hasValue("index")) { //use custom index if needed @@ -63,7 +81,14 @@ class SlowControlView : View(title = "Numass slow control view", icon = ImageVie } catch (e: Exception) { throw RuntimeException(e) } + } + fun add(id: String, loader: TableLoader) { + this.data.put(id, loader) + } + + fun remove(id: String) { + this.data.remove(id) } } diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt index cf868b7a..afd30e73 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt @@ -7,8 +7,10 @@ import hep.dataforge.fx.fragments.LogFragment import hep.dataforge.kodex.fx.dfIcon import hep.dataforge.kodex.fx.runGoal import hep.dataforge.kodex.fx.ui +import hep.dataforge.meta.Metoid import hep.dataforge.storage.api.Loader import hep.dataforge.storage.api.Storage +import hep.dataforge.storage.api.TableLoader import hep.dataforge.storage.filestorage.FileStorageFactory import inr.numass.NumassProperties import inr.numass.data.api.NumassPoint @@ -71,6 +73,13 @@ class StorageView(private val context: Context = Global.instance()) : View(title hvView.remove(id) } } + is TableLoader -> { + if (selected) { + scView.add(id, content) + } else { + scView.remove(id) + } + } } } } @@ -132,43 +141,54 @@ class StorageView(private val context: Context = Global.instance()) : View(title populate { parent -> val value = parent.value.content when (value) { - is Storage -> (value.shelves() + value.loaders()).map { buildContainer(it, parent.value) } - is NumassSet -> value.points.map { buildContainer(it, parent.value) }.toList() + is Storage -> (value.shelves().sorted() + value.loaders().sorted()).map { buildContainer(it, parent.value) } + is NumassSet -> value.points.map { buildContainer(it, parent.value) }.toList().sortedBy { it.id } else -> null } } } } cellFormat { value -> - contextMenu = null when (value.content) { - is Storage -> text = value.id + is Storage -> { + text = value.id + graphic = null + } is NumassSet -> { text = null graphic = checkbox(value.id, value.checkedProperty) - contextMenu = ContextMenu().apply { - item("Info") { - action { - openInternalBuilderWindow(title = "Info: ${value.id}", escapeClosesWindow = true) { - scrollpane { - textarea { - isEditable = false - isWrapText = true - text = value.content.meta.toString().replace(" ", "\n\t") - } + } + is NumassPoint -> { + text = null + graphic = checkbox(value.id, value.checkedProperty) + } + is TableLoader -> { + text = null + graphic = checkbox(value.id, value.checkedProperty) + } + else -> { + text = value.id + graphic = null + } + } + if (value.content is Metoid) { + contextMenu = ContextMenu().apply { + item("Meta") { + action { + openInternalBuilderWindow(title = "Info: ${value.id}", escapeClosesWindow = true) { + scrollpane { + textarea { + isEditable = false + isWrapText = true + text = value.content.meta.toString().replace(" ", "\n\t") } } } } } } - is NumassPoint -> { - text = null - graphic = checkbox(value.id, value.checkedProperty) - } - else -> { - text = (value as Loader).name - } + } else { + contextMenu = null } } } @@ -189,6 +209,11 @@ class StorageView(private val context: Context = Global.instance()) : View(title isClosable = false //visibleWhen(spectrumView.isEmpty.not()) } + tab("Slow control") { + content = scView.root + isClosable = false + //visibleWhen(scView.isEmpty.not()) + } } setDividerPosition(0, 0.3); } diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/test/NumassTest.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/test/NumassTest.kt deleted file mode 100644 index 995dbdcb..00000000 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/test/NumassTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -package inr.numass.viewer.test - -import hep.dataforge.context.Global -import inr.numass.data.api.NumassSet -import inr.numass.data.storage.NumassStorageFactory -import inr.numass.viewer.NumassLoaderView -import javafx.application.Application -import javafx.stage.Stage -import tornadofx.* -import java.io.File - -/** - * Created by darksnake on 17-Jul-17. - */ -class NumassTest : App(NumassLoaderView::class) { - override fun start(stage: Stage) { - super.start(stage) - val storage = NumassStorageFactory.buildLocal(File("D:\\Work\\Numass\\data\\2017_05\\")) - Global.setDefaultContext(Global.instance()) - val view = find(); - view.data = storage.provide("Fill_1/set_4", NumassSet::class.java).get(); - } -} - -fun main(args: Array) { - Application.launch(NumassTest::class.java) -} \ No newline at end of file