From 42a69d1334301d06e9302de843990f22336898c1 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 24 Apr 2018 15:20:50 +0300 Subject: [PATCH] Update numass viewer point caching. --- build.gradle | 2 +- .../kotlin/inr/numass/data/NumassDataUtils.kt | 12 +++-- .../numass/data/analyzers/NumassAnalyzer.kt | 4 +- .../kotlin/inr/numass/data/api/NumassPoint.kt | 35 ++++++++++++- .../kotlin/inr/numass/data/api/NumassSet.kt | 21 +++----- .../inr/numass/data/legacy/NumassDatFile.kt | 10 ++-- .../numass/data/storage/NumassDataLoader.kt | 31 ++++++----- .../numass/data/storage/ProtoNumassPoint.kt | 29 ++++++----- .../main/proto/inr/numas/numass-proto.proto | 11 ++-- .../kotlin/inr/numass/viewer/AmplitudeView.kt | 34 +++---------- .../main/kotlin/inr/numass/viewer/Cache.kt | 51 +++++++++++++++++++ .../main/kotlin/inr/numass/viewer/HVView.kt | 4 +- .../main/kotlin/inr/numass/viewer/MainView.kt | 6 +-- .../inr/numass/viewer/NumassDataCache.kt | 26 ---------- .../kotlin/inr/numass/viewer/PointInfoView.kt | 8 +-- .../kotlin/inr/numass/viewer/SpectrumView.kt | 15 +++--- .../kotlin/inr/numass/viewer/StorageView.kt | 17 +++---- .../main/kotlin/inr/numass/viewer/Viewer.kt | 19 +------ .../inr/numass/viewer/test/ComponentTest.kt | 9 ++-- 19 files changed, 188 insertions(+), 156 deletions(-) create mode 100644 numass-viewer/src/main/kotlin/inr/numass/viewer/Cache.kt delete mode 100644 numass-viewer/src/main/kotlin/inr/numass/viewer/NumassDataCache.kt diff --git a/build.gradle b/build.gradle index c8728c37..c0b6eea4 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ allprojects { repositories { jcenter() mavenCentral() - maven { url = "https://jitpack.io" } + //maven { url = "https://jitpack.io" } maven { url = "http://dl.bintray.com/kotlin/ktor" } maven { url = "https://dl.bintray.com/kotlin/kotlinx" } } diff --git a/numass-core/src/main/kotlin/inr/numass/data/NumassDataUtils.kt b/numass-core/src/main/kotlin/inr/numass/data/NumassDataUtils.kt index 066ef189..2ffbc2cf 100644 --- a/numass-core/src/main/kotlin/inr/numass/data/NumassDataUtils.kt +++ b/numass-core/src/main/kotlin/inr/numass/data/NumassDataUtils.kt @@ -3,15 +3,17 @@ package inr.numass.data import hep.dataforge.io.envelopes.Envelope import hep.dataforge.meta.Meta import hep.dataforge.meta.MetaBuilder +import hep.dataforge.tables.Table import inr.numass.data.api.* import inr.numass.data.storage.ProtoBlock +import kotlinx.coroutines.experimental.Deferred import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.InputStream import java.util.stream.Collectors -import java.util.stream.Stream import java.util.zip.Inflater import kotlin.streams.asSequence +import kotlin.streams.toList /** @@ -20,10 +22,14 @@ import kotlin.streams.asSequence object NumassDataUtils { fun join(setName: String, sets: Collection): NumassSet { return object : NumassSet { - override val points: Stream by lazy { - val points = sets.stream().flatMap { it.points } + override val hvData: Deferred + get() = TODO("Join hv tables") + + override val points: List by lazy { + val points = sets.stream().flatMap { it.points.stream() } .collect(Collectors.groupingBy { it.voltage }) points.entries.stream().map { entry -> SimpleNumassPoint(entry.value, entry.key) } + .toList() } override val meta: Meta by lazy { diff --git a/numass-core/src/main/kotlin/inr/numass/data/analyzers/NumassAnalyzer.kt b/numass-core/src/main/kotlin/inr/numass/data/analyzers/NumassAnalyzer.kt index 7ee48558..2f8308be 100644 --- a/numass-core/src/main/kotlin/inr/numass/data/analyzers/NumassAnalyzer.kt +++ b/numass-core/src/main/kotlin/inr/numass/data/analyzers/NumassAnalyzer.kt @@ -95,11 +95,11 @@ interface NumassAnalyzer { * @param config * @return */ - fun getLength(block: NumassBlock, config: Meta): Long { + fun getLength(block: NumassBlock, config: Meta = Meta.empty()): Long { return analyze(block, config).getValue(LENGTH_KEY).getNumber().toLong() } - fun getAmplitudeSpectrum(block: NumassBlock, config: Meta): Table { + fun getAmplitudeSpectrum(block: NumassBlock, config: Meta = Meta.empty()): Table { val seconds = block.length.toMillis().toDouble() / 1000.0 return getAmplitudeSpectrum(getEvents(block, config).asSequence(), seconds, config) } diff --git a/numass-core/src/main/kotlin/inr/numass/data/api/NumassPoint.kt b/numass-core/src/main/kotlin/inr/numass/data/api/NumassPoint.kt index 1426f042..403e03e9 100644 --- a/numass-core/src/main/kotlin/inr/numass/data/api/NumassPoint.kt +++ b/numass-core/src/main/kotlin/inr/numass/data/api/NumassPoint.kt @@ -2,6 +2,8 @@ package inr.numass.data.api import hep.dataforge.io.envelopes.Envelope import hep.dataforge.meta.Metoid +import hep.dataforge.providers.Provider +import hep.dataforge.providers.Provides import inr.numass.data.channel import inr.numass.data.storage.ClassicNumassPoint import inr.numass.data.storage.ProtoNumassPoint @@ -12,11 +14,40 @@ import java.util.stream.Stream /** * Created by darksnake on 06-Jul-17. */ -interface NumassPoint : Metoid, NumassBlock { +interface NumassPoint : Metoid, NumassBlock, Provider { val blocks: List + /** + * Provides block with given number (starting with 0) + */ + @Provides(NUMASS_BLOCK_TARGET) + operator fun get(index: Int): NumassBlock? { + return blocks[index] + } + + /** + * Provides all blocks in given channel + */ + @Provides(NUMASS_CHANNEL_TARGET) + fun channel(index: Int): NumassBlock? { + return channels[index] + } + + /** + * Distinct map of channel number to corresponding grouping block + */ + val channels: Map + get() = blocks.toList().groupBy { it.channel }.mapValues { entry -> + if (entry.value.size == 1) { + entry.value.first() + } else { + MetaBlock(entry.value) + } + } + + /** * Get the voltage setting for the point * @@ -77,6 +108,8 @@ interface NumassPoint : Metoid, NumassBlock { get() = blocks.stream().flatMap { it.frames } companion object { + const val NUMASS_BLOCK_TARGET = "block" + const val NUMASS_CHANNEL_TARGET = "channel" const val START_TIME_KEY = "start" const val LENGTH_KEY = "length" diff --git a/numass-core/src/main/kotlin/inr/numass/data/api/NumassSet.kt b/numass-core/src/main/kotlin/inr/numass/data/api/NumassSet.kt index 33155ba9..c26c9669 100644 --- a/numass-core/src/main/kotlin/inr/numass/data/api/NumassSet.kt +++ b/numass-core/src/main/kotlin/inr/numass/data/api/NumassSet.kt @@ -6,15 +6,15 @@ package inr.numass.data.api import hep.dataforge.Named -import hep.dataforge.kodex.toList +import hep.dataforge.kodex.optional import hep.dataforge.meta.Metoid import hep.dataforge.providers.Provider import hep.dataforge.providers.Provides import hep.dataforge.providers.ProvidesNames import hep.dataforge.tables.Table +import kotlinx.coroutines.experimental.Deferred import java.time.Instant import java.util.* -import java.util.stream.Stream /** * A single set of numass points previously called file. @@ -23,7 +23,7 @@ import java.util.stream.Stream */ interface NumassSet : Named, Metoid, Iterable, Provider { - val points: Stream + val points: List /** * Get the first point if it exists. Throw runtime exception otherwise. @@ -31,7 +31,7 @@ interface NumassSet : Named, Metoid, Iterable, Provider { * @return */ val firstPoint: NumassPoint - get() = points.findFirst().orElseThrow { RuntimeException("The set is empty") } + get() = points.firstOrNull() ?: throw RuntimeException("The set is empty") /** * Get the starting time from meta or from first point @@ -39,14 +39,9 @@ interface NumassSet : Named, Metoid, Iterable, Provider { * @return */ val startTime: Instant - get() = meta.optValue(NumassPoint.START_TIME_KEY).map{ it.getTime() }.orElseGet { firstPoint.startTime } + get() = meta.optValue(NumassPoint.START_TIME_KEY).map { it.time }.orElseGet { firstPoint.startTime } - val hvData: Optional - get() = Optional.empty() - - // default String getDescription() { - // return getMeta().getString(DESCRIPTION_KEY, ""); - // } + val hvData: Deferred override fun iterator(): Iterator { return points.iterator() @@ -59,7 +54,7 @@ interface NumassSet : Named, Metoid, Iterable, Provider { * @return */ fun optPoint(voltage: Double): Optional { - return points.filter { it -> it.voltage == voltage }.findFirst() + return points.firstOrNull { it -> it.voltage == voltage }.optional } /** @@ -82,7 +77,7 @@ interface NumassSet : Named, Metoid, Iterable, Provider { } @ProvidesNames(NUMASS_POINT_PROVIDER_KEY) - fun listPoints(): Stream { + fun listPoints(): List { return points.map { it -> java.lang.Double.toString(it.voltage) } } diff --git a/numass-core/src/main/kotlin/inr/numass/data/legacy/NumassDatFile.kt b/numass-core/src/main/kotlin/inr/numass/data/legacy/NumassDatFile.kt index 6f59b9cc..94dd469a 100644 --- a/numass-core/src/main/kotlin/inr/numass/data/legacy/NumassDatFile.kt +++ b/numass-core/src/main/kotlin/inr/numass/data/legacy/NumassDatFile.kt @@ -2,8 +2,11 @@ package inr.numass.data.legacy import hep.dataforge.meta.Meta import hep.dataforge.meta.MetaBuilder +import hep.dataforge.tables.Table import inr.numass.data.api.* import inr.numass.data.api.NumassPoint.Companion.HV_KEY +import kotlinx.coroutines.experimental.CompletableDeferred +import kotlinx.coroutines.experimental.Deferred import org.apache.commons.io.FilenameUtils import java.io.IOException import java.nio.ByteBuffer @@ -17,20 +20,21 @@ import java.time.LocalDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter import java.util.* -import java.util.stream.Stream /** * Created by darksnake on 08.07.2017. */ class NumassDatFile @Throws(IOException::class) constructor(override val name: String, private val path: Path, meta: Meta) : NumassSet { + override val hvData: Deferred = CompletableDeferred(null) + override val meta: Meta private val hVdev: Double get() = meta.getDouble("dat.hvDev", 2.468555393226049) //TODO check point start - override val points: Stream + override val points: List get() = try { Files.newByteChannel(path, READ).use { channel -> var lab: Int @@ -39,7 +43,7 @@ constructor(override val name: String, private val path: Path, meta: Meta) : Num points.add(readPoint(channel)) lab = readBlock(channel, 1).get().toInt() } while (lab != 0xff) - return points.stream() + return points } } catch (ex: IOException) { throw RuntimeException(ex) diff --git a/numass-core/src/main/kotlin/inr/numass/data/storage/NumassDataLoader.kt b/numass-core/src/main/kotlin/inr/numass/data/storage/NumassDataLoader.kt index 049ec67e..038619e5 100644 --- a/numass-core/src/main/kotlin/inr/numass/data/storage/NumassDataLoader.kt +++ b/numass-core/src/main/kotlin/inr/numass/data/storage/NumassDataLoader.kt @@ -19,6 +19,7 @@ import hep.dataforge.context.Context import hep.dataforge.exceptions.StorageException import hep.dataforge.io.ColumnedDataReader import hep.dataforge.io.envelopes.Envelope +import hep.dataforge.kodex.toList import hep.dataforge.meta.Meta import hep.dataforge.meta.MetaBuilder import hep.dataforge.providers.Provider @@ -31,6 +32,9 @@ import hep.dataforge.tables.Table import inr.numass.data.api.NumassPoint import inr.numass.data.api.NumassSet import inr.numass.data.legacy.NumassFileEnvelope +import kotlinx.coroutines.experimental.CoroutineStart +import kotlinx.coroutines.experimental.Deferred +import kotlinx.coroutines.experimental.async import org.slf4j.LoggerFactory import java.io.IOException import java.nio.file.Files @@ -56,8 +60,8 @@ class NumassDataLoader( override val meta: Meta = items[META_FRAGMENT_NAME]?.get()?.meta ?: Meta.empty() - private val hvEnvelope: Optional - get() = Optional.ofNullable(items[HV_FRAGMENT_NAME]).map { it.get() } + private val hvEnvelope: Envelope? + get() = items[HV_FRAGMENT_NAME]?.get() private val pointEnvelopes: Stream get() = items.entries.stream() @@ -77,22 +81,24 @@ class NumassDataLoader( return items.keys } - override val hvData: Optional
- get() = hvEnvelope.map { hvEnvelope -> - try { - ColumnedDataReader(hvEnvelope.data.stream, "timestamp", "block", "value").toTable() - } catch (ex: IOException) { - LoggerFactory.getLogger(javaClass).error("Failed to load HV data from file", ex) - null + override val hvData: Deferred + get() = async(start = CoroutineStart.LAZY) { + hvEnvelope?.let { hvEnvelope -> + try { + ColumnedDataReader(hvEnvelope.data.stream, "timestamp", "block", "value").toTable() + } catch (ex: IOException) { + LoggerFactory.getLogger(javaClass).error("Failed to load HV data from file", ex) + null + } } } - override val points: Stream + override val points: List get() { return pointEnvelopes.map { NumassPoint.read(it) - } + }.toList() } override fun pull(fragmentName: String): Envelope { @@ -203,5 +209,6 @@ class NumassDataLoader( */ val HV_FRAGMENT_NAME = "voltage" } - } + + diff --git a/numass-core/src/main/kotlin/inr/numass/data/storage/ProtoNumassPoint.kt b/numass-core/src/main/kotlin/inr/numass/data/storage/ProtoNumassPoint.kt index 7e3741ee..7eafeef6 100644 --- a/numass-core/src/main/kotlin/inr/numass/data/storage/ProtoNumassPoint.kt +++ b/numass-core/src/main/kotlin/inr/numass/data/storage/ProtoNumassPoint.kt @@ -6,17 +6,13 @@ import hep.dataforge.io.envelopes.Envelope import hep.dataforge.kodex.toList import hep.dataforge.meta.Meta import inr.numass.data.NumassProto -import inr.numass.data.api.NumassBlock -import inr.numass.data.api.NumassEvent -import inr.numass.data.api.NumassFrame -import inr.numass.data.api.NumassPoint +import inr.numass.data.api.* import inr.numass.data.dataStream import inr.numass.data.legacy.NumassFileEnvelope import org.slf4j.LoggerFactory import java.nio.file.Path import java.time.Duration import java.time.Instant -import java.util.* import java.util.stream.IntStream import java.util.stream.Stream @@ -24,18 +20,23 @@ import java.util.stream.Stream * Protobuf based numass point * Created by darksnake on 09.07.2017. */ -class ProtoNumassPoint(override val meta: Meta, protoBuilder: () -> NumassProto.Point) : NumassPoint { +class ProtoNumassPoint(override val meta: Meta, val protoBuilder: () -> NumassProto.Point) : NumassPoint { - val proto: NumassProto.Point by lazy(protoBuilder) + val proto: NumassProto.Point + get() = protoBuilder() - override val blocks: List by lazy { - proto.channelsList.stream() + override val blocks: List + get() = proto.channelsList .flatMap { channel -> - channel.blocksList.stream() + channel.blocksList .map { block -> ProtoBlock(channel.id.toInt(), block, this) } - .sorted(Comparator.comparing { it.startTime }) - }.toList() - } + .sortedBy { it.startTime } + } + + override val channels: Map + get() = proto.channelsList.groupBy { it.id.toInt() }.mapValues { entry -> + MetaBlock(entry.value.flatMap { it.blocksList }.map { ProtoBlock(entry.key, it, this) }) + } override val voltage: Double = meta.getDouble("external_meta.HV1_value", super.voltage) @@ -62,7 +63,7 @@ class ProtoNumassPoint(override val meta: Meta, protoBuilder: () -> NumassProto. } fun fromEnvelope(envelope: Envelope): ProtoNumassPoint { - return ProtoNumassPoint(envelope.meta){ + return ProtoNumassPoint(envelope.meta) { envelope.dataStream.use { NumassProto.Point.parseFrom(it) } diff --git a/numass-core/src/main/proto/inr/numas/numass-proto.proto b/numass-core/src/main/proto/inr/numas/numass-proto.proto index bafb68c6..6ce6f065 100644 --- a/numass-core/src/main/proto/inr/numas/numass-proto.proto +++ b/numass-core/src/main/proto/inr/numas/numass-proto.proto @@ -12,10 +12,9 @@ message Point { uint64 time = 1; // Time in nanos from the beginning of the block bytes data = 2; // Frame data as an array of int16 mesured in arbitrary channels } - // Обработанные события. Содержат только время и амплитуду сигналов. - // Для экономии места при сериализации амплитуды и времена лежат в - // разных массивах. Амплитуда и время имеющие одинаковые индексы - // соответствуют одному событию + // Event block obtained directly from device of from frame analysis + // In order to save space, times and amplitudes are in separate arrays. + // Amplitude and time with the same index correspond to the same event message Events { repeated uint64 times = 1; // Array of time in nanos from the beginning of the block repeated uint64 amplitudes = 2; // Array of amplitudes of events in channels @@ -24,8 +23,8 @@ message Point { uint64 time = 1; // Block start in epoch nanos repeated Frame frames = 2; // Frames array Events events = 3; // Events array - uint64 length = 4; // block size in nanos - uint64 bin_size = 5; // tick size in nanos + uint64 length = 4; // block size in nanos. If missing, take from meta. + uint64 bin_size = 5; // tick size in nanos. Obsolete, to be removed } uint64 id = 1; // The number of measuring channel repeated Block blocks = 2; // Blocks 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 d80d28cc..d6ef3138 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/AmplitudeView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/AmplitudeView.kt @@ -6,7 +6,6 @@ import hep.dataforge.fx.runGoal import hep.dataforge.fx.ui import hep.dataforge.goals.Goal import hep.dataforge.kodex.configure -import hep.dataforge.kodex.toList import hep.dataforge.plots.PlotFrame import hep.dataforge.plots.PlotGroup import hep.dataforge.plots.Plottable @@ -15,10 +14,6 @@ import hep.dataforge.plots.jfreechart.JFreeChartFrame import hep.dataforge.tables.Adapters import inr.numass.data.analyzers.NumassAnalyzer import inr.numass.data.analyzers.withBinning -import inr.numass.data.api.MetaBlock -import inr.numass.data.api.NumassBlock -import inr.numass.data.api.NumassPoint -import inr.numass.data.channel import javafx.beans.Observable import javafx.beans.binding.DoubleBinding import javafx.beans.property.SimpleBooleanProperty @@ -74,7 +69,7 @@ class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = Imag addToSideBar(0, binningSelector, normalizeSwitch) } - private val data: ObservableMap = FXCollections.observableHashMap() + private val data: ObservableMap = FXCollections.observableHashMap() private val plots: ObservableMap> = FXCollections.observableHashMap() val isEmpty = booleanBinding(data) { data.isEmpty() } @@ -112,27 +107,14 @@ class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = Imag /** * Put or replace current plot with name `key` */ - fun add(key: String, point: NumassPoint) { + fun add(key: String, point: CachedPoint) { data[key] = point } - fun addAll(data: Map) { + fun addAll(data: Map) { this.data.putAll(data); } - /** - * Distinct map of channel number to corresponding grouping block - */ - private fun NumassPoint.getChannels(): Map { - return blocks.toList().groupBy { it.channel }.mapValues { entry -> - if (entry.value.size == 1) { - entry.value.first() - } else { - MetaBlock(entry.value) - } - } - } - private fun invalidate() { data.forEach { key, point -> plots.computeIfAbsent(key) { @@ -144,21 +126,21 @@ class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = Imag } val adapter = Adapters.buildXYAdapter(NumassAnalyzer.CHANNEL_KEY, valueAxis) - val channels = point.getChannels() + val channels = point.channelSpectra.await() return@runGoal if (channels.size == 1) { DataPlot.plot( key, adapter, - PointCache[point].withBinning(binning) + channels.values.first().withBinning(binning) ) } else { val group = PlotGroup.typed(key) - channels.forEach { key, block -> + channels.forEach { key, spectrum -> val plot = DataPlot.plot( key.toString(), adapter, - PointCache[block].withBinning(binning) + spectrum.withBinning(binning) ) group.add(plot) } @@ -192,7 +174,7 @@ class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = Imag /** * Set frame content to the given map. All keys not in the map are removed. */ - fun setAll(map: Map) { + fun setAll(map: Map) { plots.clear(); //Remove obsolete keys data.keys.filter { !map.containsKey(it) }.forEach { diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/Cache.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/Cache.kt new file mode 100644 index 00000000..646d46ca --- /dev/null +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/Cache.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2018 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.meta.Meta +import hep.dataforge.tables.Table +import inr.numass.data.analyzers.SimpleAnalyzer +import inr.numass.data.api.NumassBlock +import inr.numass.data.api.NumassPoint +import inr.numass.data.api.NumassSet +import kotlinx.coroutines.experimental.CoroutineStart +import kotlinx.coroutines.experimental.Deferred +import kotlinx.coroutines.experimental.async + +private val analyzer = SimpleAnalyzer() + + +class CachedPoint(point: NumassPoint) : NumassPoint by point { + private val lazyBlocks: () -> List = { point.blocks } + + override val blocks: List + get() = lazyBlocks() + + override val meta: Meta = point.meta + + val channelSpectra: Deferred> = async(start = CoroutineStart.LAZY) { + return@async point.channels.mapValues { (_, value) -> analyzer.getAmplitudeSpectrum(value) } + } + + val spectrum: Deferred
= async(start = CoroutineStart.LAZY) { + analyzer.getAmplitudeSpectrum(point) + } +} + +class CachedSet(set: NumassSet) : NumassSet by set { + override val points: List = set.points.map { CachedPoint(it) } +} 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 b33bae4f..97141f3e 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/HVView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/HVView.kt @@ -53,9 +53,9 @@ class HVView : View(title = "High voltage time plot", icon = ImageView(dfIcon)) if (change.wasAdded()) { runLater { container.progress = -1.0 } runGoal("hvData[${change.key}]") { - change.valueAdded.hvData + change.valueAdded.hvData.await() } ui { hvData -> - hvData.ifPresent { + hvData?.let { for (dp in it) { val plot: TimePlot = frame[change.key] as TimePlot? ?: TimePlot(change.key).apply { frame.add(this) } plot.put(dp.getValue("timestamp").getTime(), dp.getValue("value")) 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 b474487a..4ddb63e4 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/MainView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/MainView.kt @@ -144,7 +144,7 @@ class MainView(val context: Context = Global.getContext("viewer")) : View(title NumassDataLoader.fromDir(context, path) } ui { contentView = SpectrumView().apply { - add(it.name, it) + set(it.name, CachedSet(it)) } infoView = MetaViewer(it.meta) } except { @@ -195,9 +195,9 @@ class MainView(val context: Context = Global.getContext("viewer")) : View(title val point = NumassPoint.read(it) runLater { contentView = AmplitudeView().apply { - add(path.toString(), point) + add(path.toString(), CachedPoint(point)) } - infoView = PointInfoView(point) + infoView = PointInfoView(CachedPoint(point)) } } else { alert( diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/NumassDataCache.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/NumassDataCache.kt deleted file mode 100644 index 0fbe211e..00000000 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/NumassDataCache.kt +++ /dev/null @@ -1,26 +0,0 @@ -package inr.numass.viewer - -import hep.dataforge.meta.Meta -import hep.dataforge.tables.Table -import inr.numass.data.api.NumassPoint -import inr.numass.data.api.NumassSet -import java.util.* -import java.util.stream.Collectors -import java.util.stream.Stream - -/** - * Cached numass data - * Created by darksnake on 23-Jun-17. - */ -class NumassDataCache(private val data: NumassSet) : NumassSet { - //private val cachedDescription: String by lazy { data.description } - override val meta: Meta by lazy { data.meta } - private val cachedPoints: List by lazy { data.points.collect(Collectors.toList()) } - override val hvData: Optional
by lazy { data.hvData } - - - override val points: Stream - get() = cachedPoints.stream() - - override val name: String = data.name -} \ No newline at end of file diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/PointInfoView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/PointInfoView.kt index 9c6680fd..b6fbb41e 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/PointInfoView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/PointInfoView.kt @@ -2,13 +2,15 @@ package inr.numass.viewer import hep.dataforge.fx.meta.MetaViewer import inr.numass.data.analyzers.NumassAnalyzer -import inr.numass.data.api.NumassPoint +import kotlinx.coroutines.experimental.runBlocking import tornadofx.* import tornadofx.controlsfx.borders -class PointInfoView(val point: NumassPoint) : MetaViewer(point.meta) { +class PointInfoView(val point: CachedPoint) : MetaViewer(point.meta) { private val count: Int by lazy { - PointCache[point].sumBy { it.getValue(NumassAnalyzer.COUNT_KEY).int } + runBlocking { + point.spectrum.await().sumBy { it.getValue(NumassAnalyzer.COUNT_KEY).int } + } } override val root = super.root.apply { 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 1383f470..7a974b5a 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/SpectrumView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/SpectrumView.kt @@ -22,7 +22,6 @@ import javafx.util.converter.NumberStringConverter import org.controlsfx.control.RangeSlider import tornadofx.* import java.util.concurrent.atomic.AtomicInteger -import java.util.stream.Collectors /** * View for energy spectrum @@ -52,7 +51,7 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco private var upChannel by upChannelProperty - private val data: ObservableMap = FXCollections.observableHashMap(); + private val data: ObservableMap = FXCollections.observableHashMap(); val isEmpty = booleanBinding(data) { data.isEmpty() } override val root = borderpane { @@ -113,24 +112,24 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco private fun updateView() { runLater { container.progress = 0.0 } val progress = AtomicInteger(0) - val totalProgress = data.values.stream().mapToLong() { it.points.count() }.sum() + val totalProgress = data.values.stream().mapToInt { it.points.size }.sum() data.forEach { name, set -> val plot: DataPlot = frame[name] as DataPlot? ?: DataPlot(name).apply { frame.add(this) } runGoal("spectrumData[$name]") { set.points.map { point -> - val count = PointCache[point].countInWindow(loChannel.toShort(), upChannel.toShort()); + val count = point.spectrum.await().countInWindow(loChannel.toShort(), upChannel.toShort()); val seconds = point.length.toMillis() / 1000.0; runLater { - container.progress = progress.incrementAndGet().toDouble() / totalProgress + container.progress = progress.incrementAndGet().toDouble() / totalProgress } Adapters.buildXYDataPoint( point.voltage, (count / seconds), Math.sqrt(count.toDouble()) / seconds ) - }.collect(Collectors.toList()) + } } ui { points -> plot.fillData(points) container.progress = 1.0 @@ -139,8 +138,8 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco } } - fun add(key: String, value: NumassSet) { - data[key] = NumassDataCache(value) + operator fun set(key: String, value: CachedSet) { + data[key] = value } fun remove(key: String) { 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 e9fa1555..7c068b09 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt @@ -14,7 +14,6 @@ import javafx.beans.property.SimpleBooleanProperty import javafx.scene.control.ContextMenu import javafx.scene.control.TreeItem import tornadofx.* -import kotlin.streams.toList class StorageView(val storage: Storage) : View(title = "Numass storage", icon = dfIconView) { @@ -29,7 +28,7 @@ class StorageView(val storage: Storage) : View(title = "Numass storage", icon = val infoView: UIComponent? by lazy { when (content) { - is NumassPoint -> PointInfoView(content) + is CachedPoint -> PointInfoView(content) is Metoid -> MetaViewer(content.meta, title = "Meta view: $id") else -> null } @@ -38,16 +37,16 @@ class StorageView(val storage: Storage) : View(title = "Numass storage", icon = init { checkedProperty.onChange { selected -> when (content) { - is NumassPoint -> { + is CachedPoint -> { if (selected) { ampView.add(id, content) } else { ampView.remove(id) } } - is NumassSet -> { + is CachedSet -> { if (selected) { - spectrumView.add(id, content) + spectrumView.set(id, content) hvView.add(id, content) } else { spectrumView.remove(id) @@ -68,8 +67,8 @@ class StorageView(val storage: Storage) : View(title = "Numass storage", icon = val children: List? by lazy { when (content) { is Storage -> (content.shelves().sorted() + content.loaders().sorted()).map { buildContainer(it, this) } - is NumassSet -> content.points - .sorted(compareBy { it.index }) + is CachedSet -> content.points + .sortedBy { it.index } .map { buildContainer(it, this) } .toList() else -> null @@ -179,10 +178,10 @@ class StorageView(val storage: Storage) : View(title = "Numass storage", icon = } else { content.name } - Container(id, content) + Container(id, content as? CachedSet ?: CachedSet(content)) } is NumassPoint -> { - Container("${parent.id}/${content.voltage}[${content.index}]", content) + Container("${parent.id}/${content.voltage}[${content.index}]", content as? CachedPoint ?: CachedPoint(content)) } is Loader -> { Container(content.path.toString(), content); diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/Viewer.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/Viewer.kt index 6b9dfe60..33a5da02 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/Viewer.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/Viewer.kt @@ -4,11 +4,6 @@ import ch.qos.logback.classic.Level import ch.qos.logback.classic.Logger import hep.dataforge.context.Global import hep.dataforge.fx.dfIcon -import hep.dataforge.meta.Meta -import hep.dataforge.tables.Table -import hep.dataforge.utils.Misc -import inr.numass.data.analyzers.SimpleAnalyzer -import inr.numass.data.api.NumassBlock import javafx.stage.Stage import org.slf4j.LoggerFactory import tornadofx.* @@ -17,7 +12,7 @@ import tornadofx.* * Created by darksnake on 14-Apr-17. */ class Viewer : App(MainView::class) { - init{ + init { (LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as Logger).level = Level.INFO } @@ -30,16 +25,4 @@ class Viewer : App(MainView::class) { super.stop() Global.terminate(); } -} - -/** - * Global point cache - */ -object PointCache{ - private val analyzer = SimpleAnalyzer() - private val cache: MutableMap = Misc.getLRUCache(1000) - - operator fun get(point: NumassBlock): Table { - return cache.computeIfAbsent(point) { analyzer.getAmplitudeSpectrum(point, Meta.empty()) } - } } \ No newline at end of file diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/test/ComponentTest.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/test/ComponentTest.kt index a93d233b..1efc6285 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/test/ComponentTest.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/test/ComponentTest.kt @@ -6,14 +6,11 @@ import hep.dataforge.tables.Table import inr.numass.data.api.NumassPoint import inr.numass.data.api.NumassSet import inr.numass.data.storage.NumassStorageFactory -import inr.numass.viewer.AmplitudeView -import inr.numass.viewer.HVView -import inr.numass.viewer.SpectrumView +import inr.numass.viewer.* import javafx.application.Application import javafx.scene.image.ImageView import tornadofx.* import java.util.concurrent.ConcurrentHashMap -import java.util.stream.Collectors class ViewerComponentsTestApp : App(ViewerComponentsTest::class) @@ -53,8 +50,8 @@ class ViewerComponentsTest : View(title = "Numass viewer test", icon = ImageView } fun update(set: NumassSet) { - amp.setAll(set.points.filter { it.voltage != 16000.0 }.collect(Collectors.toMap({ "point_${it.voltage}" }, { it }))); - sp.add("test", set); + amp.setAll(set.points.filter { it.voltage != 16000.0 }.associateBy({ "point_${it.voltage}" }) { CachedPoint(it) }); + sp.set("test", CachedSet(set)); hv.add(set.name, set) } }