From 48c7c27af4338644c7d78ca650e27440c99a5b7f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 29 Nov 2021 15:57:20 +0300 Subject: [PATCH] Fix watcher view --- .../io/envelopes/DefaultEnvelopeReader.kt | 2 +- .../main/kotlin/hep/dataforge/names/Name.kt | 2 +- .../kotlin/inr/numass/viewer/AmplitudeView.kt | 4 +- .../inr/numass/viewer/DataController.kt | 60 +++++++++---------- .../inr/numass/viewer/DirectoryWatchView.kt | 49 +++++++++++---- .../main/kotlin/inr/numass/viewer/HVView.kt | 9 ++- .../main/kotlin/inr/numass/viewer/MainView.kt | 5 +- .../inr/numass/viewer/SlowControlView.kt | 8 +-- .../kotlin/inr/numass/viewer/SpectrumView.kt | 8 +-- .../kotlin/inr/numass/viewer/StorageView.kt | 40 +++++++------ .../main/kotlin/inr/numass/viewer/TimeView.kt | 13 +--- 11 files changed, 105 insertions(+), 95 deletions(-) diff --git a/dataforge-core/src/main/kotlin/hep/dataforge/io/envelopes/DefaultEnvelopeReader.kt b/dataforge-core/src/main/kotlin/hep/dataforge/io/envelopes/DefaultEnvelopeReader.kt index 966e6f3..da46c77 100644 --- a/dataforge-core/src/main/kotlin/hep/dataforge/io/envelopes/DefaultEnvelopeReader.kt +++ b/dataforge-core/src/main/kotlin/hep/dataforge/io/envelopes/DefaultEnvelopeReader.kt @@ -88,7 +88,7 @@ open class DefaultEnvelopeReader : EnvelopeReader { val dataLength = tag.dataSize if (metaLength < 0 || dataLength < 0) { LoggerFactory.getLogger(javaClass).error("Can't lazy read infinite data or meta. Returning non-lazy envelope") - return read(file) + return read(Files.newInputStream(file)) } val metaBuffer = ByteBuffer.allocate(metaLength) diff --git a/dataforge-core/src/main/kotlin/hep/dataforge/names/Name.kt b/dataforge-core/src/main/kotlin/hep/dataforge/names/Name.kt index d2a6aa7..8658b8d 100644 --- a/dataforge-core/src/main/kotlin/hep/dataforge/names/Name.kt +++ b/dataforge-core/src/main/kotlin/hep/dataforge/names/Name.kt @@ -215,7 +215,7 @@ interface Name : Comparable { return of(segments[0]) } - return of(Stream.of(*segments).filter { it -> !it.isEmpty() }.map{ of(it) }.toList()) + return of(Stream.of(*segments).filter { it -> it.isNotEmpty() }.map { of(it) }.toList()) } fun joinString(vararg segments: String): String { diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/AmplitudeView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/AmplitudeView.kt index 5dff93d..5fa0391 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/AmplitudeView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/AmplitudeView.kt @@ -82,7 +82,7 @@ class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = Imag init { data.addListener(MapChangeListener { change -> - val key = change.key + val key = change.key.toString() if (change.wasAdded()) { replotOne(key, change.valueAdded) } else if (change.wasRemoved()) { @@ -153,7 +153,7 @@ class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = Imag plotJobs.clear() data.forEach { (key, point) -> - replotOne(key, point) + replotOne(key.toString(), point) } } diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/DataController.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/DataController.kt index 9440566..91ab7c9 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/DataController.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/DataController.kt @@ -2,6 +2,7 @@ package inr.numass.viewer import hep.dataforge.context.ContextAware import hep.dataforge.meta.Meta +import hep.dataforge.names.Name import hep.dataforge.storage.tables.TableLoader import hep.dataforge.tables.Adapters import hep.dataforge.tables.ListTable @@ -20,13 +21,11 @@ import javafx.collections.ObservableList import javafx.collections.ObservableMap import kotlinx.coroutines.* import tornadofx.* -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.StandardWatchEventKinds -import java.nio.file.WatchKey +import java.nio.file.* import java.nio.file.attribute.BasicFileAttributes import kotlin.math.floor + class DataController : Controller(), ContextAware { override val context get() = app.context @@ -45,11 +44,11 @@ class DataController : Controller(), ContextAware { point.channels.mapValues { (_, value) -> analyzer.getAmplitudeSpectrum(value) } } - val spectrum: Deferred = context.async{ + val spectrum: Deferred
= context.async { analyzer.getAmplitudeSpectrum(point) } - val timeSpectrum: Deferred
= context.async{ + val timeSpectrum: Deferred
= context.async { val cr = spectrum.await().sumOf { it.getValue(NumassAnalyzer.COUNT_KEY).int }.toDouble() / point.length.toMillis() * 1000 @@ -76,19 +75,19 @@ class DataController : Controller(), ContextAware { } } - private val cache = Misc.getLRUCache(400) + private val cache = Misc.getLRUCache(400) - fun getCachedPoint(id: String, point: NumassPoint): CachedPoint = cache.getOrPut(id) { CachedPoint(point) } + fun getCachedPoint(id: Name, point: NumassPoint): CachedPoint = cache.getOrPut(id) { CachedPoint(point) } - fun getSpectrumAsync(id: String, point: NumassPoint): Deferred
= + fun getSpectrumAsync(id: Name, point: NumassPoint): Deferred
= getCachedPoint(id, point).spectrum - suspend fun getChannelSpectra(id: String, point: NumassPoint): Map = + suspend fun getChannelSpectra(id: Name, point: NumassPoint): Map = getCachedPoint(id, point).channelSpectra.await() - val sets: ObservableMap = FXCollections.observableHashMap() - val points: ObservableMap = FXCollections.observableHashMap() - val sc: ObservableMap = FXCollections.observableHashMap() + val sets: ObservableMap = FXCollections.observableHashMap() + val points: ObservableMap = FXCollections.observableHashMap() + val sc: ObservableMap = FXCollections.observableHashMap() val files: ObservableList = FXCollections.observableArrayList() @@ -102,7 +101,8 @@ class DataController : Controller(), ContextAware { if (watchPath != null) { Files.list(watchPath).toList() .filter { - !Files.isDirectory(it) && it.fileName.toString().startsWith(NumassDataLoader.POINT_FRAGMENT_NAME) + !Files.isDirectory(it) && it.fileName.toString() + .startsWith(NumassDataLoader.POINT_FRAGMENT_NAME) } .sortedBy { file -> val attr = Files.readAttributes(file, BasicFileAttributes::class.java) @@ -117,26 +117,20 @@ class DataController : Controller(), ContextAware { } } val watcher = watchPath.fileSystem.newWatchService() - watchJob = app.context.launch { + watchJob = app.context.launch(Dispatchers.IO) { watcher.use { watcher -> - val key: WatchKey = watchPath.register(watcher, - StandardWatchEventKinds.ENTRY_CREATE) - coroutineContext[Job]?.invokeOnCompletion { - key.cancel() - } + watchPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE) while (isActive) { - try { - key.pollEvents().forEach { event -> - if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) { - val path: Path = event.context() as Path - runLater { - files.add(watchPath.resolve(path)) - } + val key: WatchKey = watcher.take() + for (event: WatchEvent<*> in key.pollEvents()) { + if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) { + val path: Path = event.context() as Path + runLater { + files.add(watchPath.resolve(path)) } } - } catch (x: Throwable) { - app.context.logger.error("Error during dynamic point read", x) } + key.reset() } } } @@ -153,21 +147,21 @@ class DataController : Controller(), ContextAware { } - fun addPoint(id: String, point: NumassPoint): CachedPoint { + fun addPoint(id: Name, point: NumassPoint): CachedPoint { val newPoint = getCachedPoint(id, point) points[id] = newPoint return newPoint } - fun addSet(id: String, set: NumassSet) { + fun addSet(id: Name, set: NumassSet) { sets[id] = set } - fun addSc(id: String, set: TableLoader) { + fun addSc(id: Name, set: TableLoader) { sc[id] = set } - fun remove(id: String) { + fun remove(id: Name) { points.remove(id) sets.remove(id) sc.remove(id) diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/DirectoryWatchView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/DirectoryWatchView.kt index 4b955ae..29372f1 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/DirectoryWatchView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/DirectoryWatchView.kt @@ -1,12 +1,15 @@ package inr.numass.viewer +import hep.dataforge.asName import hep.dataforge.fx.dfIconView import hep.dataforge.io.envelopes.Envelope +import hep.dataforge.names.AlphanumComparator +import hep.dataforge.names.Name import inr.numass.data.NumassDataUtils import inr.numass.data.NumassEnvelopeType import inr.numass.data.api.NumassPoint import inr.numass.data.storage.NumassDataLoader -import javafx.scene.control.ContextMenu +import kotlinx.coroutines.launch import tornadofx.* import java.nio.file.Path @@ -28,24 +31,46 @@ class DirectoryWatchView : View(title = "Numass storage", icon = dfIconView) { return NumassDataUtils.read(envelope) } + //private class PointContainer(val path: Path, val checkedProperty: BooleanProperty = SimpleBooleanProperty()) + override val root = splitpane { - listview(dataController.files) { - //multiSelect(true) + listview(dataController.files.sorted { l, r -> AlphanumComparator.compare(l.toString(), r.toString()) }) { cellFormat { path: Path -> - text = path.fileName.toString() - graphic = null if (path.fileName.toString().startsWith(NumassDataLoader.POINT_FRAGMENT_NAME)) { - val point = readPointFile(path) - val cachedPoint = dataController.addPoint(path.toString(), point) - //val point = dataController.getCachedPoint(value.toString()) - contextMenu = ContextMenu().apply { - item("Info") { - action { - PointInfoView(cachedPoint).openModal(escapeClosesWindow = true) + val name = Name.of(path.map { it.toString().asName() }) + text = null + graphic = checkbox(path.fileName.toString()).apply { + isSelected = false + selectedProperty().onChange { + if (it) { + app.context.launch { + dataController.addPoint(name, readPointFile(path)) + } + } else { + dataController.remove(name) } } } + +// app.context.launch { +// val point = readPointFile(path) +// val cachedPoint = dataController.addPoint(path.toString().asName(), point) +// +// //val point = dataController.getCachedPoint(value.toString()) +// withContext(Dispatchers.JavaFx) { +// contextMenu = ContextMenu().apply { +// item("Info") { +// action { +// PointInfoView(cachedPoint).openModal(escapeClosesWindow = true) +// } +// } +// } +// } +// } + } else { + text = path.fileName.toString() + graphic = null contextMenu = null } } diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/HVView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/HVView.kt index 811f45e..e78cca6 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/HVView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/HVView.kt @@ -13,7 +13,6 @@ import hep.dataforge.tables.Adapters import inr.numass.data.api.NumassSet import javafx.collections.MapChangeListener import javafx.scene.image.ImageView -import kotlinx.coroutines.Dispatchers import tornadofx.* @@ -48,10 +47,10 @@ class HVView : View(title = "High voltage time plot", icon = ImageView(dfIcon)) val isEmpty = booleanBinding(data) { data.isEmpty() } init { - data.addListener { change: MapChangeListener.Change -> + data.addListener { change: MapChangeListener.Change -> isEmpty.invalidate() if (change.wasRemoved()) { - frame.plots.remove(Name.ofSingle(change.key)) + frame.plots.remove(change.key) } if (change.wasAdded()) { runLater { container.progress = -1.0 } @@ -59,8 +58,8 @@ class HVView : View(title = "High voltage time plot", icon = ImageView(dfIcon)) change.valueAdded.getHvData() } ui { table -> if (table != null) { - ((frame[change.key] as? DataPlot) - ?: DataPlot(change.key, adapter = Adapters.buildXYAdapter("timestamp", "value")).also { frame.add(it) }) + ((frame[change.key.toString()] as? DataPlot) + ?: DataPlot(change.key.toString(), adapter = Adapters.buildXYAdapter("timestamp", "value")).also { frame.add(it) }) .fillData(table) } diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/MainView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/MainView.kt index 93de7b6..ebc728a 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/MainView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/MainView.kt @@ -1,5 +1,6 @@ package inr.numass.viewer +import hep.dataforge.asName import hep.dataforge.fx.dfIconView import hep.dataforge.fx.except import hep.dataforge.fx.runGoal @@ -67,7 +68,7 @@ class MainView : View(title = "Numass viewer", icon = dfIconView) { NumassDataLoader(app.context, null, path.fileName.toString(), path) } ui { loader: NumassDataLoader -> contentView = spectrumView - dataController.addSet(loader.name, loader) + dataController.addSet(loader.name.asName(), loader) } except { alert( @@ -116,7 +117,7 @@ class MainView : View(title = "Numass viewer", icon = dfIconView) { val point = NumassDataUtils.read(it) runLater { contentView = amplitudeView - dataController.addPoint(path.fileName.toString(), point) + dataController.addPoint(path.fileName.toString().asName(), point) } } } 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 d6d8d9d..0b97b1a 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/SlowControlView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/SlowControlView.kt @@ -5,6 +5,7 @@ import hep.dataforge.fx.dfIcon import hep.dataforge.fx.plots.PlotContainer import hep.dataforge.fx.runGoal import hep.dataforge.fx.ui +import hep.dataforge.names.Name import hep.dataforge.plots.PlotGroup import hep.dataforge.plots.data.DataPlot import hep.dataforge.plots.jfreechart.JFreeChartFrame @@ -13,7 +14,6 @@ import hep.dataforge.storage.tables.asTable import hep.dataforge.tables.Adapters import javafx.collections.MapChangeListener import javafx.scene.image.ImageView -import kotlinx.coroutines.Dispatchers import tornadofx.* /** @@ -38,16 +38,16 @@ class SlowControlView : View(title = "Numass slow control view", icon = ImageVie } init { - data.addListener { change: MapChangeListener.Change -> + data.addListener { change: MapChangeListener.Change -> if (change.wasRemoved()) { - plot.remove(change.key) + plot.remove(change.key.toString()) } if (change.wasAdded()) { runGoal(app.context,"loadTable[${change.key}]") { val plotData = change.valueAdded.asTable().await() val names = plotData.format.namesAsArray().filter { it != "timestamp" } - val group = PlotGroup(change.key) + val group = PlotGroup(change.key.toString()) names.forEach { val adapter = Adapters.buildXYAdapter("timestamp", it); diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/SpectrumView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/SpectrumView.kt index 23e18dd..fcd866b 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/SpectrumView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/SpectrumView.kt @@ -99,9 +99,9 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco } init { - data.addListener { change: MapChangeListener.Change -> + data.addListener { change: MapChangeListener.Change -> if (change.wasRemoved()) { - frame.plots.remove(Name.ofSingle(change.key)) + frame.plots.remove(Name.ofSingle(change.key.toString())) } if (change.wasAdded()) { @@ -118,11 +118,11 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco data.forEach { (name, set) -> val plot: DataPlot = - frame.plots[Name.ofSingle(name)] as DataPlot? ?: DataPlot(name).apply { frame.add(this) } + frame.plots[name] as DataPlot? ?: DataPlot(name.toString()).apply { frame.add(this) } app.context.launch { val points = set.points.map { - dataController.getCachedPoint("$name/${it.voltage}[${it.index}]", it) + dataController.getCachedPoint(Name.join("$name","${it.voltage}[${it.index}]"), it) }.map { cachedPoint -> val count = cachedPoint.spectrum.await().countInWindow(loChannel.toShort(), upChannel.toShort()) val seconds = cachedPoint.length.toMillis() / 1000.0 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 c083915..d8b663b 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt @@ -1,10 +1,12 @@ package inr.numass.viewer +import hep.dataforge.asName import hep.dataforge.fx.dfIconView import hep.dataforge.fx.meta.MetaViewer import hep.dataforge.meta.Meta import hep.dataforge.meta.Metoid import hep.dataforge.names.AlphanumComparator +import hep.dataforge.names.Name import hep.dataforge.storage.Storage import hep.dataforge.storage.files.FileTableLoader import hep.dataforge.storage.tables.TableLoader @@ -35,15 +37,15 @@ class StorageView : View(title = "Numass storage", icon = dfIconView) { private val hvView: HVView by inject() private val scView: SlowControlView by inject() - private inner class Container(val id: String, val content: Any) { + private inner class Container(val name: Name, val content: Any) { val checkedProperty = SimpleBooleanProperty(false) var checked by checkedProperty val infoView: UIComponent by lazy { when (content) { - is NumassPoint -> PointInfoView(dataController.getCachedPoint(id, content)) - is Metoid -> MetaViewer(content.meta, title = "Meta view: $id") - else -> MetaViewer(Meta.empty(), title = "Meta view: $id") + is NumassPoint -> PointInfoView(dataController.getCachedPoint(name, content)) + is Metoid -> MetaViewer(content.meta, title = "Meta view: $name") + else -> MetaViewer(Meta.empty(), title = "Meta view: $name") } } @@ -54,23 +56,23 @@ class StorageView : View(title = "Numass storage", icon = dfIconView) { when (content) { is NumassPoint -> { if (selected) { - dataController.addPoint(id, content) + dataController.addPoint(name, content) } else { - dataController.remove(id) + dataController.remove(name) } } is NumassSet -> { if (selected) { - dataController.addSet(id, content) + dataController.addSet(name, content) } else { - dataController.remove(id) + dataController.remove(name) } } is TableLoader -> { if (selected) { - dataController.addSc(id, content) + dataController.addSc(name, content) } else { - dataController.remove(id) + dataController.remove(name) } } } @@ -95,7 +97,7 @@ class StorageView : View(title = "Numass storage", icon = dfIconView) { } else { buildContainer(it, this) } - }.sortedWith(Comparator.comparing({ it.id }, AlphanumComparator)).asObservable() + }.sortedWith(Comparator.comparing({ it.name.toString() }, AlphanumComparator)).asObservable() is NumassSet -> content.points .sortedBy { it.index } .map { buildContainer(it, this) } @@ -117,7 +119,7 @@ class StorageView : View(title = "Numass storage", icon = dfIconView) { storageProperty.onChange { storage -> dataController.clear() if (storage == null) return@onChange - root = TreeItem(Container(storage.name, storage)) + root = TreeItem(Container(storage.name.asName(), storage)) root.isExpanded = true lazyPopulate(leafCheck = { !it.value.hasChildren @@ -152,7 +154,7 @@ class StorageView : View(title = "Numass storage", icon = dfIconView) { } } else -> { - text = value.id + text = value.name.toString() graphic = null } } @@ -210,19 +212,19 @@ class StorageView : View(title = "Numass storage", icon = dfIconView) { private fun buildContainer(content: Any, parent: Container): Container = when (content) { - is Storage -> Container(content.fullName.toString(), content) + is Storage -> Container(content.fullName, content) is NumassSet -> { - val id: String = if (content is NumassDataLoader) { - content.fullName.unescaped + val id: Name = if (content is NumassDataLoader) { + content.fullName } else { - content.name + content.name.asName() } Container(id, content) } is NumassPoint -> { - Container("${parent.id}/${content.voltage}[${content.index}]", content) + Container("${parent.name}/${content.voltage}[${content.index}]".asName(), content) } - is FileTableLoader -> Container(content.path.toString(), content) + is FileTableLoader -> Container(Name.of(content.path.map { it.toString().asName() }), content) else -> throw IllegalArgumentException("Unknown content type: ${content::class.java}"); } } diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/TimeView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/TimeView.kt index b6de027..e4a2799 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/TimeView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/TimeView.kt @@ -64,7 +64,7 @@ class TimeView : View(title = "Numass time spectrum plot", icon = ImageView(dfIc init { data.addListener(MapChangeListener { change -> - val key = change.key + val key = change.key.toString() if (change.wasAdded()) { replotOne(key, change.valueAdded) } else if(change.wasRemoved()){ @@ -105,16 +105,5 @@ class TimeView : View(title = "Numass time spectrum plot", icon = ImageView(dfIc } } - - private fun replot() { - frame.plots.clear() - plotJobs.forEach { (_, job) -> job.cancel() } - plotJobs.clear() - - data.forEach { (key, point) -> - replotOne(key, point) - } - } - }