new numass viewer components
This commit is contained in:
parent
755a901d2e
commit
4904825bf2
@ -151,6 +151,7 @@ public class TimeAnalyzer extends AbstractAnalyzer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lastEvent.set(event);
|
lastEvent.set(event);
|
||||||
|
//TODO remove autoboxing somehow
|
||||||
return new Pair<>(event, res);
|
return new Pair<>(event, res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
123
numass-viewer/src/main/kotlin/inr/numass/viewer/AmplitudeView.kt
Normal file
123
numass-viewer/src/main/kotlin/inr/numass/viewer/AmplitudeView.kt
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
package inr.numass.viewer
|
||||||
|
|
||||||
|
import hep.dataforge.kodex.configure
|
||||||
|
import hep.dataforge.kodex.fx.dfIcon
|
||||||
|
import hep.dataforge.kodex.fx.plots.PlotContainer
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.plots.PlotFrame
|
||||||
|
import hep.dataforge.plots.data.DataPlot
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
||||||
|
import hep.dataforge.tables.Table
|
||||||
|
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 javafx.beans.property.SimpleBooleanProperty
|
||||||
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
|
import javafx.collections.FXCollections
|
||||||
|
import javafx.scene.control.CheckBox
|
||||||
|
import javafx.scene.control.ChoiceBox
|
||||||
|
import javafx.scene.image.ImageView
|
||||||
|
import tornadofx.*
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
|
class AmplitudeView(
|
||||||
|
private val analyzer: NumassAnalyzer = SimpleAnalyzer(),
|
||||||
|
private val cache: MutableMap<NumassPoint, Table> = ConcurrentHashMap()
|
||||||
|
) : View(title = "Numass amplitude spectrum plot", icon = ImageView(dfIcon)) {
|
||||||
|
|
||||||
|
private val frame: PlotFrame = JFreeChartFrame().configure {
|
||||||
|
"title" to "Detector response plot"
|
||||||
|
node("xAxis") {
|
||||||
|
"axisTitle" to "ADC"
|
||||||
|
"axisUnits" to "channels"
|
||||||
|
|
||||||
|
}
|
||||||
|
node("yAxis") {
|
||||||
|
"axisTitle" to "count rate"
|
||||||
|
"axisUnits" to "Hz"
|
||||||
|
}
|
||||||
|
"legend.show" to false
|
||||||
|
}
|
||||||
|
|
||||||
|
val binningProperty = SimpleObjectProperty<Int>(20)
|
||||||
|
var binning by binningProperty
|
||||||
|
|
||||||
|
val normalizeProperty = SimpleBooleanProperty(true)
|
||||||
|
var normalize by normalizeProperty
|
||||||
|
|
||||||
|
|
||||||
|
private val container = PlotContainer(frame).apply {
|
||||||
|
val binnintSelector: ChoiceBox<Int> = ChoiceBox(FXCollections.observableArrayList(1, 2, 5, 10, 20, 50)).apply {
|
||||||
|
minWidth = 0.0
|
||||||
|
selectionModel.selectLast()
|
||||||
|
binningProperty.bind(this.selectionModel.selectedItemProperty())
|
||||||
|
}
|
||||||
|
val normalizeSwitch: CheckBox = CheckBox("Normalize").apply {
|
||||||
|
minWidth = 0.0
|
||||||
|
this.selectedProperty().bindBidirectional(normalizeProperty)
|
||||||
|
}
|
||||||
|
addToSideBar(0, binnintSelector, normalizeSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val data: MutableMap<String, NumassPoint> = HashMap();
|
||||||
|
|
||||||
|
override val root = borderpane {
|
||||||
|
center = container.root
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSpectrum(point: NumassPoint): Table {
|
||||||
|
return cache.computeIfAbsent(point) { analyzer.getSpectrum(point, Meta.empty()) }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateView() {
|
||||||
|
val valueAxis = if (normalize) {
|
||||||
|
NumassAnalyzer.COUNT_RATE_KEY
|
||||||
|
} else {
|
||||||
|
NumassAnalyzer.COUNT_KEY
|
||||||
|
}
|
||||||
|
|
||||||
|
val progress = AtomicInteger(0);
|
||||||
|
runLater { container.progress = 0.0 }
|
||||||
|
|
||||||
|
runAsync {
|
||||||
|
val totalCount = data.size
|
||||||
|
|
||||||
|
data.map { entry ->
|
||||||
|
val seriesName = String.format("%s: %.2f", entry.key, entry.value.voltage)
|
||||||
|
DataPlot.plot(
|
||||||
|
seriesName,
|
||||||
|
XYAdapter(NumassAnalyzer.CHANNEL_KEY, valueAxis),
|
||||||
|
NumassDataUtils.spectrumWithBinning(getSpectrum(entry.value), binning)
|
||||||
|
).configure {
|
||||||
|
"connectionType" to "step"
|
||||||
|
"thickness" to 2
|
||||||
|
"showLine" to true
|
||||||
|
"showSymbol" to false
|
||||||
|
"showErrors" to false
|
||||||
|
"JFreeChart.cache" to true
|
||||||
|
}.also {
|
||||||
|
runLater { container.progress = progress.incrementAndGet().toDouble() / data.size }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ui { plots ->
|
||||||
|
frame.setAll(plots)
|
||||||
|
//detectorDataExportButton.isDisable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(map: Map<String, NumassPoint>) {
|
||||||
|
synchronized(data) {
|
||||||
|
//Remove obsolete keys
|
||||||
|
data.keys.filter { !map.containsKey(it) }.forEach {
|
||||||
|
data.remove(it)
|
||||||
|
frame.remove(it);
|
||||||
|
}
|
||||||
|
this.data.putAll(map);
|
||||||
|
updateView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
numass-viewer/src/main/kotlin/inr/numass/viewer/HVView.kt
Normal file
66
numass-viewer/src/main/kotlin/inr/numass/viewer/HVView.kt
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package inr.numass.viewer
|
||||||
|
|
||||||
|
import hep.dataforge.kodex.configure
|
||||||
|
import hep.dataforge.kodex.fx.dfIcon
|
||||||
|
import hep.dataforge.kodex.fx.plots.PlotContainer
|
||||||
|
import hep.dataforge.plots.PlotFrame
|
||||||
|
import hep.dataforge.plots.data.TimePlot
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
||||||
|
import inr.numass.data.api.NumassSet
|
||||||
|
import javafx.scene.image.ImageView
|
||||||
|
import tornadofx.*
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View for hv
|
||||||
|
*/
|
||||||
|
class HVView : View(title = "High voltage time plot", icon = ImageView(dfIcon)) {
|
||||||
|
|
||||||
|
private val frame: PlotFrame = JFreeChartFrame().configure {
|
||||||
|
"xAxis.axisTitle" to "time"
|
||||||
|
"xAxis.type" to "time"
|
||||||
|
"yAxis.axisTitle" to "HV"
|
||||||
|
}
|
||||||
|
private val container = PlotContainer(frame);
|
||||||
|
|
||||||
|
override val root = borderpane {
|
||||||
|
center = PlotContainer(frame).root
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun update(vararg sets: NumassSet) {
|
||||||
|
frame.plots.clear()
|
||||||
|
container.sideBarExpanded = false
|
||||||
|
|
||||||
|
val progress = AtomicInteger(0);
|
||||||
|
runLater { container.progress = -1.0 }
|
||||||
|
|
||||||
|
sets.forEach { data ->
|
||||||
|
runAsync {
|
||||||
|
val res = data.hvData
|
||||||
|
runLater { container.progress = progress.incrementAndGet().toDouble() / sets.size }
|
||||||
|
res
|
||||||
|
} ui { hvData ->
|
||||||
|
hvData.ifPresent {
|
||||||
|
for (dp in it) {
|
||||||
|
val blockName = dp.getString("block", "default").replace(".", "_");
|
||||||
|
//val opt = frame.opt(blockName)
|
||||||
|
val plot = frame.opt(blockName).orElseGet {
|
||||||
|
TimePlot(blockName).configure {
|
||||||
|
"connectionType" to "step"
|
||||||
|
"thickness" to 2
|
||||||
|
"showLine" to true
|
||||||
|
"showSymbol" to false
|
||||||
|
"showErrors" to false
|
||||||
|
}
|
||||||
|
.apply { frame.add(this) }
|
||||||
|
} as TimePlot;
|
||||||
|
plot.put(dp.getValue("timestamp").timeValue(), dp.getValue("value"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
container.progress = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,10 +7,10 @@ import hep.dataforge.kodex.buildMeta
|
|||||||
import hep.dataforge.kodex.fx.plots.PlotContainer
|
import hep.dataforge.kodex.fx.plots.PlotContainer
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.MetaBuilder
|
import hep.dataforge.meta.MetaBuilder
|
||||||
|
import hep.dataforge.plots.PlotGroup
|
||||||
import hep.dataforge.plots.XYPlotFrame
|
import hep.dataforge.plots.XYPlotFrame
|
||||||
import hep.dataforge.plots.data.DataPlot
|
import hep.dataforge.plots.data.DataPlot
|
||||||
import hep.dataforge.plots.data.PlotDataUtils
|
import hep.dataforge.plots.data.DataPlotUtils
|
||||||
import hep.dataforge.plots.data.PlottableGroup
|
|
||||||
import hep.dataforge.plots.data.TimePlot
|
import hep.dataforge.plots.data.TimePlot
|
||||||
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
||||||
import hep.dataforge.storage.commons.JSONMetaWriter
|
import hep.dataforge.storage.commons.JSONMetaWriter
|
||||||
@ -45,7 +45,7 @@ import java.util.concurrent.atomic.AtomicInteger
|
|||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
import java.util.stream.Collectors
|
import java.util.stream.Collectors
|
||||||
|
|
||||||
@Suppress("UNNECESSARY_LATEINIT")
|
|
||||||
/**
|
/**
|
||||||
* Numass loader view
|
* Numass loader view
|
||||||
*
|
*
|
||||||
@ -84,7 +84,7 @@ class NumassLoaderView : View() {
|
|||||||
private val spectra = HashMap<Double, Table>();//spectra cache
|
private val spectra = HashMap<Double, Table>();//spectra cache
|
||||||
|
|
||||||
val spectrumData = DataPlot("spectrum")
|
val spectrumData = DataPlot("spectrum")
|
||||||
val hvPlotData = PlottableGroup<TimePlot>()
|
val hvPlotData = PlotGroup("hv")
|
||||||
//private var points = FXCollections.observableArrayList<NumassPoint>()
|
//private var points = FXCollections.observableArrayList<NumassPoint>()
|
||||||
|
|
||||||
val detectorPlotFrame = JFreeChartFrame(
|
val detectorPlotFrame = JFreeChartFrame(
|
||||||
@ -224,7 +224,7 @@ class NumassLoaderView : View() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
spectrumData.clear()
|
spectrumData.clear()
|
||||||
hvPlotData.forEach { it.clear() }
|
hvPlotData.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +246,7 @@ class NumassLoaderView : View() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateHV(data: NumassSet) {
|
private fun updateHV(data: NumassSet) {
|
||||||
hvPlotData.forEach { it.clear() }
|
hvPlotData.clear()
|
||||||
runAsync {
|
runAsync {
|
||||||
data.hvData
|
data.hvData
|
||||||
} ui { hvData ->
|
} ui { hvData ->
|
||||||
@ -256,9 +256,10 @@ class NumassLoaderView : View() {
|
|||||||
if (!hvPlotData.has(block)) {
|
if (!hvPlotData.has(block)) {
|
||||||
hvPlotData.add(TimePlot(block))
|
hvPlotData.add(TimePlot(block))
|
||||||
}
|
}
|
||||||
hvPlotData.get(block).put(dp.getValue("timestamp").timeValue(), dp.getValue("value"))
|
(hvPlotData.opt(block).orElseThrow{RuntimeException()} as TimePlot)
|
||||||
|
.put(dp.getValue("timestamp").timeValue(), dp.getValue("value"))
|
||||||
}
|
}
|
||||||
hvPlot.plot.addAll(hvPlotData)
|
hvPlot.plot.add(hvPlotData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,7 +401,7 @@ class NumassLoaderView : View() {
|
|||||||
fileChooser.initialFileName = data!!.name + "_detector.out"
|
fileChooser.initialFileName = data!!.name + "_detector.out"
|
||||||
val destination = fileChooser.showSaveDialog(detectorPlotPane.scene.window)
|
val destination = fileChooser.showSaveDialog(detectorPlotPane.scene.window)
|
||||||
if (destination != null) {
|
if (destination != null) {
|
||||||
val detectorData = PlotDataUtils.collectXYDataFromPlot(detectorPlot.plot as XYPlotFrame, true)
|
val detectorData = DataPlotUtils.collectXYDataFromPlot(detectorPlot.plot as XYPlotFrame, true)
|
||||||
try {
|
try {
|
||||||
ColumnedDataWriter.writeTable(
|
ColumnedDataWriter.writeTable(
|
||||||
destination,
|
destination,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package inr.numass.viewer
|
package inr.numass.viewer
|
||||||
|
|
||||||
import hep.dataforge.kodex.buildMeta
|
|
||||||
import hep.dataforge.kodex.configure
|
import hep.dataforge.kodex.configure
|
||||||
|
import hep.dataforge.kodex.fx.dfIcon
|
||||||
import hep.dataforge.kodex.fx.plots.PlotContainer
|
import hep.dataforge.kodex.fx.plots.PlotContainer
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.plots.Plot
|
import hep.dataforge.plots.Plot
|
||||||
@ -13,23 +13,24 @@ 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.scene.image.ImageView
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by darksnake on 18.06.2017.
|
* Created by darksnake on 18.06.2017.
|
||||||
*/
|
*/
|
||||||
class SlowControlView : View("My View") {
|
class SlowControlView : View(title = "Numass slow control view", icon = ImageView(dfIcon)) {
|
||||||
private val plotMeta = buildMeta("plot") {
|
|
||||||
|
private val plot = JFreeChartFrame().configure {
|
||||||
"xAxis.type" to "time"
|
"xAxis.type" to "time"
|
||||||
"yAxis.type" to "log"
|
"yAxis.type" to "log"
|
||||||
}
|
}
|
||||||
|
|
||||||
val plot = JFreeChartFrame(plotMeta)
|
|
||||||
|
|
||||||
override val root = borderpane {
|
override val root = borderpane {
|
||||||
center = PlotContainer(plot).root
|
center = PlotContainer(plot).root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO add multiple loaders
|
||||||
fun load(loader: PointLoader) {
|
fun load(loader: PointLoader) {
|
||||||
runAsync {
|
runAsync {
|
||||||
val data = getData(loader)
|
val data = getData(loader)
|
||||||
|
177
numass-viewer/src/main/kotlin/inr/numass/viewer/SpectrumView.kt
Normal file
177
numass-viewer/src/main/kotlin/inr/numass/viewer/SpectrumView.kt
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
package inr.numass.viewer
|
||||||
|
|
||||||
|
import hep.dataforge.kodex.configure
|
||||||
|
import hep.dataforge.kodex.fx.dfIcon
|
||||||
|
import hep.dataforge.kodex.fx.plots.PlotContainer
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.plots.PlotFrame
|
||||||
|
import hep.dataforge.plots.data.DataPlot
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
||||||
|
import hep.dataforge.tables.Table
|
||||||
|
import hep.dataforge.tables.XYAdapter
|
||||||
|
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.beans.property.SimpleIntegerProperty
|
||||||
|
import javafx.geometry.Orientation
|
||||||
|
import javafx.scene.image.ImageView
|
||||||
|
import javafx.util.converter.IntegerStringConverter
|
||||||
|
import org.controlsfx.control.RangeSlider
|
||||||
|
import tornadofx.*
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
import java.util.stream.Collectors
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View for energy spectrum
|
||||||
|
* @param analyzer
|
||||||
|
* @param cache - optional global point cache
|
||||||
|
*/
|
||||||
|
class SpectrumView(
|
||||||
|
val analyzer: NumassAnalyzer = SimpleAnalyzer(),
|
||||||
|
val cache: MutableMap<NumassPoint, Table> = ConcurrentHashMap()
|
||||||
|
) : View(title = "Numass spectrum plot", icon = ImageView(dfIcon)) {
|
||||||
|
|
||||||
|
private val frame: PlotFrame = JFreeChartFrame().configure {
|
||||||
|
"xAxis.axisTitle" to "U"
|
||||||
|
"xAxis.axisUnits" to "V"
|
||||||
|
"yAxis.axisTitle" to "count rate"
|
||||||
|
"yAxis.axisUnits" to "Hz"
|
||||||
|
//"legend.show" to false
|
||||||
|
}
|
||||||
|
private val container = PlotContainer(frame);
|
||||||
|
|
||||||
|
|
||||||
|
private val loChannelProperty = SimpleIntegerProperty(0).apply {
|
||||||
|
addListener { _ -> updateView() }
|
||||||
|
}
|
||||||
|
private var loChannel by loChannelProperty
|
||||||
|
|
||||||
|
private val upChannelProperty = SimpleIntegerProperty(4000).apply {
|
||||||
|
addListener { _ -> updateView() }
|
||||||
|
}
|
||||||
|
private var upChannel by upChannelProperty
|
||||||
|
|
||||||
|
|
||||||
|
private val data: MutableMap<String, NumassSet> = HashMap()
|
||||||
|
|
||||||
|
/*
|
||||||
|
<BorderPane fx:id="spectrumPlotPane" prefHeight="200.0" prefWidth="200.0"
|
||||||
|
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||||
|
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
|
<top>
|
||||||
|
<ToolBar prefHeight="40.0" prefWidth="200.0" BorderPane.alignment="CENTER">
|
||||||
|
<VBox>
|
||||||
|
<Label text="Lo channel"/>
|
||||||
|
<TextField fx:id="lowChannelField" prefWidth="60.0"/>
|
||||||
|
</VBox>
|
||||||
|
<RangeSlider fx:id="channelSlider" accessibleRole="SLIDER"
|
||||||
|
highValue="1900.0" lowValue="300.0" majorTickUnit="500.0"
|
||||||
|
max="4000.0" minorTickCount="5" prefHeight="38.0"
|
||||||
|
prefWidth="276.0" showTickLabels="true" showTickMarks="true">
|
||||||
|
<padding>
|
||||||
|
<Insets left="10.0" right="10.0"/>
|
||||||
|
</padding>
|
||||||
|
</RangeSlider>
|
||||||
|
<VBox>
|
||||||
|
<Label text="Up channel"/>
|
||||||
|
<TextField fx:id="upChannelField" prefWidth="60.0"/>
|
||||||
|
</VBox>
|
||||||
|
<Separator orientation="VERTICAL"/>
|
||||||
|
<VBox>
|
||||||
|
<Label text="Dead time (us)"/>
|
||||||
|
<TextField fx:id="dTimeField" prefHeight="25.0" prefWidth="0.0"
|
||||||
|
text="7.2"/>
|
||||||
|
</VBox>
|
||||||
|
<Separator orientation="VERTICAL"/>
|
||||||
|
<Pane minWidth="0.0" HBox.hgrow="ALWAYS"/>
|
||||||
|
<Button fx:id="spectrumExportButton" mnemonicParsing="false" text="Export"/>
|
||||||
|
</ToolBar>
|
||||||
|
</top>
|
||||||
|
</BorderPane>
|
||||||
|
*/
|
||||||
|
override val root = borderpane {
|
||||||
|
top {
|
||||||
|
toolbar {
|
||||||
|
prefHeight = 40.0
|
||||||
|
vbox {
|
||||||
|
label("Lo channel")
|
||||||
|
textfield {
|
||||||
|
textProperty().bindBidirectional(loChannelProperty.asObject(), IntegerStringConverter())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
items += RangeSlider().apply {
|
||||||
|
highValueProperty().bindBidirectional(upChannelProperty)
|
||||||
|
lowValueProperty().bindBidirectional(loChannelProperty)
|
||||||
|
majorTickUnit = 500.0
|
||||||
|
max = 4000.0
|
||||||
|
minorTickCount = 5
|
||||||
|
prefHeight = 38.0
|
||||||
|
isShowTickLabels = true
|
||||||
|
isShowTickMarks = true
|
||||||
|
}
|
||||||
|
|
||||||
|
vbox {
|
||||||
|
label("Up channel")
|
||||||
|
textfield {
|
||||||
|
textProperty().bindBidirectional(upChannelProperty.asObject(), IntegerStringConverter())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
separator(Orientation.VERTICAL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
center = container.root
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSpectrum(point: NumassPoint): Table {
|
||||||
|
return cache.computeIfAbsent(point) { analyzer.getSpectrum(point, Meta.empty()) }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateView() {
|
||||||
|
runLater { container.progress = 0.0 }
|
||||||
|
val progress = AtomicInteger(0)
|
||||||
|
val totalProgress = data.values.stream().mapToLong() { it.points.count() }.sum()
|
||||||
|
|
||||||
|
data.forEach { name, set ->
|
||||||
|
val plot = frame.opt(name).orElseGet {
|
||||||
|
DataPlot(name).apply {
|
||||||
|
frame.add(this)
|
||||||
|
}
|
||||||
|
} as DataPlot
|
||||||
|
|
||||||
|
runAsync {
|
||||||
|
set.points.map { point ->
|
||||||
|
val count = NumassAnalyzer.countInWindow(getSpectrum(point), loChannel.toShort(), upChannel.toShort());
|
||||||
|
val seconds = point.length.toMillis() / 1000.0;
|
||||||
|
runLater {
|
||||||
|
container.progress = progress.incrementAndGet().toDouble() / totalProgress
|
||||||
|
}
|
||||||
|
XYAdapter.DEFAULT_ADAPTER.buildXYDataPoint(
|
||||||
|
point.voltage,
|
||||||
|
(count / seconds),
|
||||||
|
Math.sqrt(count.toDouble()) / seconds
|
||||||
|
)
|
||||||
|
}.collect(Collectors.toList())
|
||||||
|
} ui { points ->
|
||||||
|
plot.fillData(points)
|
||||||
|
container.progress = 1.0
|
||||||
|
//spectrumExportButton.isDisable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(map: Map<String, NumassSet>) {
|
||||||
|
synchronized(data) {
|
||||||
|
//Remove obsolete keys
|
||||||
|
data.keys.filter { !map.containsKey(it) }.forEach {
|
||||||
|
data.remove(it)
|
||||||
|
frame.remove(it);
|
||||||
|
}
|
||||||
|
this.data.putAll(map.mapValues { NumassDataCache(it.value) });
|
||||||
|
updateView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package inr.numass.viewer.test
|
||||||
|
|
||||||
|
import hep.dataforge.kodex.fx.dfIcon
|
||||||
|
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 javafx.application.Application
|
||||||
|
import javafx.scene.image.ImageView
|
||||||
|
import tornadofx.*
|
||||||
|
import java.io.File
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import java.util.stream.Collectors
|
||||||
|
|
||||||
|
class ViewerTestApp : App(ViewerTest::class)
|
||||||
|
|
||||||
|
class ViewerTest : View(title = "Numass viewer test", icon = ImageView(dfIcon)) {
|
||||||
|
|
||||||
|
//val rootDir = File("D:\\Work\\Numass\\data\\2017_05\\Fill_2")
|
||||||
|
|
||||||
|
//val set: NumassSet = NumassStorageFactory.buildLocal(rootDir).provide("loader::set_8", NumassSet::class.java).orElseThrow { RuntimeException("err") }
|
||||||
|
|
||||||
|
|
||||||
|
private val cache: MutableMap<NumassPoint, Table> = ConcurrentHashMap();
|
||||||
|
|
||||||
|
val amp = AmplitudeView(cache = cache)
|
||||||
|
val sp = SpectrumView(cache = cache)
|
||||||
|
val hv = HVView()
|
||||||
|
|
||||||
|
override val root = borderpane {
|
||||||
|
top {
|
||||||
|
button("Click me!") {
|
||||||
|
action {
|
||||||
|
runAsync {
|
||||||
|
val rootDir = File("D:\\Work\\Numass\\data\\2017_05\\Fill_2")
|
||||||
|
val set: NumassSet = NumassStorageFactory.buildLocal(rootDir).provide("loader::set_3", NumassSet::class.java)
|
||||||
|
.orElseThrow { RuntimeException("err") }
|
||||||
|
update(set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
center {
|
||||||
|
tabpane {
|
||||||
|
tab("amplitude") {
|
||||||
|
content = amp.root
|
||||||
|
}
|
||||||
|
tab("spectrum") {
|
||||||
|
content = sp.root
|
||||||
|
}
|
||||||
|
tab("hv") {
|
||||||
|
content = hv.root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(set: NumassSet) {
|
||||||
|
amp.update(set.points.filter { it.voltage != 16000.0 }.collect(Collectors.toMap({ "point_${it.voltage}" }, { it })));
|
||||||
|
sp.update(mapOf("test" to set));
|
||||||
|
hv.update(set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
Application.launch(ViewerTestApp::class.java, *args);
|
||||||
|
}
|
@ -20,73 +20,61 @@ limitations under the License.
|
|||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
<?import org.controlsfx.control.RangeSlider?>
|
<?import org.controlsfx.control.RangeSlider?>
|
||||||
<AnchorPane id="AnchorPane" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
|
<AnchorPane id="AnchorPane" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0"
|
||||||
<children>
|
xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<TabPane fx:id="tabPane" layoutX="200.0" layoutY="100.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<TabPane fx:id="tabPane" layoutX="200.0" layoutY="100.0" minHeight="-Infinity" minWidth="-Infinity"
|
||||||
<tabs>
|
prefHeight="400.0" prefWidth="600.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0"
|
||||||
<Tab text="Info">
|
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
<content>
|
<Tab text="Info">
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||||
<children>
|
<TextArea fx:id="infoTextBox" layoutY="30.0" prefHeight="200.0" prefWidth="200.0"
|
||||||
<TextArea fx:id="infoTextBox" layoutY="30.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0" />
|
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||||
</children>
|
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0"/>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
</content>
|
</Tab>
|
||||||
</Tab>
|
<Tab fx:id="detectorTab" text="Detector">
|
||||||
<Tab fx:id="detectorTab" text="Detector">
|
<BorderPane fx:id="detectorPlotPane" minHeight="0.0" minWidth="0.0" prefHeight="180.0"
|
||||||
<content>
|
prefWidth="200.0"/>
|
||||||
<BorderPane fx:id="detectorPlotPane" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
|
</Tab>
|
||||||
</content>
|
<Tab fx:id="hvTab" text="HV">
|
||||||
</Tab>
|
<BorderPane fx:id="hvPane" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0"/>
|
||||||
<Tab fx:id="hvTab" text="HV">
|
</Tab>
|
||||||
<content>
|
<Tab fx:id="spectrumTab" text="Spectrum">
|
||||||
<BorderPane fx:id="hvPane" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
|
<AnchorPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0">
|
||||||
</content>
|
<BorderPane fx:id="spectrumPlotPane" prefHeight="200.0" prefWidth="200.0"
|
||||||
</Tab>
|
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||||
<Tab fx:id="spectrumTab" text="Spectrum">
|
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
<content>
|
<top>
|
||||||
<AnchorPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0">
|
<ToolBar prefHeight="40.0" prefWidth="200.0" BorderPane.alignment="CENTER">
|
||||||
<children>
|
<VBox>
|
||||||
<BorderPane fx:id="spectrumPlotPane" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<Label text="Lo channel"/>
|
||||||
<top>
|
<TextField fx:id="lowChannelField" prefWidth="60.0"/>
|
||||||
<ToolBar prefHeight="40.0" prefWidth="200.0" BorderPane.alignment="CENTER">
|
</VBox>
|
||||||
<items>
|
<RangeSlider fx:id="channelSlider" accessibleRole="SLIDER"
|
||||||
<VBox>
|
highValue="1900.0" lowValue="300.0" majorTickUnit="500.0"
|
||||||
<children>
|
max="4000.0" minorTickCount="5" prefHeight="38.0"
|
||||||
<Label text="Lo channel" />
|
prefWidth="276.0" showTickLabels="true" showTickMarks="true">
|
||||||
<TextField fx:id="lowChannelField" prefWidth="60.0" />
|
<padding>
|
||||||
</children>
|
<Insets left="10.0" right="10.0"/>
|
||||||
</VBox>
|
</padding>
|
||||||
<RangeSlider fx:id="channelSlider" accessibleRole="SLIDER" highValue="1900.0" lowValue="300.0" majorTickUnit="500.0" max="4000.0" minorTickCount="5" prefHeight="38.0" prefWidth="276.0" showTickLabels="true" showTickMarks="true">
|
</RangeSlider>
|
||||||
<padding>
|
<VBox>
|
||||||
<Insets left="10.0" right="10.0" />
|
<Label text="Up channel"/>
|
||||||
</padding>
|
<TextField fx:id="upChannelField" prefWidth="60.0"/>
|
||||||
</RangeSlider>
|
</VBox>
|
||||||
<VBox>
|
<Separator orientation="VERTICAL"/>
|
||||||
<children>
|
<VBox>
|
||||||
<Label text="Up channel" />
|
<Label text="Dead time (us)"/>
|
||||||
<TextField fx:id="upChannelField" prefWidth="60.0" />
|
<TextField fx:id="dTimeField" prefHeight="25.0" prefWidth="0.0"
|
||||||
</children>
|
text="7.2"/>
|
||||||
</VBox>
|
</VBox>
|
||||||
<Separator orientation="VERTICAL" />
|
<Separator orientation="VERTICAL"/>
|
||||||
<VBox>
|
<Pane minWidth="0.0" HBox.hgrow="ALWAYS"/>
|
||||||
<children>
|
<Button fx:id="spectrumExportButton" mnemonicParsing="false" text="Export"/>
|
||||||
<Label text="Dead time (us)" />
|
</ToolBar>
|
||||||
<TextField fx:id="dTimeField" prefHeight="25.0" prefWidth="0.0" text="7.2" />
|
</top>
|
||||||
</children>
|
</BorderPane>
|
||||||
</VBox>
|
</AnchorPane>
|
||||||
<Separator orientation="VERTICAL" />
|
</Tab>
|
||||||
<Pane minWidth="0.0" HBox.hgrow="ALWAYS" />
|
</TabPane>
|
||||||
<Button fx:id="spectrumExportButton" mnemonicParsing="false" text="Export" />
|
|
||||||
</items>
|
|
||||||
</ToolBar>
|
|
||||||
</top>
|
|
||||||
</BorderPane>
|
|
||||||
</children>
|
|
||||||
</AnchorPane>
|
|
||||||
</content>
|
|
||||||
</Tab>
|
|
||||||
</tabs>
|
|
||||||
</TabPane>
|
|
||||||
</children>
|
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
|
Loading…
Reference in New Issue
Block a user