Partially fixed plot group visualization
This commit is contained in:
parent
25251e64f9
commit
dbe93f546a
@ -31,8 +31,8 @@ import hep.dataforge.exceptions.ControlException;
|
|||||||
import hep.dataforge.exceptions.MeasurementException;
|
import hep.dataforge.exceptions.MeasurementException;
|
||||||
import hep.dataforge.exceptions.StorageException;
|
import hep.dataforge.exceptions.StorageException;
|
||||||
import hep.dataforge.meta.Meta;
|
import hep.dataforge.meta.Meta;
|
||||||
import hep.dataforge.storage.api.PointLoader;
|
|
||||||
import hep.dataforge.storage.api.Storage;
|
import hep.dataforge.storage.api.Storage;
|
||||||
|
import hep.dataforge.storage.api.TableLoader;
|
||||||
import hep.dataforge.storage.commons.LoaderFactory;
|
import hep.dataforge.storage.commons.LoaderFactory;
|
||||||
import hep.dataforge.tables.TableFormat;
|
import hep.dataforge.tables.TableFormat;
|
||||||
import hep.dataforge.tables.TableFormatBuilder;
|
import hep.dataforge.tables.TableFormatBuilder;
|
||||||
@ -85,7 +85,7 @@ public class PKT8Device extends PortSensor<PKT8Result> {
|
|||||||
setMeta(meta);
|
setMeta(meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PointLoader buildLoader(StorageConnection connection) {
|
private TableLoader buildLoader(StorageConnection connection) {
|
||||||
Storage storage = connection.getStorage();
|
Storage storage = connection.getStorage();
|
||||||
String suffix = DateTimeUtils.fileSuffix();
|
String suffix = DateTimeUtils.fileSuffix();
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ import hep.dataforge.exceptions.MeasurementException;
|
|||||||
import hep.dataforge.exceptions.PortException;
|
import hep.dataforge.exceptions.PortException;
|
||||||
import hep.dataforge.exceptions.StorageException;
|
import hep.dataforge.exceptions.StorageException;
|
||||||
import hep.dataforge.meta.Meta;
|
import hep.dataforge.meta.Meta;
|
||||||
import hep.dataforge.storage.api.PointLoader;
|
|
||||||
import hep.dataforge.storage.api.Storage;
|
import hep.dataforge.storage.api.Storage;
|
||||||
|
import hep.dataforge.storage.api.TableLoader;
|
||||||
import hep.dataforge.storage.commons.LoaderFactory;
|
import hep.dataforge.storage.commons.LoaderFactory;
|
||||||
import hep.dataforge.tables.TableFormat;
|
import hep.dataforge.tables.TableFormat;
|
||||||
import hep.dataforge.tables.TableFormatBuilder;
|
import hep.dataforge.tables.TableFormatBuilder;
|
||||||
@ -421,7 +421,7 @@ public class MspDevice extends Sensor<Values> implements PortHandler.PortControl
|
|||||||
this.meta = meta;
|
this.meta = meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PointLoader makeLoader(StorageConnection connection) {
|
private TableLoader makeLoader(StorageConnection connection) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Storage storage = connection.getStorage();
|
Storage storage = connection.getStorage();
|
||||||
|
@ -3,7 +3,7 @@ package inr.numass.control
|
|||||||
import hep.dataforge.control.connections.StorageConnection
|
import hep.dataforge.control.connections.StorageConnection
|
||||||
import hep.dataforge.control.devices.AbstractDevice
|
import hep.dataforge.control.devices.AbstractDevice
|
||||||
import hep.dataforge.exceptions.StorageException
|
import hep.dataforge.exceptions.StorageException
|
||||||
import hep.dataforge.storage.api.PointLoader
|
import hep.dataforge.storage.api.TableLoader
|
||||||
import hep.dataforge.values.Values
|
import hep.dataforge.values.Values
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.function.Function
|
import java.util.function.Function
|
||||||
@ -12,8 +12,8 @@ import java.util.function.Function
|
|||||||
* A helper to store points in multiple loaders
|
* A helper to store points in multiple loaders
|
||||||
* Created by darksnake on 16-May-17.
|
* Created by darksnake on 16-May-17.
|
||||||
*/
|
*/
|
||||||
class StorageHelper(private val device: AbstractDevice, private val loaderFactory: Function<StorageConnection, PointLoader>) : AutoCloseable {
|
class StorageHelper(private val device: AbstractDevice, private val loaderFactory: Function<StorageConnection, TableLoader>) : AutoCloseable {
|
||||||
private val loaderMap = HashMap<StorageConnection, PointLoader>()
|
private val loaderMap = HashMap<StorageConnection, TableLoader>()
|
||||||
|
|
||||||
fun push(point: Values) {
|
fun push(point: Values) {
|
||||||
if (!device.hasState("storing") || device.getState("storing").booleanValue()) {
|
if (!device.hasState("storing") || device.getState("storing").booleanValue()) {
|
||||||
|
@ -19,7 +19,7 @@ import hep.dataforge.control.measurements.Measurement;
|
|||||||
import hep.dataforge.description.ValueDef;
|
import hep.dataforge.description.ValueDef;
|
||||||
import hep.dataforge.exceptions.ControlException;
|
import hep.dataforge.exceptions.ControlException;
|
||||||
import hep.dataforge.meta.Meta;
|
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.storage.commons.LoaderFactory;
|
||||||
import hep.dataforge.tables.TableFormatBuilder;
|
import hep.dataforge.tables.TableFormatBuilder;
|
||||||
import hep.dataforge.tables.ValueMap;
|
import hep.dataforge.tables.ValueMap;
|
||||||
@ -113,7 +113,7 @@ public class VacCollectorDevice extends Sensor<Values> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PointLoader buildLoader(StorageConnection connection) {
|
private TableLoader buildLoader(StorageConnection connection) {
|
||||||
TableFormatBuilder format = new TableFormatBuilder().setType("timestamp", ValueType.TIME);
|
TableFormatBuilder format = new TableFormatBuilder().setType("timestamp", ValueType.TIME);
|
||||||
getSensors().forEach((s) -> {
|
getSensors().forEach((s) -> {
|
||||||
format.setType(s.getName(), ValueType.NUMBER);
|
format.setType(s.getName(), ValueType.NUMBER);
|
||||||
|
@ -26,7 +26,7 @@ ctx.pluginManager().load(PlotManager)
|
|||||||
ctx.pluginManager().load(NumassPlugin.class)
|
ctx.pluginManager().load(NumassPlugin.class)
|
||||||
|
|
||||||
new GrindShell(ctx).eval {
|
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);
|
NumassStorage storage = NumassStorageFactory.buildLocal(rootDir);
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ import hep.dataforge.server.ServerManager;
|
|||||||
import hep.dataforge.server.ServletUtils;
|
import hep.dataforge.server.ServletUtils;
|
||||||
import hep.dataforge.server.storage.StorageRatpackHandler;
|
import hep.dataforge.server.storage.StorageRatpackHandler;
|
||||||
import hep.dataforge.storage.api.ObjectLoader;
|
import hep.dataforge.storage.api.ObjectLoader;
|
||||||
import hep.dataforge.storage.api.PointLoader;
|
|
||||||
import hep.dataforge.storage.api.Storage;
|
import hep.dataforge.storage.api.Storage;
|
||||||
|
import hep.dataforge.storage.api.TableLoader;
|
||||||
import inr.numass.data.api.NumassSet;
|
import inr.numass.data.api.NumassSet;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import ratpack.handling.Context;
|
import ratpack.handling.Context;
|
||||||
@ -73,7 +73,7 @@ public class NumassStorageHandler extends StorageRatpackHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MetaBuilder pointLoaderPlotOptions(PointLoader loader) {
|
protected MetaBuilder pointLoaderPlotOptions(TableLoader loader) {
|
||||||
MetaBuilder builder = super.pointLoaderPlotOptions(loader);
|
MetaBuilder builder = super.pointLoaderPlotOptions(loader);
|
||||||
if (loader.getName().startsWith("msp")
|
if (loader.getName().startsWith("msp")
|
||||||
|| loader.getName().startsWith("vac")
|
|| loader.getName().startsWith("vac")
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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<Storage?>();
|
|
||||||
|
|
||||||
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<Item> {
|
|
||||||
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<Pair<String, String>>()
|
|
||||||
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<Item> {
|
|
||||||
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 "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<Int> = ChoiceBox(FXCollections.observableArrayList(1, 2, 5, 10, 20, 50))
|
|
||||||
private val detectorNormalizeSwitch: CheckBox = CheckBox("Normalize")
|
|
||||||
private val detectorDataExportButton: Button = Button("Export")
|
|
||||||
|
|
||||||
val dataProperty = SimpleObjectProperty<NumassSet>()
|
|
||||||
var data: NumassSet? by dataProperty
|
|
||||||
|
|
||||||
val analyzerProperty = SimpleObjectProperty<NumassAnalyzer>(SimpleAnalyzer())
|
|
||||||
var analyzer: NumassAnalyzer by analyzerProperty
|
|
||||||
|
|
||||||
private val spectra = HashMap<Double, Table>();//spectra cache
|
|
||||||
|
|
||||||
val spectrumData = DataPlot("spectrum")
|
|
||||||
val hvPlotData = PlotGroup("hv")
|
|
||||||
//private var points = FXCollections.observableArrayList<NumassPoint>()
|
|
||||||
|
|
||||||
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<out String>, _: String, _: String ->
|
|
||||||
if (data != null) {
|
|
||||||
updateSpectrum(data!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val rangeChangeListener = { _: ObservableValue<out Number>, _: 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -3,16 +3,21 @@ package inr.numass.viewer
|
|||||||
import hep.dataforge.kodex.configure
|
import hep.dataforge.kodex.configure
|
||||||
import hep.dataforge.kodex.fx.dfIcon
|
import hep.dataforge.kodex.fx.dfIcon
|
||||||
import hep.dataforge.kodex.fx.plots.PlotContainer
|
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.meta.Meta
|
||||||
import hep.dataforge.plots.Plot
|
import hep.dataforge.plots.PlotGroup
|
||||||
import hep.dataforge.plots.data.DataPlot
|
import hep.dataforge.plots.data.DataPlot
|
||||||
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
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.storage.api.ValueIndex
|
||||||
import hep.dataforge.tables.ListTable
|
import hep.dataforge.tables.ListTable
|
||||||
import hep.dataforge.tables.Table
|
import hep.dataforge.tables.Table
|
||||||
import hep.dataforge.tables.XYAdapter
|
import hep.dataforge.tables.XYAdapter
|
||||||
import hep.dataforge.values.Values
|
import hep.dataforge.values.Values
|
||||||
|
import javafx.collections.FXCollections
|
||||||
|
import javafx.collections.MapChangeListener
|
||||||
|
import javafx.collections.ObservableMap
|
||||||
import javafx.scene.image.ImageView
|
import javafx.scene.image.ImageView
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
@ -30,26 +35,39 @@ class SlowControlView : View(title = "Numass slow control view", icon = ImageVie
|
|||||||
center = PlotContainer(plot).root
|
center = PlotContainer(plot).root
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO add multiple loaders
|
val data: ObservableMap<String, TableLoader> = FXCollections.observableHashMap();
|
||||||
fun load(loader: PointLoader) {
|
val isEmpty = booleanBinding(data) { data.isEmpty() }
|
||||||
runAsync {
|
|
||||||
val data = getData(loader)
|
init {
|
||||||
ArrayList<Plot>().apply {
|
data.addListener { change: MapChangeListener.Change<out String, out TableLoader> ->
|
||||||
loader.format.columns.filter { it.name != "timestamp" }.forEach {
|
if (change.wasRemoved()) {
|
||||||
val adapter = XYAdapter("timestamp", it.name);
|
plot.remove(change.key)
|
||||||
this += DataPlot.plot(it.name, adapter, data).configure {
|
}
|
||||||
|
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
|
"showLine" to true
|
||||||
"showSymbol" to false
|
"showSymbol" to false
|
||||||
"showErrors" to false
|
"showErrors" to false
|
||||||
}
|
}
|
||||||
|
group.add(plot)
|
||||||
}
|
}
|
||||||
}
|
group
|
||||||
} ui {
|
} ui {
|
||||||
plot.setAll(it)
|
plot.add(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getData(loader: PointLoader, query: Meta = Meta.empty()): Table {
|
private fun getData(loader: TableLoader, query: Meta = Meta.empty()): Table {
|
||||||
val index: ValueIndex<Values> =
|
val index: ValueIndex<Values> =
|
||||||
if (query.hasValue("index")) {
|
if (query.hasValue("index")) {
|
||||||
//use custom index if needed
|
//use custom index if needed
|
||||||
@ -63,7 +81,14 @@ class SlowControlView : View(title = "Numass slow control view", icon = ImageVie
|
|||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw RuntimeException(e)
|
throw RuntimeException(e)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(id: String, loader: TableLoader) {
|
||||||
|
this.data.put(id, loader)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove(id: String) {
|
||||||
|
this.data.remove(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,10 @@ import hep.dataforge.fx.fragments.LogFragment
|
|||||||
import hep.dataforge.kodex.fx.dfIcon
|
import hep.dataforge.kodex.fx.dfIcon
|
||||||
import hep.dataforge.kodex.fx.runGoal
|
import hep.dataforge.kodex.fx.runGoal
|
||||||
import hep.dataforge.kodex.fx.ui
|
import hep.dataforge.kodex.fx.ui
|
||||||
|
import hep.dataforge.meta.Metoid
|
||||||
import hep.dataforge.storage.api.Loader
|
import hep.dataforge.storage.api.Loader
|
||||||
import hep.dataforge.storage.api.Storage
|
import hep.dataforge.storage.api.Storage
|
||||||
|
import hep.dataforge.storage.api.TableLoader
|
||||||
import hep.dataforge.storage.filestorage.FileStorageFactory
|
import hep.dataforge.storage.filestorage.FileStorageFactory
|
||||||
import inr.numass.NumassProperties
|
import inr.numass.NumassProperties
|
||||||
import inr.numass.data.api.NumassPoint
|
import inr.numass.data.api.NumassPoint
|
||||||
@ -71,6 +73,13 @@ class StorageView(private val context: Context = Global.instance()) : View(title
|
|||||||
hvView.remove(id)
|
hvView.remove(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is TableLoader -> {
|
||||||
|
if (selected) {
|
||||||
|
scView.add(id, content)
|
||||||
|
} else {
|
||||||
|
scView.remove(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,22 +141,39 @@ class StorageView(private val context: Context = Global.instance()) : View(title
|
|||||||
populate { parent ->
|
populate { parent ->
|
||||||
val value = parent.value.content
|
val value = parent.value.content
|
||||||
when (value) {
|
when (value) {
|
||||||
is Storage -> (value.shelves() + value.loaders()).map { buildContainer(it, parent.value) }
|
is Storage -> (value.shelves().sorted() + value.loaders().sorted()).map { buildContainer(it, parent.value) }
|
||||||
is NumassSet -> value.points.map { buildContainer(it, parent.value) }.toList()
|
is NumassSet -> value.points.map { buildContainer(it, parent.value) }.toList().sortedBy { it.id }
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cellFormat { value ->
|
cellFormat { value ->
|
||||||
contextMenu = null
|
|
||||||
when (value.content) {
|
when (value.content) {
|
||||||
is Storage -> text = value.id
|
is Storage -> {
|
||||||
|
text = value.id
|
||||||
|
graphic = null
|
||||||
|
}
|
||||||
is NumassSet -> {
|
is NumassSet -> {
|
||||||
text = null
|
text = null
|
||||||
graphic = checkbox(value.id, value.checkedProperty)
|
graphic = checkbox(value.id, value.checkedProperty)
|
||||||
|
}
|
||||||
|
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 {
|
contextMenu = ContextMenu().apply {
|
||||||
item("Info") {
|
item("Meta") {
|
||||||
action {
|
action {
|
||||||
openInternalBuilderWindow(title = "Info: ${value.id}", escapeClosesWindow = true) {
|
openInternalBuilderWindow(title = "Info: ${value.id}", escapeClosesWindow = true) {
|
||||||
scrollpane {
|
scrollpane {
|
||||||
@ -161,14 +187,8 @@ class StorageView(private val context: Context = Global.instance()) : View(title
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
is NumassPoint -> {
|
contextMenu = null
|
||||||
text = null
|
|
||||||
graphic = checkbox(value.id, value.checkedProperty)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
text = (value as Loader).name
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,6 +209,11 @@ class StorageView(private val context: Context = Global.instance()) : View(title
|
|||||||
isClosable = false
|
isClosable = false
|
||||||
//visibleWhen(spectrumView.isEmpty.not())
|
//visibleWhen(spectrumView.isEmpty.not())
|
||||||
}
|
}
|
||||||
|
tab("Slow control") {
|
||||||
|
content = scView.root
|
||||||
|
isClosable = false
|
||||||
|
//visibleWhen(scView.isEmpty.not())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setDividerPosition(0, 0.3);
|
setDividerPosition(0, 0.3);
|
||||||
}
|
}
|
||||||
|
@ -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<NumassLoaderView>();
|
|
||||||
view.data = storage.provide("Fill_1/set_4", NumassSet::class.java).get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
Application.launch(NumassTest::class.java)
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user