Fix viewer cache
This commit is contained in:
parent
d3689638e0
commit
15d17f2cc4
@ -1,6 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.5.31"
|
kotlin("jvm") version "1.5.31"
|
||||||
id("org.openjfx.javafxplugin") version "0.0.9" apply false
|
id("org.openjfx.javafxplugin") version "0.0.10" apply false
|
||||||
id("com.github.johnrengelman.shadow") version "7.1.0" apply false
|
id("com.github.johnrengelman.shadow") version "7.1.0" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ allprojects {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
/*
|
|
||||||
* The Alphanum Algorithm is an improved sorting algorithm for strings
|
|
||||||
* containing numbers. Instead of sorting numbers in ASCII order like
|
|
||||||
* a standard sort, this algorithm sorts numbers in numeric order.
|
|
||||||
*
|
|
||||||
* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package hep.dataforge.names;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an updated version with enhancements made by Daniel Migowski,
|
|
||||||
* Andre Bogus, and David Koelle
|
|
||||||
* To use this class:
|
|
||||||
* Use the static "sort" method from the java.util.Collections class:
|
|
||||||
* Collections.sort(your list, new AlphanumComparator());
|
|
||||||
*/
|
|
||||||
public class AlphanumComparator implements Comparator<String> {
|
|
||||||
public static final AlphanumComparator INSTANCE = new AlphanumComparator();
|
|
||||||
|
|
||||||
private Comparator<String> comparator = new NaturalComparator();
|
|
||||||
|
|
||||||
public AlphanumComparator(Comparator<String> comparator) {
|
|
||||||
this.comparator = comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AlphanumComparator() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private final boolean isDigit(char ch) {
|
|
||||||
return ch >= 48 && ch <= 57;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Length of string is passed in for improved efficiency (only need to calculate it once)
|
|
||||||
**/
|
|
||||||
private final String getChunk(String s, int slength, int marker) {
|
|
||||||
StringBuilder chunk = new StringBuilder();
|
|
||||||
char c = s.charAt(marker);
|
|
||||||
chunk.append(c);
|
|
||||||
marker++;
|
|
||||||
if (isDigit(c)) {
|
|
||||||
while (marker < slength) {
|
|
||||||
c = s.charAt(marker);
|
|
||||||
if (!isDigit(c))
|
|
||||||
break;
|
|
||||||
chunk.append(c);
|
|
||||||
marker++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while (marker < slength) {
|
|
||||||
c = s.charAt(marker);
|
|
||||||
if (isDigit(c))
|
|
||||||
break;
|
|
||||||
chunk.append(c);
|
|
||||||
marker++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return chunk.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compare(String s1, String s2) {
|
|
||||||
|
|
||||||
int thisMarker = 0;
|
|
||||||
int thatMarker = 0;
|
|
||||||
int s1Length = s1.length();
|
|
||||||
int s2Length = s2.length();
|
|
||||||
|
|
||||||
while (thisMarker < s1Length && thatMarker < s2Length) {
|
|
||||||
String thisChunk = getChunk(s1, s1Length, thisMarker);
|
|
||||||
thisMarker += thisChunk.length();
|
|
||||||
|
|
||||||
String thatChunk = getChunk(s2, s2Length, thatMarker);
|
|
||||||
thatMarker += thatChunk.length();
|
|
||||||
|
|
||||||
// If both chunks contain numeric characters, sort them numerically
|
|
||||||
int result = 0;
|
|
||||||
if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) {
|
|
||||||
// Simple chunk comparison by length.
|
|
||||||
int thisChunkLength = thisChunk.length();
|
|
||||||
result = thisChunkLength - thatChunk.length();
|
|
||||||
// If equal, the first different number counts
|
|
||||||
if (result == 0) {
|
|
||||||
for (int i = 0; i < thisChunkLength; i++) {
|
|
||||||
result = thisChunk.charAt(i) - thatChunk.charAt(i);
|
|
||||||
if (result != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result = comparator.compare(thisChunk, thatChunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s1Length - s2Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class NaturalComparator implements Comparator<String> {
|
|
||||||
public int compare(String o1, String o2) {
|
|
||||||
return o1.compareTo(o2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,6 +6,7 @@
|
|||||||
package hep.dataforge.utils;
|
package hep.dataforge.utils;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -15,7 +16,7 @@ import java.util.concurrent.CancellationException;
|
|||||||
* @author Alexander Nozik
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public class Misc {
|
public class Misc {
|
||||||
public static final Charset UTF = Charset.forName("UTF-8");
|
public static final Charset UTF = StandardCharsets.UTF_8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A synchronized lru cache
|
* A synchronized lru cache
|
||||||
|
@ -36,6 +36,7 @@ import hep.dataforge.values.Value
|
|||||||
import hep.dataforge.values.ValueProvider
|
import hep.dataforge.values.ValueProvider
|
||||||
import hep.dataforge.values.ValueProvider.Companion.VALUE_TARGET
|
import hep.dataforge.values.ValueProvider.Companion.VALUE_TARGET
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -47,7 +48,6 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
import java.util.concurrent.ExecutorService
|
import java.util.concurrent.ExecutorService
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
import kotlin.collections.HashMap
|
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.streams.asSequence
|
import kotlin.streams.asSequence
|
||||||
@ -308,10 +308,12 @@ open class Context(
|
|||||||
*/
|
*/
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
override fun close() {
|
override fun close() {
|
||||||
|
logger.info("Closing context: $name")
|
||||||
//detach all plugins
|
//detach all plugins
|
||||||
plugins.close()
|
plugins.close()
|
||||||
|
|
||||||
if (started) {
|
if (started) {
|
||||||
|
coroutineContext.cancel()
|
||||||
dispatcher.shutdown()
|
dispatcher.shutdown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,15 +133,13 @@ object Global : Context("GLOBAL", null, Thread.currentThread().contextClassLoade
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun getContext(name: String): Context {
|
fun getContext(name: String): Context = contextRegistry
|
||||||
return contextRegistry
|
|
||||||
.findFirst { ctx -> ctx.name == name }
|
.findFirst { ctx -> ctx.name == name }
|
||||||
.orElseGet {
|
.orElseGet {
|
||||||
val ctx = Context(name)
|
val ctx = Context(name)
|
||||||
contextRegistry.add(ctx)
|
contextRegistry.add(ctx)
|
||||||
ctx
|
ctx
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close all contexts and terminate framework
|
* Close all contexts and terminate framework
|
||||||
|
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* The Alphanum Algorithm is an improved sorting algorithm for strings
|
||||||
|
* containing numbers. Instead of sorting numbers in ASCII order like
|
||||||
|
* a standard sort, this algorithm sorts numbers in numeric order.
|
||||||
|
*
|
||||||
|
* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package hep.dataforge.names
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is an updated version with enhancements made by Daniel Migowski,
|
||||||
|
* Andre Bogus, and David Koelle
|
||||||
|
* To use this class:
|
||||||
|
* Use the static "sort" method from the java.util.Collections class:
|
||||||
|
* Collections.sort(your list, new AlphanumComparator());
|
||||||
|
*/
|
||||||
|
object AlphanumComparator : Comparator<String> {
|
||||||
|
private val comparator: Comparator<String> = NaturalComparator()
|
||||||
|
|
||||||
|
private fun isDigit(ch: Char): Boolean {
|
||||||
|
return ch.code in 48..57
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Length of string is passed in for improved efficiency (only need to calculate it once)
|
||||||
|
*/
|
||||||
|
private fun getChunk(s: String, slength: Int, marker: Int): String {
|
||||||
|
var modMarker = marker
|
||||||
|
val chunk = StringBuilder()
|
||||||
|
var c = s[modMarker]
|
||||||
|
chunk.append(c)
|
||||||
|
modMarker++
|
||||||
|
if (isDigit(c)) {
|
||||||
|
while (modMarker < slength) {
|
||||||
|
c = s[modMarker]
|
||||||
|
if (!isDigit(c)) break
|
||||||
|
chunk.append(c)
|
||||||
|
modMarker++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (modMarker < slength) {
|
||||||
|
c = s[modMarker]
|
||||||
|
if (isDigit(c)) break
|
||||||
|
chunk.append(c)
|
||||||
|
modMarker++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chunk.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun compare(s1: String, s2: String): Int {
|
||||||
|
var thisMarker = 0
|
||||||
|
var thatMarker = 0
|
||||||
|
val s1Length = s1.length
|
||||||
|
val s2Length = s2.length
|
||||||
|
while (thisMarker < s1Length && thatMarker < s2Length) {
|
||||||
|
val thisChunk = getChunk(s1, s1Length, thisMarker)
|
||||||
|
thisMarker += thisChunk.length
|
||||||
|
val thatChunk = getChunk(s2, s2Length, thatMarker)
|
||||||
|
thatMarker += thatChunk.length
|
||||||
|
|
||||||
|
// If both chunks contain numeric characters, sort them numerically
|
||||||
|
var result = 0
|
||||||
|
if (isDigit(thisChunk[0]) && isDigit(thatChunk[0])) {
|
||||||
|
// Simple chunk comparison by length.
|
||||||
|
val thisChunkLength = thisChunk.length
|
||||||
|
result = thisChunkLength - thatChunk.length
|
||||||
|
// If equal, the first different number counts
|
||||||
|
if (result == 0) {
|
||||||
|
for (i in 0 until thisChunkLength) {
|
||||||
|
result = thisChunk[i] - thatChunk[i]
|
||||||
|
if (result != 0) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = comparator.compare(thisChunk, thatChunk)
|
||||||
|
}
|
||||||
|
if (result != 0) return result
|
||||||
|
}
|
||||||
|
return s1Length - s2Length
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NaturalComparator : Comparator<String> {
|
||||||
|
override fun compare(o1: String, o2: String): Int {
|
||||||
|
return o1.compareTo(o2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -126,7 +126,7 @@ interface Value : Serializable, Comparable<Value> {
|
|||||||
return when (type) {
|
return when (type) {
|
||||||
ValueType.NUMBER -> ValueUtils.NUMBER_COMPARATOR.compare(number, other.number)
|
ValueType.NUMBER -> ValueUtils.NUMBER_COMPARATOR.compare(number, other.number)
|
||||||
ValueType.BOOLEAN -> boolean.compareTo(other.boolean)
|
ValueType.BOOLEAN -> boolean.compareTo(other.boolean)
|
||||||
ValueType.STRING -> AlphanumComparator.INSTANCE.compare(this.string, other.string)
|
ValueType.STRING -> AlphanumComparator.compare(this.string, other.string)
|
||||||
ValueType.TIME -> time.compareTo(other.time)
|
ValueType.TIME -> time.compareTo(other.time)
|
||||||
ValueType.NULL -> if (other.type == ValueType.NULL) 0 else -1
|
ValueType.NULL -> if (other.type == ValueType.NULL) 0 else -1
|
||||||
ValueType.BINARY -> binary.compareTo(other.binary)
|
ValueType.BINARY -> binary.compareTo(other.binary)
|
||||||
|
@ -70,6 +70,7 @@ class WorkspaceTest {
|
|||||||
@BeforeClass
|
@BeforeClass
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setup() {
|
fun setup() {
|
||||||
|
counter.set(0)
|
||||||
val context = Global.getContext("TEST").apply {
|
val context = Global.getContext("TEST").apply {
|
||||||
load(CachePlugin::class.java, MetaBuilder().setValue("fileCache.enabled", false))
|
load(CachePlugin::class.java, MetaBuilder().setValue("fileCache.enabled", false))
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
//apply plugin: 'org.openjfx.javafxplugin'
|
|
||||||
//
|
|
||||||
//javafx {
|
|
||||||
// modules = [ 'javafx.controls', 'javafx.web' ]
|
|
||||||
//}
|
|
||||||
|
|
||||||
description = "A tornadofx based kotlin library"
|
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
api project(':dataforge-plots')
|
|
||||||
api project(':dataforge-gui:dataforge-html')
|
|
||||||
api 'org.controlsfx:controlsfx:8.40.14'
|
|
||||||
api "no.tornado:tornadofx:1.7.19"
|
|
||||||
api 'no.tornado:tornadofx-controlsfx:0.1.1'
|
|
||||||
api group: 'org.fxmisc.richtext', name: 'richtextfx', version: '0.10.2'
|
|
||||||
api 'org.jetbrains.kotlinx:kotlinx-coroutines-javafx:1.5.0'
|
|
||||||
|
|
||||||
// optional dependency for JFreeChart
|
|
||||||
//compileOnly project(":dataforge-plots:plots-jfc")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
25
dataforge-gui/build.gradle.kts
Normal file
25
dataforge-gui/build.gradle.kts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
plugins {
|
||||||
|
id("org.openjfx.javafxplugin")
|
||||||
|
}
|
||||||
|
|
||||||
|
javafx {
|
||||||
|
modules = listOf("javafx.controls", "javafx.web")
|
||||||
|
version = "11"
|
||||||
|
}
|
||||||
|
|
||||||
|
description = "A tornadofx based kotlin library"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":dataforge-plots"))
|
||||||
|
api(project(":dataforge-gui:dataforge-html"))
|
||||||
|
api("no.tornado:tornadofx:1.7.20")
|
||||||
|
api("org.controlsfx:controlsfx:11.1.0")
|
||||||
|
api("no.tornado:tornadofx-controlsfx:0.1.1")
|
||||||
|
api("org.fxmisc.richtext:richtextfx:0.10.7")
|
||||||
|
api("org.jetbrains.kotlinx:kotlinx-coroutines-javafx:1.5.2")
|
||||||
|
|
||||||
|
// optional dependency for JFreeChart
|
||||||
|
//compileOnly project(":dataforge-plots:plots-jfc")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -2,5 +2,6 @@ description = "An html rendering core and HTML output"
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api project(':dataforge-core')
|
api project(':dataforge-core')
|
||||||
api 'org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.11'
|
// https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-html-jvm
|
||||||
|
api 'org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.3'
|
||||||
}
|
}
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
//allprojects {
|
|
||||||
// apply plugin: 'org.openjfx.javafxplugin'
|
|
||||||
//
|
|
||||||
// javafx {
|
|
||||||
// modules = ['javafx.controls']
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
description = 'dataforge-plots'
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
api project(':dataforge-core')
|
|
||||||
}
|
|
14
dataforge-plots/build.gradle.kts
Normal file
14
dataforge-plots/build.gradle.kts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
plugins {
|
||||||
|
id("org.openjfx.javafxplugin")
|
||||||
|
}
|
||||||
|
|
||||||
|
javafx {
|
||||||
|
modules = listOf("javafx.controls")
|
||||||
|
version = "11"
|
||||||
|
}
|
||||||
|
|
||||||
|
description = "dataforge-plots"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":dataforge-core"))
|
||||||
|
}
|
@ -33,11 +33,11 @@ import hep.dataforge.storage.MutableStorage
|
|||||||
import hep.dataforge.storage.StorageElement
|
import hep.dataforge.storage.StorageElement
|
||||||
import hep.dataforge.storage.StorageElementType
|
import hep.dataforge.storage.StorageElementType
|
||||||
import hep.dataforge.storage.StorageManager
|
import hep.dataforge.storage.StorageManager
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.joinAll
|
import kotlinx.coroutines.joinAll
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.nio.file.*
|
import java.nio.file.*
|
||||||
import kotlin.streams.asSequence
|
import kotlin.streams.asSequence
|
||||||
import kotlin.streams.toList
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An element of file storage with fixed path
|
* An element of file storage with fixed path
|
||||||
@ -67,7 +67,7 @@ class FileStorage(
|
|||||||
override val meta: Meta,
|
override val meta: Meta,
|
||||||
override val path: Path,
|
override val path: Path,
|
||||||
override val parent: StorageElement? = null,
|
override val parent: StorageElement? = null,
|
||||||
val type: FileStorageElementType
|
val type: FileStorageElementType,
|
||||||
) : MutableStorage, FileStorageElement {
|
) : MutableStorage, FileStorageElement {
|
||||||
|
|
||||||
private val _connectionHelper by lazy { ConnectionHelper(this) }
|
private val _connectionHelper by lazy { ConnectionHelper(this) }
|
||||||
@ -79,15 +79,14 @@ class FileStorage(
|
|||||||
|
|
||||||
|
|
||||||
override val children: Collection<StorageElement>
|
override val children: Collection<StorageElement>
|
||||||
get() = synchronized(this) {
|
get() = runBlocking(Dispatchers.IO) {
|
||||||
runBlocking {
|
|
||||||
if (!isInitialized) {
|
if (!isInitialized) {
|
||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_children.values
|
_children.values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun resolveType(meta: Meta): StorageElementType? {
|
override fun resolveType(meta: Meta): StorageElementType? {
|
||||||
val type = meta.optString(StorageManager.STORAGE_META_TYPE_KEY).nullable
|
val type = meta.optString(StorageManager.STORAGE_META_TYPE_KEY).nullable
|
||||||
return if (type == null) {
|
return if (type == null) {
|
||||||
@ -141,7 +140,10 @@ class FileStorage(
|
|||||||
/**
|
/**
|
||||||
* Resolve meta for given path if it is available. If directory search for file called meta or meta.df inside
|
* Resolve meta for given path if it is available. If directory search for file called meta or meta.df inside
|
||||||
*/
|
*/
|
||||||
fun resolveMeta(path: Path, metaReader: (Path) -> Meta? = { EnvelopeType.infer(it)?.reader?.read(it)?.meta }): Meta? {
|
fun resolveMeta(
|
||||||
|
path: Path,
|
||||||
|
metaReader: (Path) -> Meta? = { EnvelopeType.infer(it)?.reader?.read(it)?.meta },
|
||||||
|
): Meta? {
|
||||||
return if (Files.isDirectory(path)) {
|
return if (Files.isDirectory(path)) {
|
||||||
Files.list(path).asSequence()
|
Files.list(path).asSequence()
|
||||||
.find { it.fileName.toString() == "meta.df" || it.fileName.toString() == "meta" }
|
.find { it.fileName.toString() == "meta.df" || it.fileName.toString() == "meta" }
|
||||||
@ -167,7 +169,9 @@ class FileStorage(
|
|||||||
|
|
||||||
@ValueDefs(
|
@ValueDefs(
|
||||||
ValueDef(key = "path", info = "The relative path to the shelf inside parent storage or absolute path"),
|
ValueDef(key = "path", info = "The relative path to the shelf inside parent storage or absolute path"),
|
||||||
ValueDef(key = "name", required = true, info = "The name of the new storage. By default use last segment shelf name")
|
ValueDef(key = "name",
|
||||||
|
required = true,
|
||||||
|
info = "The name of the new storage. By default use last segment shelf name")
|
||||||
)
|
)
|
||||||
override fun create(context: Context, meta: Meta, parent: StorageElement?): FileStorageElement {
|
override fun create(context: Context, meta: Meta, parent: StorageElement?): FileStorageElement {
|
||||||
val shelfName = meta.getString("name")
|
val shelfName = meta.getString("name")
|
||||||
@ -192,7 +196,9 @@ class FileStorage(
|
|||||||
override suspend fun read(context: Context, path: Path, parent: StorageElement?): FileStorageElement? {
|
override suspend fun read(context: Context, path: Path, parent: StorageElement?): FileStorageElement? {
|
||||||
val meta = resolveMeta(path)
|
val meta = resolveMeta(path)
|
||||||
val name = meta?.optString("name").nullable ?: path.fileName.toString()
|
val name = meta?.optString("name").nullable ?: path.fileName.toString()
|
||||||
val type = meta?.optString("type").nullable?.let { context.load<StorageManager>().getType(it) } as? FileStorageElementType
|
val type = meta?.optString("type").nullable?.let {
|
||||||
|
context.load<StorageManager>().getType(it)
|
||||||
|
} as? FileStorageElementType
|
||||||
return if (type == null || type is Directory) {
|
return if (type == null || type is Directory) {
|
||||||
// Read path as directory if type not found and path is directory
|
// Read path as directory if type not found and path is directory
|
||||||
if (Files.isDirectory(path)) {
|
if (Files.isDirectory(path)) {
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
idea
|
|
||||||
kotlin("jvm")
|
kotlin("jvm")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
@ -13,7 +9,3 @@ repositories {
|
|||||||
dependencies {
|
dependencies {
|
||||||
api(project(":dataforge-core"))
|
api(project(":dataforge-core"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<KotlinCompile> {
|
|
||||||
kotlinOptions.jvmTarget = "1.8"
|
|
||||||
}
|
|
@ -28,7 +28,6 @@ import java.util.stream.Stream
|
|||||||
*/
|
*/
|
||||||
interface NumassPoint : Metoid, ParentBlock, Provider {
|
interface NumassPoint : Metoid, ParentBlock, Provider {
|
||||||
|
|
||||||
|
|
||||||
override val blocks: List<NumassBlock>
|
override val blocks: List<NumassBlock>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
apply plugin: 'application'
|
|
||||||
apply plugin: 'kotlin'
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
//apply plugin: 'org.openjfx.javafxplugin'
|
|
||||||
//
|
|
||||||
//javafx {
|
|
||||||
// modules = [ 'javafx.controls' ]
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (!hasProperty('mainClass')) {
|
|
||||||
ext.mainClass = 'inr.numass.viewer.Viewer'//"inr.numass.viewer.test.TestApp"
|
|
||||||
}
|
|
||||||
|
|
||||||
mainClassName = mainClass
|
|
||||||
|
|
||||||
version = "0.5.6"
|
|
||||||
|
|
||||||
description = "The viewer for numass data"
|
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
api project(':numass-core')
|
|
||||||
api project(':dataforge-plots:plots-jfc')
|
|
||||||
api project(':dataforge-gui')
|
|
||||||
}
|
|
||||||
|
|
42
numass-viewer/build.gradle.kts
Normal file
42
numass-viewer/build.gradle.kts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
id("org.openjfx.javafxplugin")
|
||||||
|
application
|
||||||
|
}
|
||||||
|
|
||||||
|
javafx {
|
||||||
|
modules = listOf("javafx.controls", "javafx.web")
|
||||||
|
version = "11"
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
mainClass.set("inr.numass.viewer.Viewer")
|
||||||
|
}
|
||||||
|
|
||||||
|
version = "0.6.0"
|
||||||
|
|
||||||
|
description = "The viewer for numass data"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":numass-core"))
|
||||||
|
api(project(":dataforge-plots:plots-jfc"))
|
||||||
|
api(project(":dataforge-gui"))
|
||||||
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
applicationDefaultJvmArgs = listOf(
|
||||||
|
"--add-exports=javafx.graphics/com.sun.glass.ui=ALL-UNNAMED",
|
||||||
|
"--add-opens=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED",
|
||||||
|
"--add-opens=javafx.graphics/com.sun.javafx.scene=ALL-UNNAMED",
|
||||||
|
"--add-opens=javafx.graphics/com.sun.javafx.scene.traversal=ALL-UNNAMED",
|
||||||
|
"--add-opens=javafx.graphics/javafx.scene=ALL-UNNAMED",
|
||||||
|
"--add-opens=javafx.controls/com.sun.javafx.scene.control=ALL-UNNAMED",
|
||||||
|
"--add-opens=javafx.controls/com.sun.javafx.scene.control.behavior=ALL-UNNAMED",
|
||||||
|
"--add-opens=javafx.controls/javafx.scene.control.skin=ALL-UNNAMED",
|
||||||
|
"--add-exports=javafx.controls/com.sun.javafx.scene.control.inputmap=ALL-UNNAMED",
|
||||||
|
)
|
||||||
|
}
|
@ -15,6 +15,7 @@ import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
|||||||
import hep.dataforge.tables.Adapters
|
import hep.dataforge.tables.Adapters
|
||||||
import inr.numass.data.analyzers.NumassAnalyzer
|
import inr.numass.data.analyzers.NumassAnalyzer
|
||||||
import inr.numass.data.analyzers.withBinning
|
import inr.numass.data.analyzers.withBinning
|
||||||
|
import inr.numass.data.api.NumassPoint
|
||||||
import javafx.beans.Observable
|
import javafx.beans.Observable
|
||||||
import javafx.beans.binding.DoubleBinding
|
import javafx.beans.binding.DoubleBinding
|
||||||
import javafx.beans.property.SimpleBooleanProperty
|
import javafx.beans.property.SimpleBooleanProperty
|
||||||
@ -28,6 +29,8 @@ import tornadofx.*
|
|||||||
|
|
||||||
class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = ImageView(dfIcon)) {
|
class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = ImageView(dfIcon)) {
|
||||||
|
|
||||||
|
private val pointCache by inject<PointCache>()
|
||||||
|
|
||||||
private val frame = JFreeChartFrame().configure {
|
private val frame = JFreeChartFrame().configure {
|
||||||
"title" to "Detector response plot"
|
"title" to "Detector response plot"
|
||||||
node("xAxis") {
|
node("xAxis") {
|
||||||
@ -70,7 +73,7 @@ class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = Imag
|
|||||||
addToSideBar(0, binningSelector, normalizeSwitch)
|
addToSideBar(0, binningSelector, normalizeSwitch)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val data: ObservableMap<String, CachedPoint> = FXCollections.observableHashMap()
|
private val data: ObservableMap<String, NumassPoint> = FXCollections.observableHashMap()
|
||||||
private val plots: ObservableMap<String, Goal<Plottable>> = FXCollections.observableHashMap()
|
private val plots: ObservableMap<String, Goal<Plottable>> = FXCollections.observableHashMap()
|
||||||
|
|
||||||
val isEmpty = booleanBinding(data) { isEmpty() }
|
val isEmpty = booleanBinding(data) { isEmpty() }
|
||||||
@ -113,16 +116,16 @@ class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = Imag
|
|||||||
/**
|
/**
|
||||||
* Put or replace current plot with name `key`
|
* Put or replace current plot with name `key`
|
||||||
*/
|
*/
|
||||||
operator fun set(key: String, point: CachedPoint) {
|
operator fun set(key: String, point: NumassPoint) {
|
||||||
data[key] = point
|
data[key] = point
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addAll(data: Map<String, CachedPoint>) {
|
fun addAll(data: Map<String, NumassPoint>) {
|
||||||
this.data.putAll(data);
|
this.data.putAll(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invalidate() {
|
private fun invalidate() {
|
||||||
data.forEach { key, point ->
|
data.forEach { (key, point) ->
|
||||||
plots.getOrPut(key) {
|
plots.getOrPut(key) {
|
||||||
runGoal<Plottable>("loadAmplitudeSpectrum_$key") {
|
runGoal<Plottable>("loadAmplitudeSpectrum_$key") {
|
||||||
val valueAxis = if (normalize) {
|
val valueAxis = if (normalize) {
|
||||||
@ -132,7 +135,7 @@ class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = Imag
|
|||||||
}
|
}
|
||||||
val adapter = Adapters.buildXYAdapter(NumassAnalyzer.CHANNEL_KEY, valueAxis)
|
val adapter = Adapters.buildXYAdapter(NumassAnalyzer.CHANNEL_KEY, valueAxis)
|
||||||
|
|
||||||
val channels = point.channelSpectra.await()
|
val channels = pointCache.getChannelSpectra(key, point)
|
||||||
|
|
||||||
return@runGoal if (channels.size == 1) {
|
return@runGoal if (channels.size == 1) {
|
||||||
DataPlot.plot(
|
DataPlot.plot(
|
||||||
@ -186,7 +189,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.
|
* Set frame content to the given map. All keys not in the map are removed.
|
||||||
*/
|
*/
|
||||||
fun setAll(map: Map<String, CachedPoint>) {
|
fun setAll(map: Map<String, NumassPoint>) {
|
||||||
plots.clear();
|
plots.clear();
|
||||||
//Remove obsolete keys
|
//Remove obsolete keys
|
||||||
data.keys.filter { !map.containsKey(it) }.forEach {
|
data.keys.filter { !map.containsKey(it) }.forEach {
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.CoroutineStart
|
|
||||||
import kotlinx.coroutines.Deferred
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.async
|
|
||||||
|
|
||||||
private val analyzer = SimpleAnalyzer()
|
|
||||||
|
|
||||||
|
|
||||||
class CachedPoint(val point: NumassPoint) : NumassPoint by point {
|
|
||||||
|
|
||||||
override val blocks: List<NumassBlock> by lazy { point.blocks }
|
|
||||||
|
|
||||||
override val meta: Meta = point.meta
|
|
||||||
|
|
||||||
val channelSpectra: Deferred<Map<Int, Table>> = GlobalScope.async(start = CoroutineStart.LAZY) {
|
|
||||||
point.channels.mapValues { (_, value) -> analyzer.getAmplitudeSpectrum(value) }
|
|
||||||
}
|
|
||||||
|
|
||||||
val spectrum: Deferred<Table> = GlobalScope.async(start = CoroutineStart.LAZY) { analyzer.getAmplitudeSpectrum(point) }
|
|
||||||
}
|
|
||||||
|
|
||||||
class CachedSet(set: NumassSet) : NumassSet by set {
|
|
||||||
override val points: List<CachedPoint> by lazy { set.points.map { CachedPoint(it) } }
|
|
||||||
}
|
|
@ -1,7 +1,5 @@
|
|||||||
package inr.numass.viewer
|
package inr.numass.viewer
|
||||||
|
|
||||||
import hep.dataforge.context.Context
|
|
||||||
import hep.dataforge.context.Global
|
|
||||||
import hep.dataforge.fx.dfIconView
|
import hep.dataforge.fx.dfIconView
|
||||||
import hep.dataforge.fx.except
|
import hep.dataforge.fx.except
|
||||||
import hep.dataforge.fx.runGoal
|
import hep.dataforge.fx.runGoal
|
||||||
@ -19,7 +17,6 @@ import javafx.scene.layout.Priority
|
|||||||
import javafx.scene.text.Font
|
import javafx.scene.text.Font
|
||||||
import javafx.stage.DirectoryChooser
|
import javafx.stage.DirectoryChooser
|
||||||
import javafx.stage.FileChooser
|
import javafx.stage.FileChooser
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.controlsfx.control.StatusBar
|
import org.controlsfx.control.StatusBar
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
@ -27,9 +24,11 @@ import java.io.File
|
|||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
class MainView(val context: Context = Global.getContext("viewer")) : View(title = "Numass viewer", icon = dfIconView) {
|
class MainView : View(title = "Numass viewer", icon = dfIconView) {
|
||||||
|
|
||||||
private val statusBar = StatusBar();
|
private val pointCache by inject<PointCache>()
|
||||||
|
|
||||||
|
private val statusBar = StatusBar()
|
||||||
// private val logFragment = LogFragment().apply {
|
// private val logFragment = LogFragment().apply {
|
||||||
// addLogHandler(context.logger)
|
// addLogHandler(context.logger)
|
||||||
// }
|
// }
|
||||||
@ -67,7 +66,7 @@ class MainView(val context: Context = Global.getContext("viewer")) : View(title
|
|||||||
|
|
||||||
if (rootDir != null) {
|
if (rootDir != null) {
|
||||||
NumassProperties.setNumassProperty("numass.viewer.lastPath", rootDir.absolutePath)
|
NumassProperties.setNumassProperty("numass.viewer.lastPath", rootDir.absolutePath)
|
||||||
GlobalScope.launch {
|
app.context.launch {
|
||||||
runLater {
|
runLater {
|
||||||
path = rootDir.toPath()
|
path = rootDir.toPath()
|
||||||
}
|
}
|
||||||
@ -95,8 +94,9 @@ class MainView(val context: Context = Global.getContext("viewer")) : View(title
|
|||||||
|
|
||||||
val file = chooser.showOpenDialog(primaryStage.scene.window)
|
val file = chooser.showOpenDialog(primaryStage.scene.window)
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
NumassProperties.setNumassProperty("numass.viewer.lastPath", file.parentFile.absolutePath)
|
NumassProperties.setNumassProperty("numass.viewer.lastPath",
|
||||||
GlobalScope.launch {
|
file.parentFile.absolutePath)
|
||||||
|
app.context.launch {
|
||||||
runLater {
|
runLater {
|
||||||
path = file.toPath()
|
path = file.toPath()
|
||||||
}
|
}
|
||||||
@ -111,8 +111,8 @@ class MainView(val context: Context = Global.getContext("viewer")) : View(title
|
|||||||
}
|
}
|
||||||
|
|
||||||
label(pathProperty.stringBinding { it?.toString() ?: "NOT LOADED" }) {
|
label(pathProperty.stringBinding { it?.toString() ?: "NOT LOADED" }) {
|
||||||
padding = Insets(0.0, 0.0, 0.0, 10.0);
|
padding = Insets(0.0, 0.0, 0.0, 10.0)
|
||||||
font = Font.font("System Bold", 13.0);
|
font = Font.font("System Bold", 13.0)
|
||||||
}
|
}
|
||||||
pane {
|
pane {
|
||||||
hgrow = Priority.ALWAYS
|
hgrow = Priority.ALWAYS
|
||||||
@ -136,17 +136,18 @@ class MainView(val context: Context = Global.getContext("viewer")) : View(title
|
|||||||
runLater {
|
runLater {
|
||||||
contentView = null
|
contentView = null
|
||||||
}
|
}
|
||||||
|
pointCache.clear()
|
||||||
if (Files.isDirectory(path)) {
|
if (Files.isDirectory(path)) {
|
||||||
if (Files.exists(path.resolve(NumassDataLoader.META_FRAGMENT_NAME))) {
|
if (Files.exists(path.resolve(NumassDataLoader.META_FRAGMENT_NAME))) {
|
||||||
//build set view
|
//build set view
|
||||||
runGoal("viewer.load.set[$path]") {
|
runGoal("viewer.load.set[$path]") {
|
||||||
title = "Load set ($path)"
|
title = "Load set ($path)"
|
||||||
message = "Building numass set..."
|
message = "Building numass set..."
|
||||||
NumassDataLoader(context, null, path.fileName.toString(), path)
|
NumassDataLoader(app.context, null, path.fileName.toString(), path)
|
||||||
} ui {
|
} ui { loader: NumassDataLoader ->
|
||||||
contentView = SpectrumView().apply {
|
contentView = SpectrumView().apply {
|
||||||
clear()
|
clear()
|
||||||
set(it.name, CachedSet(it))
|
set(loader.name, loader)
|
||||||
}
|
}
|
||||||
} except {
|
} except {
|
||||||
alert(
|
alert(
|
||||||
@ -160,7 +161,7 @@ class MainView(val context: Context = Global.getContext("viewer")) : View(title
|
|||||||
runGoal("viewer.load.storage[$path]") {
|
runGoal("viewer.load.storage[$path]") {
|
||||||
title = "Load storage ($path)"
|
title = "Load storage ($path)"
|
||||||
message = "Building numass storage tree..."
|
message = "Building numass storage tree..."
|
||||||
NumassDirectory.INSTANCE.read(context, path)
|
NumassDirectory.INSTANCE.read(app.context, path)
|
||||||
} ui {
|
} ui {
|
||||||
contentView = StorageView(it as Storage)
|
contentView = StorageView(it as Storage)
|
||||||
}
|
}
|
||||||
@ -186,7 +187,7 @@ class MainView(val context: Context = Global.getContext("viewer")) : View(title
|
|||||||
val point = NumassDataUtils.read(it)
|
val point = NumassDataUtils.read(it)
|
||||||
runLater {
|
runLater {
|
||||||
contentView = AmplitudeView().apply {
|
contentView = AmplitudeView().apply {
|
||||||
set(path.fileName.toString(), CachedPoint(point))
|
set(path.fileName.toString(), point)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* 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.tables.Table
|
||||||
|
import hep.dataforge.utils.Misc
|
||||||
|
import inr.numass.data.analyzers.SimpleAnalyzer
|
||||||
|
import inr.numass.data.api.NumassPoint
|
||||||
|
import kotlinx.coroutines.Deferred
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import tornadofx.*
|
||||||
|
|
||||||
|
|
||||||
|
private val analyzer = SimpleAnalyzer()
|
||||||
|
|
||||||
|
|
||||||
|
class PointCache : Controller() {
|
||||||
|
private val context = app.context
|
||||||
|
|
||||||
|
inner class CachedPoint(point: NumassPoint) {
|
||||||
|
val length = point.length
|
||||||
|
|
||||||
|
val voltage = point.voltage
|
||||||
|
|
||||||
|
val meta = point.meta
|
||||||
|
|
||||||
|
val channelSpectra: Deferred<Map<Int, Table>> = context.async(Dispatchers.IO) {
|
||||||
|
point.channels.mapValues { (_, value) -> analyzer.getAmplitudeSpectrum(value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val spectrum: Deferred<Table> = context.async(Dispatchers.IO) {
|
||||||
|
analyzer.getAmplitudeSpectrum(point)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val cache = Misc.getLRUCache<String, CachedPoint>(1000)
|
||||||
|
|
||||||
|
fun getCachedPoint(id: String,point: NumassPoint): CachedPoint = cache.getOrPut(id) { CachedPoint(point) }
|
||||||
|
|
||||||
|
fun getSpectrumAsync(id: String, point: NumassPoint): Deferred<Table> =
|
||||||
|
getCachedPoint(id, point).spectrum
|
||||||
|
|
||||||
|
suspend fun getChannelSpectra(id: String, point: NumassPoint): Map<Int, Table> =
|
||||||
|
getCachedPoint(id, point).channelSpectra.await()
|
||||||
|
|
||||||
|
fun clear(){
|
||||||
|
cache.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//class CachedSet(set: NumassSet, context: Context) {
|
||||||
|
// override val points: ObservableList<CachedPoint> by lazy {
|
||||||
|
// set.points.map { CachedPoint(it, context) }.toObservable()
|
||||||
|
// }
|
||||||
|
// init {
|
||||||
|
// var watcher: WatchService? = null
|
||||||
|
//
|
||||||
|
// if (set is NumassDataLoader) {
|
||||||
|
// context.launch(Dispatchers.IO) {
|
||||||
|
// watcher = set.path.fileSystem.newWatchService()
|
||||||
|
// try {
|
||||||
|
// val key: WatchKey = set.path.register(watcher!!, ENTRY_CREATE)
|
||||||
|
// while (true) {
|
||||||
|
// key.pollEvents().forEach { event ->
|
||||||
|
// if (event.kind() == ENTRY_CREATE) {
|
||||||
|
// val path: Path = event.context() as Path
|
||||||
|
// if (path.fileName.toString().startsWith(NumassDataLoader.POINT_FRAGMENT_NAME)) {
|
||||||
|
// val envelope: Envelope = NumassEnvelopeType.infer(path)?.reader?.read(path)
|
||||||
|
// ?: kotlin.error("Can't read point file")
|
||||||
|
// val point = NumassDataUtils.read(envelope)
|
||||||
|
// points.add(CachedPoint(point, context))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } catch (x: IOException) {
|
||||||
|
// x.printStackTrace()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
@ -3,15 +3,13 @@ package inr.numass.viewer
|
|||||||
import hep.dataforge.fx.meta.MetaViewer
|
import hep.dataforge.fx.meta.MetaViewer
|
||||||
import inr.numass.data.analyzers.NumassAnalyzer
|
import inr.numass.data.analyzers.NumassAnalyzer
|
||||||
import javafx.beans.property.SimpleIntegerProperty
|
import javafx.beans.property.SimpleIntegerProperty
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.controlsfx.glyphfont.FontAwesome
|
import org.controlsfx.glyphfont.FontAwesome
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import tornadofx.controlsfx.borders
|
import tornadofx.controlsfx.borders
|
||||||
import tornadofx.controlsfx.toGlyph
|
import tornadofx.controlsfx.toGlyph
|
||||||
|
|
||||||
class PointInfoView(val point: CachedPoint) : MetaViewer(point.meta) {
|
class PointInfoView(val cachedPoint: PointCache.CachedPoint) : MetaViewer(cachedPoint.meta) {
|
||||||
|
|
||||||
val countProperty = SimpleIntegerProperty(0)
|
val countProperty = SimpleIntegerProperty(0)
|
||||||
var count by countProperty
|
var count by countProperty
|
||||||
|
|
||||||
@ -25,8 +23,10 @@ class PointInfoView(val point: CachedPoint) : MetaViewer(point.meta) {
|
|||||||
row {
|
row {
|
||||||
button(graphic = FontAwesome.Glyph.REFRESH.toGlyph()) {
|
button(graphic = FontAwesome.Glyph.REFRESH.toGlyph()) {
|
||||||
action {
|
action {
|
||||||
GlobalScope.launch {
|
app.context.launch {
|
||||||
val res = point.spectrum.await().sumOf { it.getValue(NumassAnalyzer.COUNT_KEY).int }
|
val res = cachedPoint.spectrum.await().sumOf {
|
||||||
|
it.getValue(NumassAnalyzer.COUNT_KEY).int
|
||||||
|
}
|
||||||
runLater { count = res }
|
runLater { count = res }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,7 +44,10 @@ class PointInfoView(val point: CachedPoint) : MetaViewer(point.meta) {
|
|||||||
hbox {
|
hbox {
|
||||||
label("Total count rate: ")
|
label("Total count rate: ")
|
||||||
label {
|
label {
|
||||||
textProperty().bind(countProperty.stringBinding { String.format("%.2f", it!!.toDouble() / point.length.toMillis() * 1000) })
|
textProperty().bind(countProperty.stringBinding {
|
||||||
|
String.format("%.2f",
|
||||||
|
it!!.toDouble() / cachedPoint.length.toMillis() * 1000)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import hep.dataforge.names.Name
|
|||||||
import hep.dataforge.plots.data.DataPlot
|
import hep.dataforge.plots.data.DataPlot
|
||||||
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
||||||
import hep.dataforge.tables.Adapters
|
import hep.dataforge.tables.Adapters
|
||||||
|
import hep.dataforge.values.Values
|
||||||
import inr.numass.data.analyzers.countInWindow
|
import inr.numass.data.analyzers.countInWindow
|
||||||
import inr.numass.data.api.NumassSet
|
import inr.numass.data.api.NumassSet
|
||||||
import javafx.beans.property.SimpleIntegerProperty
|
import javafx.beans.property.SimpleIntegerProperty
|
||||||
@ -22,6 +23,7 @@ import javafx.util.converter.NumberStringConverter
|
|||||||
import org.controlsfx.control.RangeSlider
|
import org.controlsfx.control.RangeSlider
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View for energy spectrum
|
* View for energy spectrum
|
||||||
@ -30,6 +32,8 @@ import java.util.concurrent.atomic.AtomicInteger
|
|||||||
*/
|
*/
|
||||||
class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIcon)) {
|
class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIcon)) {
|
||||||
|
|
||||||
|
private val pointCache by inject<PointCache>()
|
||||||
|
|
||||||
private val frame = JFreeChartFrame().configure {
|
private val frame = JFreeChartFrame().configure {
|
||||||
"xAxis.title" to "U"
|
"xAxis.title" to "U"
|
||||||
"xAxis.units" to "V"
|
"xAxis.units" to "V"
|
||||||
@ -37,7 +41,7 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco
|
|||||||
"yAxis.units" to "Hz"
|
"yAxis.units" to "Hz"
|
||||||
//"legend.show" to false
|
//"legend.show" to false
|
||||||
}
|
}
|
||||||
private val container = PlotContainer(frame);
|
private val container = PlotContainer(frame)
|
||||||
|
|
||||||
|
|
||||||
private val loChannelProperty = SimpleIntegerProperty(500).apply {
|
private val loChannelProperty = SimpleIntegerProperty(500).apply {
|
||||||
@ -51,7 +55,7 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco
|
|||||||
private var upChannel by upChannelProperty
|
private var upChannel by upChannelProperty
|
||||||
|
|
||||||
|
|
||||||
private val data: ObservableMap<String, CachedSet> = FXCollections.observableHashMap();
|
private val data: ObservableMap<String, NumassSet> = FXCollections.observableHashMap()
|
||||||
val isEmpty = booleanBinding(data) { data.isEmpty() }
|
val isEmpty = booleanBinding(data) { data.isEmpty() }
|
||||||
|
|
||||||
override val root = borderpane {
|
override val root = borderpane {
|
||||||
@ -86,7 +90,7 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco
|
|||||||
vbox {
|
vbox {
|
||||||
label("Up channel")
|
label("Up channel")
|
||||||
textfield {
|
textfield {
|
||||||
isEditable = true;
|
isEditable = true
|
||||||
prefWidth = 60.0
|
prefWidth = 60.0
|
||||||
textProperty().bindBidirectional(upChannelProperty, NumberStringConverter())
|
textProperty().bindBidirectional(upChannelProperty, NumberStringConverter())
|
||||||
}
|
}
|
||||||
@ -100,7 +104,7 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco
|
|||||||
init {
|
init {
|
||||||
data.addListener { change: MapChangeListener.Change<out String, out NumassSet> ->
|
data.addListener { change: MapChangeListener.Change<out String, out NumassSet> ->
|
||||||
if (change.wasRemoved()) {
|
if (change.wasRemoved()) {
|
||||||
frame.plots.remove(Name.ofSingle(change.key));
|
frame.plots.remove(Name.ofSingle(change.key))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.wasAdded()) {
|
if (change.wasAdded()) {
|
||||||
@ -115,24 +119,26 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco
|
|||||||
val progress = AtomicInteger(0)
|
val progress = AtomicInteger(0)
|
||||||
val totalProgress = data.values.stream().mapToInt { it.points.size }.sum()
|
val totalProgress = data.values.stream().mapToInt { it.points.size }.sum()
|
||||||
|
|
||||||
data.forEach { name, set ->
|
data.forEach { (name, set) ->
|
||||||
val plot: DataPlot = frame.plots[Name.ofSingle(name)] as DataPlot? ?: DataPlot(name).apply { frame.add(this) }
|
val plot: DataPlot =
|
||||||
|
frame.plots[Name.ofSingle(name)] as DataPlot? ?: DataPlot(name).apply { frame.add(this) }
|
||||||
|
|
||||||
runGoal("spectrumData[$name]") {
|
runGoal("spectrumData[$name]") {
|
||||||
set.points.forEach { it.spectrum.start() }
|
set.points.map {
|
||||||
set.points.map { point ->
|
pointCache.getCachedPoint("$name/${it.voltage}[${it.index}]", it)
|
||||||
val count = point.spectrum.await().countInWindow(loChannel.toShort(), upChannel.toShort());
|
}.map { cachedPoint ->
|
||||||
val seconds = point.length.toMillis() / 1000.0;
|
val count = cachedPoint.spectrum.await().countInWindow(loChannel.toShort(), upChannel.toShort())
|
||||||
|
val seconds = cachedPoint.length.toMillis() / 1000.0
|
||||||
runLater {
|
runLater {
|
||||||
container.progress = progress.incrementAndGet().toDouble() / totalProgress
|
container.progress = progress.incrementAndGet().toDouble() / totalProgress
|
||||||
}
|
}
|
||||||
Adapters.buildXYDataPoint(
|
Adapters.buildXYDataPoint(
|
||||||
point.voltage,
|
cachedPoint.voltage,
|
||||||
(count / seconds),
|
(count / seconds),
|
||||||
Math.sqrt(count.toDouble()) / seconds
|
sqrt(count.toDouble()) / seconds
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} ui { points ->
|
} ui { points: List<Values> ->
|
||||||
plot.fillData(points)
|
plot.fillData(points)
|
||||||
container.progress = 1.0
|
container.progress = 1.0
|
||||||
//spectrumExportButton.isDisable = false
|
//spectrumExportButton.isDisable = false
|
||||||
@ -140,7 +146,7 @@ class SpectrumView : View(title = "Numass spectrum plot", icon = ImageView(dfIco
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun set(key: String, value: CachedSet) {
|
operator fun set(key: String, value: NumassSet) {
|
||||||
data[key] = value
|
data[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,13 +12,16 @@ import inr.numass.data.api.NumassPoint
|
|||||||
import inr.numass.data.api.NumassSet
|
import inr.numass.data.api.NumassSet
|
||||||
import inr.numass.data.storage.NumassDataLoader
|
import inr.numass.data.storage.NumassDataLoader
|
||||||
import javafx.beans.property.SimpleBooleanProperty
|
import javafx.beans.property.SimpleBooleanProperty
|
||||||
|
import javafx.collections.ObservableList
|
||||||
import javafx.scene.control.ContextMenu
|
import javafx.scene.control.ContextMenu
|
||||||
import javafx.scene.control.TreeItem
|
import javafx.scene.control.TreeItem
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
|
|
||||||
class StorageView(val storage: Storage) : View(title = "Numass storage", icon = dfIconView) {
|
class StorageView(val storage: Storage) : View(title = "Numass storage", icon = dfIconView) {
|
||||||
|
|
||||||
|
private val pointCache by inject<PointCache>()
|
||||||
|
|
||||||
private val ampView: AmplitudeView by inject()
|
private val ampView: AmplitudeView by inject()
|
||||||
private val timeView: TimeView by inject()
|
private val timeView: TimeView by inject()
|
||||||
private val spectrumView: SpectrumView by inject()
|
private val spectrumView: SpectrumView by inject()
|
||||||
@ -39,7 +42,7 @@ class StorageView(val storage: Storage) : View(title = "Numass storage", icon =
|
|||||||
|
|
||||||
val infoView: UIComponent by lazy {
|
val infoView: UIComponent by lazy {
|
||||||
when (content) {
|
when (content) {
|
||||||
is CachedPoint -> PointInfoView(content)
|
is NumassPoint -> PointInfoView(pointCache.getCachedPoint(id, content))
|
||||||
is Metoid -> MetaViewer(content.meta, title = "Meta view: $id")
|
is Metoid -> MetaViewer(content.meta, title = "Meta view: $id")
|
||||||
else -> MetaViewer(Meta.empty(), title = "Meta view: $id")
|
else -> MetaViewer(Meta.empty(), title = "Meta view: $id")
|
||||||
}
|
}
|
||||||
@ -48,7 +51,7 @@ class StorageView(val storage: Storage) : View(title = "Numass storage", icon =
|
|||||||
init {
|
init {
|
||||||
checkedProperty.onChange { selected ->
|
checkedProperty.onChange { selected ->
|
||||||
when (content) {
|
when (content) {
|
||||||
is CachedPoint -> {
|
is NumassPoint -> {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
ampView[id] = content
|
ampView[id] = content
|
||||||
timeView[id] = content
|
timeView[id] = content
|
||||||
@ -57,7 +60,7 @@ class StorageView(val storage: Storage) : View(title = "Numass storage", icon =
|
|||||||
timeView.remove(id)
|
timeView.remove(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is CachedSet -> {
|
is NumassSet -> {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
spectrumView[id] = content
|
spectrumView[id] = content
|
||||||
hvView[id] = content
|
hvView[id] = content
|
||||||
@ -77,21 +80,17 @@ class StorageView(val storage: Storage) : View(title = "Numass storage", icon =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val children: List<Container>? by lazy {
|
fun getChildren(): ObservableList<Container>? = when (content) {
|
||||||
when (content) {
|
is Storage -> content.children.map {
|
||||||
is Storage -> runBlocking { content.children }.map { buildContainer(it, this) }.sortedWith(
|
buildContainer(it, this)
|
||||||
object : Comparator<Container> {
|
}.sortedWith(Comparator.comparing({ it.id }, AlphanumComparator)).asObservable()
|
||||||
private val alphanumComparator = AlphanumComparator()
|
|
||||||
override fun compare(o1: Container, o2: Container): Int = alphanumComparator.compare(o1.id, o2.id)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
is NumassSet -> content.points
|
is NumassSet -> content.points
|
||||||
.sortedBy { it.index }
|
.sortedBy { it.index }
|
||||||
.map { buildContainer(it, this) }
|
.map { buildContainer(it, this) }
|
||||||
.toList()
|
.asObservable()
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val hasChildren: Boolean = (content is Storage) || (content is NumassSet)
|
val hasChildren: Boolean = (content is Storage) || (content is NumassSet)
|
||||||
}
|
}
|
||||||
@ -102,10 +101,12 @@ class StorageView(val storage: Storage) : View(title = "Numass storage", icon =
|
|||||||
//isShowRoot = false
|
//isShowRoot = false
|
||||||
root = TreeItem(Container(storage.name, storage))
|
root = TreeItem(Container(storage.name, storage))
|
||||||
root.isExpanded = true
|
root.isExpanded = true
|
||||||
lazyPopulate(leafCheck = { !it.value.hasChildren }) {
|
lazyPopulate(leafCheck = {
|
||||||
it.value.children
|
!it.value.hasChildren
|
||||||
|
}) {
|
||||||
|
it.value.getChildren()
|
||||||
}
|
}
|
||||||
cellFormat { value ->
|
cellFormat { value: Container ->
|
||||||
when (value.content) {
|
when (value.content) {
|
||||||
is Storage -> {
|
is Storage -> {
|
||||||
text = value.content.name
|
text = value.content.name
|
||||||
@ -188,24 +189,19 @@ class StorageView(val storage: Storage) : View(title = "Numass storage", icon =
|
|||||||
|
|
||||||
private fun buildContainer(content: Any, parent: Container): Container =
|
private fun buildContainer(content: Any, parent: Container): Container =
|
||||||
when (content) {
|
when (content) {
|
||||||
is Storage -> {
|
is Storage -> Container(content.fullName.toString(), content)
|
||||||
Container(content.fullName.toString(), content)
|
|
||||||
}
|
|
||||||
is NumassSet -> {
|
is NumassSet -> {
|
||||||
val id: String = if (content is NumassDataLoader) {
|
val id: String = if (content is NumassDataLoader) {
|
||||||
content.fullName.unescaped
|
content.fullName.unescaped
|
||||||
} else {
|
} else {
|
||||||
content.name
|
content.name
|
||||||
}
|
}
|
||||||
Container(id, content as? CachedSet ?: CachedSet(content))
|
Container(id, content)
|
||||||
}
|
}
|
||||||
is NumassPoint -> {
|
is NumassPoint -> {
|
||||||
Container("${parent.id}/${content.voltage}[${content.index}]", content as? CachedPoint
|
Container("${parent.id}/${content.voltage}[${content.index}]", content)
|
||||||
?: CachedPoint(content))
|
|
||||||
}
|
|
||||||
is FileTableLoader -> {
|
|
||||||
Container(content.path.toString(), content);
|
|
||||||
}
|
}
|
||||||
|
is FileTableLoader -> Container(content.path.toString(), content)
|
||||||
else -> throw IllegalArgumentException("Unknown content type: ${content::class.java}");
|
else -> throw IllegalArgumentException("Unknown content type: ${content::class.java}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
|||||||
import hep.dataforge.tables.Adapters
|
import hep.dataforge.tables.Adapters
|
||||||
import hep.dataforge.values.ValueMap
|
import hep.dataforge.values.ValueMap
|
||||||
import inr.numass.data.analyzers.TimeAnalyzer
|
import inr.numass.data.analyzers.TimeAnalyzer
|
||||||
|
import inr.numass.data.api.NumassPoint
|
||||||
import javafx.beans.Observable
|
import javafx.beans.Observable
|
||||||
import javafx.beans.binding.DoubleBinding
|
import javafx.beans.binding.DoubleBinding
|
||||||
import javafx.collections.FXCollections
|
import javafx.collections.FXCollections
|
||||||
@ -59,7 +60,7 @@ class TimeView : View(title = "Numass time spectrum plot", icon = ImageView(dfIc
|
|||||||
|
|
||||||
private val container = PlotContainer(frame)
|
private val container = PlotContainer(frame)
|
||||||
|
|
||||||
private val data: ObservableMap<String, CachedPoint> = FXCollections.observableHashMap()
|
private val data: ObservableMap<String, NumassPoint> = FXCollections.observableHashMap()
|
||||||
private val plots: ObservableMap<String, Goal<Plottable>> = FXCollections.observableHashMap()
|
private val plots: ObservableMap<String, Goal<Plottable>> = FXCollections.observableHashMap()
|
||||||
|
|
||||||
val isEmpty = booleanBinding(data) { isEmpty() }
|
val isEmpty = booleanBinding(data) { isEmpty() }
|
||||||
@ -88,11 +89,11 @@ class TimeView : View(title = "Numass time spectrum plot", icon = ImageView(dfIc
|
|||||||
/**
|
/**
|
||||||
* Put or replace current plot with name `key`
|
* Put or replace current plot with name `key`
|
||||||
*/
|
*/
|
||||||
operator fun set(key: String, point: CachedPoint) {
|
operator fun set(key: String, point: NumassPoint) {
|
||||||
data[key] = point
|
data[key] = point
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addAll(data: Map<String, CachedPoint>) {
|
fun addAll(data: Map<String, NumassPoint>) {
|
||||||
this.data.putAll(data);
|
this.data.putAll(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +161,7 @@ class TimeView : View(title = "Numass time spectrum plot", icon = ImageView(dfIc
|
|||||||
/**
|
/**
|
||||||
* Set frame content to the given map. All keys not in the map are removed.
|
* Set frame content to the given map. All keys not in the map are removed.
|
||||||
*/
|
*/
|
||||||
fun setAll(map: Map<String, CachedPoint>) {
|
fun setAll(map: Map<String, NumassPoint>) {
|
||||||
plots.clear();
|
plots.clear();
|
||||||
//Remove obsolete keys
|
//Remove obsolete keys
|
||||||
data.keys.filter { !map.containsKey(it) }.forEach {
|
data.keys.filter { !map.containsKey(it) }.forEach {
|
||||||
|
@ -2,6 +2,7 @@ package inr.numass.viewer
|
|||||||
|
|
||||||
import ch.qos.logback.classic.Level
|
import ch.qos.logback.classic.Level
|
||||||
import ch.qos.logback.classic.Logger
|
import ch.qos.logback.classic.Logger
|
||||||
|
import hep.dataforge.context.Context
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.fx.dfIcon
|
import hep.dataforge.fx.dfIcon
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
@ -16,13 +17,18 @@ class Viewer : App(MainView::class) {
|
|||||||
(LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as Logger).level = Level.INFO
|
(LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as Logger).level = Level.INFO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val context: Context = Global.getContext("numass-viewer")
|
||||||
|
|
||||||
override fun start(stage: Stage) {
|
override fun start(stage: Stage) {
|
||||||
stage.icons += dfIcon
|
|
||||||
super.start(stage)
|
super.start(stage)
|
||||||
|
stage.icons += dfIcon
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
super.stop()
|
context.close()
|
||||||
Global.terminate();
|
Global.terminate();
|
||||||
|
super.stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val App.context get() = (this as Viewer).context
|
@ -7,10 +7,11 @@ import hep.dataforge.tables.Table
|
|||||||
import inr.numass.data.api.NumassPoint
|
import inr.numass.data.api.NumassPoint
|
||||||
import inr.numass.data.api.NumassSet
|
import inr.numass.data.api.NumassSet
|
||||||
import inr.numass.data.storage.NumassDirectory
|
import inr.numass.data.storage.NumassDirectory
|
||||||
import inr.numass.viewer.*
|
import inr.numass.viewer.AmplitudeView
|
||||||
|
import inr.numass.viewer.HVView
|
||||||
|
import inr.numass.viewer.SpectrumView
|
||||||
import javafx.application.Application
|
import javafx.application.Application
|
||||||
import javafx.scene.image.ImageView
|
import javafx.scene.image.ImageView
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -25,7 +26,8 @@ class ViewerComponentsTest : View(title = "Numass viewer test", icon = ImageView
|
|||||||
//val set: NumassSet = NumassStorageFactory.buildLocal(rootDir).provide("loader::set_8", NumassSet::class.java).orElseThrow { RuntimeException("err") }
|
//val set: NumassSet = NumassStorageFactory.buildLocal(rootDir).provide("loader::set_8", NumassSet::class.java).orElseThrow { RuntimeException("err") }
|
||||||
|
|
||||||
|
|
||||||
private val cache: MutableMap<NumassPoint, Table> = ConcurrentHashMap();
|
private val cache: MutableMap<NumassPoint, Table> = ConcurrentHashMap()
|
||||||
|
val context = Global
|
||||||
|
|
||||||
val amp: AmplitudeView by inject(params = mapOf("cache" to cache))//= AmplitudeView(immutable = immutable)
|
val amp: AmplitudeView by inject(params = mapOf("cache" to cache))//= AmplitudeView(immutable = immutable)
|
||||||
val sp: SpectrumView by inject(params = mapOf("cache" to cache))
|
val sp: SpectrumView by inject(params = mapOf("cache" to cache))
|
||||||
@ -35,11 +37,11 @@ class ViewerComponentsTest : View(title = "Numass viewer test", icon = ImageView
|
|||||||
top {
|
top {
|
||||||
button("Click me!") {
|
button("Click me!") {
|
||||||
action {
|
action {
|
||||||
GlobalScope.launch {
|
context.launch {
|
||||||
val set: NumassSet = NumassDirectory.INSTANCE.read(Global, File("D:\\Work\\Numass\\data\\2017_05\\Fill_2").toPath())
|
val set: NumassSet = NumassDirectory.INSTANCE.read(Global, File("D:\\Work\\Numass\\data\\2017_05\\Fill_2").toPath())
|
||||||
?.provide("loader::set_2", NumassSet::class.java).nullable
|
?.provide("loader::set_2", NumassSet::class.java).nullable
|
||||||
?: kotlin.error("Error")
|
?: kotlin.error("Error")
|
||||||
update(set);
|
update(set)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,13 +56,13 @@ class ViewerComponentsTest : View(title = "Numass viewer test", icon = ImageView
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun update(set: NumassSet) {
|
fun update(set: NumassSet) {
|
||||||
amp.setAll(set.points.filter { it.voltage != 16000.0 }.associateBy({ "point_${it.voltage}" }) { CachedPoint(it) });
|
amp.setAll(set.points.filter { it.voltage != 16000.0 }.associateBy { "point_${it.voltage}" })
|
||||||
sp.set("test", CachedSet(set));
|
sp["test"] = set
|
||||||
hv.set(set.name, set)
|
hv[set.name] = set
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
Application.launch(ViewerComponentsTestApp::class.java, *args);
|
Application.launch(ViewerComponentsTestApp::class.java, *args)
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user