Fix watcher view

This commit is contained in:
Alexander Nozik 2021-11-29 15:57:20 +03:00
parent 307d4cb18a
commit 48c7c27af4
11 changed files with 105 additions and 95 deletions

View File

@ -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)

View File

@ -215,7 +215,7 @@ interface Name : Comparable<Name> {
return of(segments[0])
}
return of(Stream.of(*segments).filter { it -> !it.isEmpty() }.map<Name>{ of(it) }.toList())
return of(Stream.of(*segments).filter { it -> it.isNotEmpty() }.map { of(it) }.toList())
}
fun joinString(vararg segments: String): String {

View File

@ -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)
}
}

View File

@ -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<Table> = context.async{
val spectrum: Deferred<Table> = context.async {
analyzer.getAmplitudeSpectrum(point)
}
val timeSpectrum: Deferred<Table> = context.async{
val timeSpectrum: Deferred<Table> = 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<String, CachedPoint>(400)
private val cache = Misc.getLRUCache<Name, CachedPoint>(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<Table> =
fun getSpectrumAsync(id: Name, point: NumassPoint): Deferred<Table> =
getCachedPoint(id, point).spectrum
suspend fun getChannelSpectra(id: String, point: NumassPoint): Map<Int, Table> =
suspend fun getChannelSpectra(id: Name, point: NumassPoint): Map<Int, Table> =
getCachedPoint(id, point).channelSpectra.await()
val sets: ObservableMap<String, NumassSet> = FXCollections.observableHashMap()
val points: ObservableMap<String, CachedPoint> = FXCollections.observableHashMap()
val sc: ObservableMap<String, TableLoader> = FXCollections.observableHashMap()
val sets: ObservableMap<Name, NumassSet> = FXCollections.observableHashMap()
val points: ObservableMap<Name, CachedPoint> = FXCollections.observableHashMap()
val sc: ObservableMap<Name, TableLoader> = FXCollections.observableHashMap()
val files: ObservableList<Path> = 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)

View File

@ -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
}
}

View File

@ -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<out String, out NumassSet> ->
data.addListener { change: MapChangeListener.Change<out Name, out NumassSet> ->
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)
}

View File

@ -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)
}
}
}

View File

@ -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<out String, out TableLoader> ->
data.addListener { change: MapChangeListener.Change<out Name, out TableLoader> ->
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);

View File

@ -99,9 +99,9 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco
}
init {
data.addListener { change: MapChangeListener.Change<out String, out NumassSet> ->
data.addListener { change: MapChangeListener.Change<out Name, out NumassSet> ->
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

View File

@ -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}");
}
}

View File

@ -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)
}
}
}