Compare commits
10 Commits
93c43d9ebd
...
aa25ca5674
Author | SHA1 | Date | |
---|---|---|---|
aa25ca5674 | |||
e549bad998 | |||
ee18f68928 | |||
28b7969709 | |||
5b170da7d4 | |||
84998bce6d | |||
b25c1dd0eb | |||
12114ffab3 | |||
1881c3419e | |||
3e1e78c45a |
11
build.gradle
11
build.gradle
@ -1,5 +1,5 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = "1.3.10"
|
ext.kotlin_version = "1.3.50"
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
@ -9,10 +9,15 @@ buildscript {
|
|||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugins{
|
||||||
|
id 'org.openjfx.javafxplugin' version '0.0.8' apply false
|
||||||
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
apply plugin: "kotlin"
|
apply plugin: "org.jetbrains.kotlin.jvm"
|
||||||
|
|
||||||
group = 'inr.numass'
|
group = 'inr.numass'
|
||||||
version = '1.0.0'
|
version = '1.0.0'
|
||||||
@ -33,8 +38,6 @@ allprojects {
|
|||||||
testImplementation group: 'junit', name: 'junit', version: '4.+'
|
testImplementation group: 'junit', name: 'junit', version: '4.+'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
compileKotlin {
|
compileKotlin {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,5 @@
|
|||||||
#Fri Jun 16 20:54:50 MSK 2017
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.0-bin.zip
|
|
||||||
|
57
gradlew
vendored
57
gradlew
vendored
@ -1,5 +1,21 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015 the original author or authors.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
#
|
||||||
|
# https://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.
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
##
|
||||||
## Gradle start up script for UN*X
|
## Gradle start up script for UN*X
|
||||||
@ -28,16 +44,16 @@ APP_NAME="Gradle"
|
|||||||
APP_BASE_NAME=`basename "$0"`
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
DEFAULT_JVM_OPTS=""
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD="maximum"
|
||||||
|
|
||||||
warn ( ) {
|
warn () {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
}
|
}
|
||||||
|
|
||||||
die ( ) {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
@ -109,8 +125,8 @@ if $darwin; then
|
|||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
if $cygwin ; then
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
@ -138,35 +154,30 @@ if $cygwin ; then
|
|||||||
else
|
else
|
||||||
eval `echo args$i`="\"$arg\""
|
eval `echo args$i`="\"$arg\""
|
||||||
fi
|
fi
|
||||||
i=$((i+1))
|
i=`expr $i + 1`
|
||||||
done
|
done
|
||||||
case $i in
|
case $i in
|
||||||
(0) set -- ;;
|
0) set -- ;;
|
||||||
(1) set -- "$args0" ;;
|
1) set -- "$args0" ;;
|
||||||
(2) set -- "$args0" "$args1" ;;
|
2) set -- "$args0" "$args1" ;;
|
||||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Escape application args
|
# Escape application args
|
||||||
save ( ) {
|
save () {
|
||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
echo " "
|
echo " "
|
||||||
}
|
}
|
||||||
APP_ARGS=$(save "$@")
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
|
||||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
18
gradlew.bat
vendored
18
gradlew.bat
vendored
@ -1,3 +1,19 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%" == "" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0
|
|||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS=
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
allprojects {
|
allprojects {
|
||||||
apply plugin: "kotlin"
|
apply plugin: "kotlin"
|
||||||
|
|
||||||
|
// apply plugin: 'org.openjfx.javafxplugin'
|
||||||
|
//
|
||||||
|
// javafx {
|
||||||
|
// modules = [ 'javafx.controls' ]
|
||||||
|
// }
|
||||||
|
|
||||||
compileKotlin {
|
compileKotlin {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
|
@ -18,12 +18,9 @@ import java.util.function.Supplier
|
|||||||
/**
|
/**
|
||||||
* @author Alexander Nozik
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
class PKT8VirtualPort(private val portName: String, meta: Meta) : VirtualPort(meta), Metoid {
|
class PKT8VirtualPort(override val name: String, meta: Meta) : VirtualPort(meta), Metoid {
|
||||||
|
|
||||||
private val generator = Random()
|
private val generator = Random()
|
||||||
|
|
||||||
override val name: String = portName
|
|
||||||
|
|
||||||
@Synchronized override fun evaluateRequest(request: String) {
|
@Synchronized override fun evaluateRequest(request: String) {
|
||||||
when (request) {
|
when (request) {
|
||||||
"s" -> {
|
"s" -> {
|
||||||
@ -59,6 +56,11 @@ class PKT8VirtualPort(private val portName: String, meta: Meta) : VirtualPort(me
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toMeta(): Meta {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
override fun close() {
|
override fun close() {
|
||||||
cancelByTag("measurement")
|
cancelByTag("measurement")
|
||||||
|
@ -1,26 +1,15 @@
|
|||||||
/*
|
//
|
||||||
* Copyright 2018 Alexander Nozik.
|
//plugins {
|
||||||
*
|
// id 'application'
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
// id 'org.openjfx.javafxplugin' version '0.0.5'
|
||||||
* you may not use this file except in compliance with the License.
|
//}
|
||||||
* You may obtain a copy of the License at
|
//
|
||||||
*
|
//javafx {
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
// modules = [ 'javafx.controls' ]
|
||||||
*
|
//}
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'application'
|
id 'application'
|
||||||
id 'org.openjfx.javafxplugin' version '0.0.5'
|
|
||||||
}
|
|
||||||
|
|
||||||
javafx {
|
|
||||||
modules = [ 'javafx.controls' ]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -9,11 +9,9 @@ import java.text.DecimalFormat
|
|||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
|
||||||
//@ValueDef(name = "timeout", type = [(ValueType.NUMBER)], def = "400", info = "A timeout for port response")
|
//@ValueDef(name = "timeout", type = [(ValueType.NUMBER)], def = "400", info = "A timeout for port response")
|
||||||
class LambdaPortController(context: Context, port: Port) : GenericPortController(context, port, "\r") {
|
class LambdaPortController(context: Context, port: Port, val timeout : Duration = Duration.ofMillis(200)) : GenericPortController(context, port, "\r") {
|
||||||
private var currentAddress: Int = -1;
|
private var currentAddress: Int = -1;
|
||||||
|
|
||||||
private val timeout: Duration = port.meta.optString("timeout").map<Duration> { Duration.parse(it) }.orElse(Duration.ofMillis(200))
|
|
||||||
|
|
||||||
fun setAddress(address: Int) {
|
fun setAddress(address: Int) {
|
||||||
if(currentAddress!= address) {
|
if(currentAddress!= address) {
|
||||||
val response = sendAndWait("ADR $address\r", timeout) { true }.trim()
|
val response = sendAndWait("ADR $address\r", timeout) { true }.trim()
|
||||||
|
@ -27,7 +27,6 @@ import java.util.*
|
|||||||
* @author Alexander Nozik
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
class VirtualLambdaPort(meta: Meta) : VirtualPort(meta) {
|
class VirtualLambdaPort(meta: Meta) : VirtualPort(meta) {
|
||||||
|
|
||||||
var currentAddress = -1
|
var currentAddress = -1
|
||||||
private set
|
private set
|
||||||
|
|
||||||
@ -135,6 +134,11 @@ class VirtualLambdaPort(meta: Meta) : VirtualPort(meta) {
|
|||||||
val voltage get() = current * resistance
|
val voltage get() = current * resistance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toMeta(): Meta {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val latency = Duration.ofMillis(50)
|
private val latency = Duration.ofMillis(50)
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,7 @@ abstract class DeviceDisplayFX<D : Device> : Component(), Connection {
|
|||||||
* Default display shows only board pane and nothing else
|
* Default display shows only board pane and nothing else
|
||||||
*/
|
*/
|
||||||
class DefaultDisplay : DeviceDisplayFX<Device>() {
|
class DefaultDisplay : DeviceDisplayFX<Device>() {
|
||||||
|
|
||||||
override fun buildView(device: Device): UIComponent? = null
|
override fun buildView(device: Device): UIComponent? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
apply plugin: 'application'
|
apply plugin: 'application'
|
||||||
|
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
if (!hasProperty('mainClass')) {
|
if (!hasProperty('mainClass')) {
|
||||||
ext.mainClass = 'inr.numass.control.readvac.ReadVac'
|
ext.mainClass = 'inr.numass.control.readvac.ReadVac'
|
||||||
|
@ -27,10 +27,7 @@ class MKSBaratronDevice(context: Context, meta: Meta) : PortSensor(context, meta
|
|||||||
|
|
||||||
var channel by valueState("channel").intDelegate
|
var channel by valueState("channel").intDelegate
|
||||||
|
|
||||||
override val type: String
|
override val type: String get() = meta.getString("type", "numass.vac.baratron")
|
||||||
get() {
|
|
||||||
return meta.getString("type", "numass.vac.baratron")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun buildConnection(meta: Meta): GenericPortController {
|
override fun buildConnection(meta: Meta): GenericPortController {
|
||||||
val port: Port = PortFactory.build(meta)
|
val port: Port = PortFactory.build(meta)
|
||||||
|
@ -22,7 +22,11 @@ class ReadVac : NumassControlApplication<VacCollectorDevice>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getDeviceMeta(config: Meta): Meta {
|
override fun getDeviceMeta(config: Meta): Meta {
|
||||||
return MetaUtils.findNode(config,"device"){it.getString("name") == "numass.vac"}.orElseThrow{RuntimeException("Vacuum measurement configuration not found")}
|
return MetaUtils.findNode(config, "device") {
|
||||||
|
it.getString("type") == "numass:vac"
|
||||||
|
}.orElseThrow {
|
||||||
|
RuntimeException("Vacuum measurement configuration not found")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
package inr.numass.control.readvac
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
import hep.dataforge.control.devices.PortSensor
|
||||||
|
import hep.dataforge.control.ports.GenericPortController
|
||||||
|
import hep.dataforge.control.ports.Port
|
||||||
|
import hep.dataforge.control.ports.PortFactory
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import inr.numass.control.DeviceView
|
||||||
|
|
||||||
|
//@ValueDef(key = "address")
|
||||||
|
@DeviceView(VacDisplay::class)
|
||||||
|
//@StateDef(value = ValueDef(key = "address", type = [ValueType.STRING], def = "001"))
|
||||||
|
class ThyroContVacDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
|
||||||
|
//val address by valueState("address").stringDelegate
|
||||||
|
val address = "001"
|
||||||
|
|
||||||
|
override val type: String get() = meta.getString("type", "numass.vac.thyrocont")
|
||||||
|
|
||||||
|
override fun buildConnection(meta: Meta): GenericPortController {
|
||||||
|
val port: Port = PortFactory.build(meta)
|
||||||
|
logger.info("Connecting to port {}", port.name)
|
||||||
|
return GenericPortController(context, port) { it.endsWith("\r") }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.checksum(): Char = (sumBy { it.toInt() } % 64 + 64).toChar()
|
||||||
|
|
||||||
|
private fun wrap(str: String): String = buildString {
|
||||||
|
append(str)
|
||||||
|
append(str.checksum())
|
||||||
|
append('\r')
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun startMeasurement(oldMeta: Meta?, newMeta: Meta) {
|
||||||
|
measurement {
|
||||||
|
val request = wrap("0010MV00")
|
||||||
|
val answer = sendAndWait(request)
|
||||||
|
if (answer.isEmpty()) {
|
||||||
|
updateState(CONNECTED_STATE, false)
|
||||||
|
notifyError("No connection")
|
||||||
|
} else {
|
||||||
|
updateState(CONNECTED_STATE, true)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
|
||||||
|
val address = answer.substring(0..2)
|
||||||
|
//if wrong answer
|
||||||
|
if (address != this.address) {
|
||||||
|
logger.warn("Expected response for address ${this.address}, bur received for $address")
|
||||||
|
notifyError("Wrong response address")
|
||||||
|
return@measurement
|
||||||
|
}
|
||||||
|
val dataSize = answer.substring(6..7).toInt()
|
||||||
|
val data = answer.substring(8, 8 + dataSize).toDouble()
|
||||||
|
if (data <= 0) {
|
||||||
|
notifyError("Non positive")
|
||||||
|
} else {
|
||||||
|
notifyResult(data)
|
||||||
|
}
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
logger.error("Parsing error", ex)
|
||||||
|
notifyError("Parse error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -48,16 +48,17 @@ class VacCollectorDevice(context: Context, meta: Meta, val sensors: Collection<S
|
|||||||
private val helper = StorageHelper(this, this::buildLoader)
|
private val helper = StorageHelper(this, this::buildLoader)
|
||||||
|
|
||||||
private val collector = object : DeviceListener {
|
private val collector = object : DeviceListener {
|
||||||
override fun notifyStateChanged(device: Device, name: String, state: Any) {
|
|
||||||
if (name == MEASUREMENT_RESULT_STATE) {
|
|
||||||
collector.put(device.name, (state as Meta).getValue("value"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val averagingDuration: Duration = Duration.parse(meta.getString("averagingDuration", "PT30S"))
|
val averagingDuration: Duration = Duration.parse(meta.getString("averagingDuration", "PT30S"))
|
||||||
|
|
||||||
private val collector = RegularPointCollector(averagingDuration) {
|
private val collector = RegularPointCollector(averagingDuration) {
|
||||||
notifyResult(it)
|
notifyResult(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun notifyStateChanged(device: Device, name: String, state: Any) {
|
||||||
|
if (name == MEASUREMENT_RESULT_STATE) {
|
||||||
|
collector.put(device.name, (state as Meta).getValue(RESULT_VALUE))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -69,10 +70,11 @@ class VacCollectorDevice(context: Context, meta: Meta, val sensors: Collection<S
|
|||||||
|
|
||||||
|
|
||||||
override fun init() {
|
override fun init() {
|
||||||
super.init()
|
|
||||||
for (s in sensors) {
|
for (s in sensors) {
|
||||||
s.init()
|
s.init()
|
||||||
|
s.connect(collector, Roles.DEVICE_LISTENER_ROLE)
|
||||||
}
|
}
|
||||||
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val type: String
|
override val type: String
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
*/
|
*/
|
||||||
package inr.numass.control.readvac
|
package inr.numass.control.readvac
|
||||||
|
|
||||||
import hep.dataforge.connections.Connection
|
|
||||||
import hep.dataforge.control.connections.Roles
|
import hep.dataforge.control.connections.Roles
|
||||||
|
import hep.dataforge.control.devices.Device
|
||||||
|
import hep.dataforge.control.devices.DeviceListener
|
||||||
import hep.dataforge.control.devices.Sensor
|
import hep.dataforge.control.devices.Sensor
|
||||||
import hep.dataforge.control.measurements.Measurement
|
|
||||||
import hep.dataforge.control.measurements.MeasurementListener
|
|
||||||
import hep.dataforge.fx.bindWindow
|
import hep.dataforge.fx.bindWindow
|
||||||
import hep.dataforge.fx.fragments.LogFragment
|
import hep.dataforge.fx.fragments.LogFragment
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.plots.PlotGroup
|
import hep.dataforge.plots.PlotGroup
|
||||||
import hep.dataforge.plots.data.TimePlot
|
import hep.dataforge.plots.data.TimePlot
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
@ -24,7 +24,6 @@ import javafx.geometry.Orientation
|
|||||||
import javafx.scene.control.ScrollPane
|
import javafx.scene.control.ScrollPane
|
||||||
import javafx.scene.layout.Priority
|
import javafx.scene.layout.Priority
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A view controller for Vac collector
|
* A view controller for Vac collector
|
||||||
@ -35,16 +34,13 @@ class VacCollectorDisplay : DeviceDisplayFX<VacCollectorDevice>() {
|
|||||||
|
|
||||||
private val table = FXCollections.observableHashMap<String, Double>()
|
private val table = FXCollections.observableHashMap<String, Double>()
|
||||||
|
|
||||||
private val sensorConnection = object : MeasurementListener, Connection {
|
private val sensorConnection = object : DeviceListener {
|
||||||
override fun onMeasurementResult(measurement: Measurement<*>, result: Any, time: Instant?) {
|
|
||||||
if (result is Double) {
|
override fun notifyStateChanged(device: Device, name: String, state: Any) {
|
||||||
table.put(measurement.device.name, result);
|
if (name == Sensor.MEASUREMENT_RESULT_STATE) {
|
||||||
|
table[device.name] = (state as Meta).getDouble(Sensor.RESULT_VALUE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMeasurementFailed(measurement: Measurement<*>?, exception: Throwable?) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val viewList = FXCollections.observableArrayList<VacDisplay>();
|
private val viewList = FXCollections.observableArrayList<VacDisplay>();
|
||||||
@ -58,7 +54,7 @@ class VacCollectorDisplay : DeviceDisplayFX<VacCollectorDevice>() {
|
|||||||
device.sensors.forEach { sensor ->
|
device.sensors.forEach { sensor ->
|
||||||
val view = VacDisplay()
|
val view = VacDisplay()
|
||||||
sensor.connect(view, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE)
|
sensor.connect(view, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE)
|
||||||
sensor.connect(sensorConnection, Roles.MEASUREMENT_LISTENER_ROLE);
|
sensor.connect(sensorConnection, Roles.DEVICE_LISTENER_ROLE)
|
||||||
viewList.add(view)
|
viewList.add(view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ class VacDeviceFactory : DeviceFactory {
|
|||||||
"CM32" -> CM32Device(context, sensorConfig)
|
"CM32" -> CM32Device(context, sensorConfig)
|
||||||
"meradat" -> MeradatVacDevice(context, sensorConfig)
|
"meradat" -> MeradatVacDevice(context, sensorConfig)
|
||||||
"baratron" -> MKSBaratronDevice(context, sensorConfig)
|
"baratron" -> MKSBaratronDevice(context, sensorConfig)
|
||||||
|
"ThyroCont" -> ThyroContVacDevice(context,sensorConfig)
|
||||||
// VIRTUAL_SENSOR_TYPE -> VirtualDevice.randomDoubleSensor(context, sensorConfig)
|
// VIRTUAL_SENSOR_TYPE -> VirtualDevice.randomDoubleSensor(context, sensorConfig)
|
||||||
else -> throw RuntimeException("Unknown vacuum sensor type")
|
else -> throw RuntimeException("Unknown vacuum sensor type")
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package inr.numass.control.readvac
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.meta.buildMeta
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
|
suspend fun main() {
|
||||||
|
val meta = buildMeta {
|
||||||
|
"name" to "PSP"
|
||||||
|
"port" to "tcp::192.168.111.32:4001"
|
||||||
|
"sensorType" to "ThyroCont"
|
||||||
|
}
|
||||||
|
val device = ThyroContVacDevice(Global, meta)
|
||||||
|
device.measure()
|
||||||
|
device.connected.set(true)
|
||||||
|
delay(400)
|
||||||
|
println(device.result)
|
||||||
|
device.connected.set(false)
|
||||||
|
|
||||||
|
}
|
@ -8,5 +8,6 @@
|
|||||||
<sensor name="Px" color="black" port="tcp::192.168.111.33:4003" sensorType="meradat" address="1"/>
|
<sensor name="Px" color="black" port="tcp::192.168.111.33:4003" sensorType="meradat" address="1"/>
|
||||||
<sensor name="Baratron" color="cyan" port="tcp::192.168.111.33:4004" sensorType="baratron"/>
|
<sensor name="Baratron" color="cyan" port="tcp::192.168.111.33:4004" sensorType="baratron"/>
|
||||||
<sensor name="Collector" color="magenta" port="tcp::192.168.111.33:4003" sensorType="meradat" address="2"/>
|
<sensor name="Collector" color="magenta" port="tcp::192.168.111.33:4003" sensorType="meradat" address="2"/>
|
||||||
|
<sensor name="PSP" port="tcp::192.168.111.32:4001" sensorType="ThyroCont" address="001"/>
|
||||||
</device>
|
</device>
|
||||||
</config>
|
</config>
|
||||||
|
@ -26,6 +26,9 @@ class MetaBlock(override val blocks: List<NumassBlock>) : ParentBlock {
|
|||||||
override val length: Duration
|
override val length: Duration
|
||||||
get() = Duration.ofNanos(blocks.stream().mapToLong { block -> block.length.toNanos() }.sum())
|
get() = Duration.ofNanos(blocks.stream().mapToLong { block -> block.length.toNanos() }.sum())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stream of events, sorted by block time but not sorted by event time
|
||||||
|
*/
|
||||||
override val events: Stream<NumassEvent>
|
override val events: Stream<NumassEvent>
|
||||||
get() = blocks.sortedBy { it.startTime }.stream().flatMap { it.events }
|
get() = blocks.sortedBy { it.startTime }.stream().flatMap { it.events }
|
||||||
|
|
||||||
|
@ -28,6 +28,12 @@ open class OrphanNumassEvent(val amplitude: Short, val timeOffset: Long) : Seria
|
|||||||
override fun compareTo(other: OrphanNumassEvent): Int {
|
override fun compareTo(other: OrphanNumassEvent): Int {
|
||||||
return this.timeOffset.compareTo(other.timeOffset)
|
return this.timeOffset.compareTo(other.timeOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "[$amplitude, $timeOffset]"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,18 +9,19 @@ import java.time.Instant
|
|||||||
* Created by darksnake on 06-Jul-17.
|
* Created by darksnake on 06-Jul-17.
|
||||||
*/
|
*/
|
||||||
class NumassFrame(
|
class NumassFrame(
|
||||||
/**
|
/**
|
||||||
* The absolute start time of the frame
|
* The absolute start time of the frame
|
||||||
*/
|
*/
|
||||||
val time: Instant,
|
val time: Instant,
|
||||||
/**
|
/**
|
||||||
* The time interval per tick
|
* The time interval per tick
|
||||||
*/
|
*/
|
||||||
val tickSize: Duration,
|
val tickSize: Duration,
|
||||||
/**
|
/**
|
||||||
* The buffered signal shape in ticks
|
* The buffered signal shape in ticks
|
||||||
*/
|
*/
|
||||||
val signal: ShortBuffer) {
|
val signal: ShortBuffer
|
||||||
|
) {
|
||||||
|
|
||||||
val length: Duration
|
val length: Duration
|
||||||
get() = tickSize.multipliedBy(signal.capacity().toLong())
|
get() = tickSize.multipliedBy(signal.capacity().toLong())
|
||||||
|
@ -7,5 +7,5 @@ import java.util.stream.Stream
|
|||||||
* Created by darksnake on 07.07.2017.
|
* Created by darksnake on 07.07.2017.
|
||||||
*/
|
*/
|
||||||
interface SignalProcessor {
|
interface SignalProcessor {
|
||||||
fun analyze(frame: NumassFrame): Stream<NumassEvent>
|
fun process(parent: NumassBlock, frame: NumassFrame): Stream<NumassEvent>
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,30 @@
|
|||||||
package inr.numass.data.api
|
package inr.numass.data.api
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.MetaBuilder
|
|
||||||
import hep.dataforge.meta.MetaHolder
|
import hep.dataforge.meta.MetaHolder
|
||||||
|
import hep.dataforge.meta.buildMeta
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple static implementation of NumassPoint
|
* A simple static implementation of NumassPoint
|
||||||
* Created by darksnake on 08.07.2017.
|
* Created by darksnake on 08.07.2017.
|
||||||
*/
|
*/
|
||||||
class SimpleNumassPoint(override val blocks: List<NumassBlock>, meta: Meta, override val isSequential: Boolean = true) : MetaHolder(meta), NumassPoint {
|
class SimpleNumassPoint(override val blocks: List<NumassBlock>, meta: Meta, override val isSequential: Boolean = true) :
|
||||||
|
MetaHolder(meta), NumassPoint {
|
||||||
/**
|
|
||||||
* Input blocks must be sorted
|
|
||||||
* @param voltage
|
|
||||||
* @param blocks
|
|
||||||
*/
|
|
||||||
constructor(blocks: Collection<NumassBlock>, voltage: Double) :
|
|
||||||
this(blocks.sortedBy { it.startTime }, MetaBuilder("point").setValue(NumassPoint.HV_KEY, voltage))
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if(blocks.isEmpty()){
|
if (blocks.isEmpty()) {
|
||||||
throw IllegalArgumentException("No blocks in collection")
|
throw IllegalArgumentException("No blocks in collection")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun build(blocks: Collection<NumassBlock>, voltage: Double? = null, index: Int? = null): SimpleNumassPoint {
|
||||||
|
val meta = buildMeta("point") {
|
||||||
|
NumassPoint.HV_KEY to voltage
|
||||||
|
NumassPoint.INDEX_KEY to index
|
||||||
|
}
|
||||||
|
return SimpleNumassPoint(blocks.sortedBy { it.startTime }, meta.build())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import com.google.protobuf.gradle.GenerateProtoTask
|
|
||||||
import com.google.protobuf.gradle.protobuf
|
import com.google.protobuf.gradle.protobuf
|
||||||
import com.google.protobuf.gradle.protoc
|
import com.google.protobuf.gradle.protoc
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
@ -6,7 +5,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|||||||
plugins {
|
plugins {
|
||||||
idea
|
idea
|
||||||
kotlin("jvm")
|
kotlin("jvm")
|
||||||
id("com.google.protobuf") version "0.8.7"
|
id("com.google.protobuf") version "0.8.8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -26,13 +25,13 @@ tasks.withType<KotlinCompile> {
|
|||||||
dependsOn(":numass-core:numass-data-proto:generateProto")
|
dependsOn(":numass-core:numass-data-proto:generateProto")
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets{
|
//sourceSets {
|
||||||
create("proto"){
|
// create("proto") {
|
||||||
proto {
|
// proto {
|
||||||
srcDir("src/main/proto")
|
// srcDir("src/main/proto")
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
protobuf {
|
protobuf {
|
||||||
// Configure the protoc executable
|
// Configure the protoc executable
|
||||||
|
@ -29,7 +29,6 @@ import java.time.Instant
|
|||||||
import java.util.stream.IntStream
|
import java.util.stream.IntStream
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
import java.util.zip.Inflater
|
import java.util.zip.Inflater
|
||||||
import kotlin.streams.toList
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protobuf based numass point
|
* Protobuf based numass point
|
||||||
@ -42,11 +41,11 @@ class ProtoNumassPoint(override val meta: Meta, val protoBuilder: () -> NumassPr
|
|||||||
|
|
||||||
override val blocks: List<NumassBlock>
|
override val blocks: List<NumassBlock>
|
||||||
get() = proto.channelsList
|
get() = proto.channelsList
|
||||||
.flatMap { channel ->
|
.flatMap { channel ->
|
||||||
channel.blocksList
|
channel.blocksList
|
||||||
.map { block -> ProtoBlock(channel.id.toInt(), block, this) }
|
.map { block -> ProtoBlock(channel.id.toInt(), block, this) }
|
||||||
.sortedBy { it.startTime }
|
.sortedBy { it.startTime }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val channels: Map<Int, NumassBlock>
|
override val channels: Map<Int, NumassBlock>
|
||||||
get() = proto.channelsList.groupBy { it.id.toInt() }.mapValues { entry ->
|
get() = proto.channelsList.groupBy { it.id.toInt() }.mapValues { entry ->
|
||||||
@ -127,7 +126,11 @@ class ProtoNumassPoint(override val meta: Meta, val protoBuilder: () -> NumassPr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProtoBlock(override val channel: Int, private val block: NumassProto.Point.Channel.Block, val parent: NumassPoint? = null) : NumassBlock {
|
class ProtoBlock(
|
||||||
|
override val channel: Int,
|
||||||
|
private val block: NumassProto.Point.Channel.Block,
|
||||||
|
val parent: NumassPoint? = null
|
||||||
|
) : NumassBlock {
|
||||||
|
|
||||||
override val startTime: Instant
|
override val startTime: Instant
|
||||||
get() = ProtoNumassPoint.ofEpochNanos(block.time)
|
get() = ProtoNumassPoint.ofEpochNanos(block.time)
|
||||||
@ -136,11 +139,15 @@ class ProtoBlock(override val channel: Int, private val block: NumassProto.Point
|
|||||||
block.length > 0 -> Duration.ofNanos(block.length)
|
block.length > 0 -> Duration.ofNanos(block.length)
|
||||||
parent?.meta?.hasValue("acquisition_time") ?: false ->
|
parent?.meta?.hasValue("acquisition_time") ?: false ->
|
||||||
Duration.ofMillis((parent!!.meta.getDouble("acquisition_time") * 1000).toLong())
|
Duration.ofMillis((parent!!.meta.getDouble("acquisition_time") * 1000).toLong())
|
||||||
|
parent?.meta?.hasValue("params.b_size") ?: false ->
|
||||||
|
Duration.ofNanos((parent!!.meta.getDouble("params.b_size") * 320).toLong())
|
||||||
else -> {
|
else -> {
|
||||||
LoggerFactory.getLogger(javaClass).error("No length information on block. Trying to infer from first and last events")
|
error("No length information on block")
|
||||||
val times = events.map { it.timeOffset }.toList()
|
// LoggerFactory.getLogger(javaClass).warn("No length information on block. Trying to infer from first and last events")
|
||||||
val nanos = (times.max()!! - times.min()!!)
|
// val times = events.map { it.timeOffset }.toList()
|
||||||
Duration.ofNanos(nanos)
|
// val nanos = (times.max()!! - times.min()!!)
|
||||||
|
// Duration.ofNanos(nanos)
|
||||||
|
// Duration.ofMillis(380)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,9 +155,11 @@ class ProtoBlock(override val channel: Int, private val block: NumassProto.Point
|
|||||||
get() = if (block.hasEvents()) {
|
get() = if (block.hasEvents()) {
|
||||||
val events = block.events
|
val events = block.events
|
||||||
if (events.timesCount != events.amplitudesCount) {
|
if (events.timesCount != events.amplitudesCount) {
|
||||||
LoggerFactory.getLogger(javaClass).error("The block is broken. Number of times is ${events.timesCount} and number of amplitudes is ${events.amplitudesCount}")
|
LoggerFactory.getLogger(javaClass)
|
||||||
|
.error("The block is broken. Number of times is ${events.timesCount} and number of amplitudes is ${events.amplitudesCount}")
|
||||||
}
|
}
|
||||||
IntStream.range(0, events.timesCount).mapToObj { i -> NumassEvent(events.getAmplitudes(i).toShort(), events.getTimes(i), this) }
|
IntStream.range(0, events.timesCount)
|
||||||
|
.mapToObj { i -> NumassEvent(events.getAmplitudes(i).toShort(), events.getTimes(i), this) }
|
||||||
} else {
|
} else {
|
||||||
Stream.empty()
|
Stream.empty()
|
||||||
}
|
}
|
||||||
|
20
numass-core/numass-signal-processing/build.gradle.kts
Normal file
20
numass-core/numass-signal-processing/build.gradle.kts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
plugins {
|
||||||
|
idea
|
||||||
|
kotlin("jvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile(kotlin("stdlib-jdk8"))
|
||||||
|
compile("hep.dataforge:dataforge-maths")
|
||||||
|
compile(project(":numass-core:numass-data-api"))
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/org.apache.commons/commons-collections4
|
||||||
|
compile(group = "org.apache.commons", name = "commons-collections4", version = "4.3")
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
package inr.numass.data
|
||||||
|
|
||||||
|
import inr.numass.data.api.*
|
||||||
|
import org.apache.commons.collections4.queue.CircularFifoQueue
|
||||||
|
import org.apache.commons.math3.fitting.PolynomialCurveFitter
|
||||||
|
import org.apache.commons.math3.fitting.WeightedObservedPoint
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import java.nio.ShortBuffer
|
||||||
|
import java.util.stream.Stream
|
||||||
|
import kotlin.streams.asStream
|
||||||
|
|
||||||
|
|
||||||
|
private fun ShortBuffer.clone(): ShortBuffer {
|
||||||
|
val clone = ShortBuffer.allocate(capacity())
|
||||||
|
rewind()//copy from the beginning
|
||||||
|
clone.put(this)
|
||||||
|
rewind()
|
||||||
|
clone.flip()
|
||||||
|
return clone
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ChernovProcessor(
|
||||||
|
val threshold: Short,
|
||||||
|
val signalRange: IntRange,
|
||||||
|
val tickSize: Int = 320,
|
||||||
|
val signal: (Double) -> Double
|
||||||
|
) : SignalProcessor {
|
||||||
|
|
||||||
|
private val fitter = PolynomialCurveFitter.create(2)
|
||||||
|
|
||||||
|
private val signalMax = signal(0.0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* position an amplitude of peak relative to buffer end (negative)
|
||||||
|
*/
|
||||||
|
private fun CircularFifoQueue<Short>.findMax(): Pair<Double, Double> {
|
||||||
|
val data = this.mapIndexed { index, value ->
|
||||||
|
WeightedObservedPoint(
|
||||||
|
1.0,
|
||||||
|
index.toDouble() - size + 1, // final point in zero
|
||||||
|
value.toDouble()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val (c, b, a) = fitter.fit(data)
|
||||||
|
if (a > 0) error("Minimum!")
|
||||||
|
val x = -b / 2 / a
|
||||||
|
val y = -(b * b - 4 * a * c) / 4 / a
|
||||||
|
return x to y
|
||||||
|
}
|
||||||
|
|
||||||
|
fun processBuffer(buffer: ShortBuffer): Sequence<OrphanNumassEvent> {
|
||||||
|
|
||||||
|
val ringBuffer = CircularFifoQueue<Short>(5)
|
||||||
|
|
||||||
|
fun roll() {
|
||||||
|
ringBuffer.add(buffer.get())
|
||||||
|
}
|
||||||
|
|
||||||
|
return sequence<OrphanNumassEvent> {
|
||||||
|
while (buffer.remaining() > 1) {
|
||||||
|
roll()
|
||||||
|
if (ringBuffer.isAtFullCapacity) {
|
||||||
|
if (ringBuffer.all { it > threshold && it <= ringBuffer[2] }) {
|
||||||
|
//Found bending, evaluating event
|
||||||
|
//TODO check end of frame
|
||||||
|
try {
|
||||||
|
val (pos, amp) = ringBuffer.findMax()
|
||||||
|
|
||||||
|
val timeInTicks = (pos + buffer.position() - 1)
|
||||||
|
|
||||||
|
val event = OrphanNumassEvent(amp.toShort(), (timeInTicks * tickSize).toLong())
|
||||||
|
yield(event)
|
||||||
|
|
||||||
|
//subtracting event from buffer copy
|
||||||
|
for (x in (signalRange.first + timeInTicks.toInt())..(signalRange.endInclusive + timeInTicks.toInt())) {
|
||||||
|
//TODO check all roundings
|
||||||
|
if (x >= 0 && x < buffer.limit()) {
|
||||||
|
val oldValue = buffer.get(x)
|
||||||
|
val newValue = oldValue - amp * signal(x - timeInTicks) / signalMax
|
||||||
|
buffer.put(x, newValue.toShort())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println(buffer.array().joinToString())
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
LoggerFactory.getLogger(javaClass).error("Something went wrong", ex)
|
||||||
|
}
|
||||||
|
roll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun process(parent: NumassBlock, frame: NumassFrame): Stream<NumassEvent> {
|
||||||
|
val buffer = frame.signal.clone()
|
||||||
|
return processBuffer(buffer).map { it.adopt(parent) }.asStream()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
package inr.numass.data
|
||||||
|
|
||||||
|
import org.apache.commons.math3.analysis.function.Gaussian
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Test
|
||||||
|
import java.nio.ShortBuffer
|
||||||
|
|
||||||
|
class ChernovProcessorTest {
|
||||||
|
val gaussian = Gaussian(1000.0, 0.0, 3.0)
|
||||||
|
val processor = ChernovProcessor(10, -12..12, tickSize = 100) { gaussian.value(it) }
|
||||||
|
|
||||||
|
val events = mapOf<Double, Double>(10.0 to 1.0, 16.0 to 0.5)
|
||||||
|
|
||||||
|
val buffer = ShortArray(40) { i ->
|
||||||
|
events.entries.sumByDouble { (pos, amp) -> amp * gaussian.value(pos - i.toDouble()) }.toShort()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testPeaks() {
|
||||||
|
println(buffer.joinToString())
|
||||||
|
val peaks = processor.processBuffer(ShortBuffer.wrap(buffer)).toList()
|
||||||
|
assertTrue(peaks.isNotEmpty())
|
||||||
|
println(peaks.joinToString())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -21,9 +21,8 @@ import hep.dataforge.meta.Meta
|
|||||||
import hep.dataforge.meta.MetaBuilder
|
import hep.dataforge.meta.MetaBuilder
|
||||||
import inr.numass.data.api.*
|
import inr.numass.data.api.*
|
||||||
import inr.numass.data.storage.ClassicNumassPoint
|
import inr.numass.data.storage.ClassicNumassPoint
|
||||||
import java.util.stream.Collectors
|
import org.slf4j.LoggerFactory
|
||||||
import kotlin.streams.asSequence
|
import kotlin.streams.asSequence
|
||||||
import kotlin.streams.toList
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,10 +34,8 @@ object NumassDataUtils {
|
|||||||
override suspend fun getHvData() = TODO()
|
override suspend fun getHvData() = TODO()
|
||||||
|
|
||||||
override val points: List<NumassPoint> by lazy {
|
override val points: List<NumassPoint> by lazy {
|
||||||
val points = sets.stream().flatMap<NumassPoint> { it.points.stream() }
|
val points = sets.flatMap { it.points }.groupBy { it.voltage }
|
||||||
.collect(Collectors.groupingBy<NumassPoint, Double> { it.voltage })
|
return@lazy points.entries.map { entry -> SimpleNumassPoint.build(entry.value, entry.key) }
|
||||||
points.entries.stream().map { entry -> SimpleNumassPoint(entry.value, entry.key) }
|
|
||||||
.toList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val meta: Meta by lazy {
|
override val meta: Meta by lazy {
|
||||||
@ -51,6 +48,35 @@ object NumassDataUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun joinByIndex(setName: String, sets: Collection<NumassSet>): NumassSet {
|
||||||
|
return object : NumassSet {
|
||||||
|
override suspend fun getHvData() = TODO()
|
||||||
|
|
||||||
|
override val points: List<NumassPoint> by lazy {
|
||||||
|
val points = sets.flatMap { it.points }.groupBy { it.index }
|
||||||
|
return@lazy points.mapNotNull { (index, points) ->
|
||||||
|
val voltage = points.first().voltage
|
||||||
|
if (!points.all { it.voltage == voltage }) {
|
||||||
|
LoggerFactory.getLogger(javaClass)
|
||||||
|
.warn("Not all points with index $index have voltage $voltage")
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
SimpleNumassPoint.build(points, voltage, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val meta: Meta by lazy {
|
||||||
|
val metaBuilder = MetaBuilder()
|
||||||
|
sets.forEach { set -> metaBuilder.putNode(set.name, set.meta) }
|
||||||
|
metaBuilder
|
||||||
|
}
|
||||||
|
|
||||||
|
override val name = setName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun adapter(): SpectrumAdapter {
|
fun adapter(): SpectrumAdapter {
|
||||||
return SpectrumAdapter("Uset", "CR", "CRerr", "Time")
|
return SpectrumAdapter("Uset", "CR", "CRerr", "Time")
|
||||||
}
|
}
|
||||||
@ -67,18 +93,18 @@ object NumassDataUtils {
|
|||||||
suspend fun NumassBlock.transformChain(transform: (NumassEvent, NumassEvent) -> Pair<Short, Long>?): NumassBlock {
|
suspend fun NumassBlock.transformChain(transform: (NumassEvent, NumassEvent) -> Pair<Short, Long>?): NumassBlock {
|
||||||
return SimpleBlock.produce(this.startTime, this.length) {
|
return SimpleBlock.produce(this.startTime, this.length) {
|
||||||
this.events.asSequence()
|
this.events.asSequence()
|
||||||
.sortedBy { it.timeOffset }
|
.sortedBy { it.timeOffset }
|
||||||
.zipWithNext(transform)
|
.zipWithNext(transform)
|
||||||
.filterNotNull()
|
.filterNotNull()
|
||||||
.map { OrphanNumassEvent(it.first, it.second) }.asIterable()
|
.map { OrphanNumassEvent(it.first, it.second) }.asIterable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun NumassBlock.filterChain(condition: (NumassEvent, NumassEvent) -> Boolean): NumassBlock {
|
suspend fun NumassBlock.filterChain(condition: (NumassEvent, NumassEvent) -> Boolean): NumassBlock {
|
||||||
return SimpleBlock.produce(this.startTime, this.length) {
|
return SimpleBlock.produce(this.startTime, this.length) {
|
||||||
this.events.asSequence()
|
this.events.asSequence()
|
||||||
.sortedBy { it.timeOffset }
|
.sortedBy { it.timeOffset }
|
||||||
.zipWithNext().filter { condition.invoke(it.first, it.second) }.map { it.second }.asIterable()
|
.zipWithNext().filter { condition.invoke(it.first, it.second) }.map { it.second }.asIterable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +117,7 @@ suspend fun NumassBlock.filter(condition: (NumassEvent) -> Boolean): NumassBlock
|
|||||||
suspend fun NumassBlock.transform(transform: (NumassEvent) -> OrphanNumassEvent): NumassBlock {
|
suspend fun NumassBlock.transform(transform: (NumassEvent) -> OrphanNumassEvent): NumassBlock {
|
||||||
return SimpleBlock.produce(this.startTime, this.length) {
|
return SimpleBlock.produce(this.startTime, this.length) {
|
||||||
this.events.asSequence()
|
this.events.asSequence()
|
||||||
.map { transform(it) }
|
.map { transform(it) }
|
||||||
.asIterable()
|
.asIterable()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,18 +22,19 @@ import hep.dataforge.tables.ListTable
|
|||||||
import hep.dataforge.tables.Table
|
import hep.dataforge.tables.Table
|
||||||
import hep.dataforge.tables.TableFormat
|
import hep.dataforge.tables.TableFormat
|
||||||
import hep.dataforge.tables.TableFormatBuilder
|
import hep.dataforge.tables.TableFormatBuilder
|
||||||
|
import hep.dataforge.toList
|
||||||
import inr.numass.data.api.NumassBlock
|
import inr.numass.data.api.NumassBlock
|
||||||
import inr.numass.data.api.NumassEvent
|
import inr.numass.data.api.NumassEvent
|
||||||
import inr.numass.data.api.NumassPoint.Companion.HV_KEY
|
import inr.numass.data.api.NumassPoint.Companion.HV_KEY
|
||||||
import inr.numass.data.api.NumassSet
|
import inr.numass.data.api.NumassSet
|
||||||
import inr.numass.data.api.SignalProcessor
|
import inr.numass.data.api.SignalProcessor
|
||||||
import java.lang.IllegalArgumentException
|
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by darksnake on 11.07.2017.
|
* Created by darksnake on 11.07.2017.
|
||||||
*/
|
*/
|
||||||
abstract class AbstractAnalyzer @JvmOverloads constructor(private val processor: SignalProcessor? = null) : NumassAnalyzer {
|
abstract class AbstractAnalyzer @JvmOverloads constructor(private val processor: SignalProcessor? = null) :
|
||||||
|
NumassAnalyzer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return unsorted stream of events including events from frames.
|
* Return unsorted stream of events including events from frames.
|
||||||
@ -43,22 +44,24 @@ abstract class AbstractAnalyzer @JvmOverloads constructor(private val processor:
|
|||||||
* @param block
|
* @param block
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
override fun getEvents(block: NumassBlock, meta: Meta): Stream<NumassEvent> {
|
override fun getEvents(block: NumassBlock, meta: Meta): List<NumassEvent> {
|
||||||
val loChannel = meta.getInt("window.lo", 0)
|
val range = meta.getRange()
|
||||||
val upChannel = meta.getInt("window.up", Integer.MAX_VALUE)
|
|
||||||
// if (meta.getBoolean("sort", false)) {
|
|
||||||
// res = res.sorted(compareBy { it.timeOffset })
|
|
||||||
// }
|
|
||||||
return getAllEvents(block).filter { event ->
|
return getAllEvents(block).filter { event ->
|
||||||
event.amplitude.toInt() in loChannel..(upChannel - 1)
|
event.amplitude.toInt() in range
|
||||||
}
|
}.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun Meta.getRange(): IntRange {
|
||||||
|
val loChannel = getInt("window.lo", 0)
|
||||||
|
val upChannel = getInt("window.up", Integer.MAX_VALUE)
|
||||||
|
return loChannel until upChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun getAllEvents(block: NumassBlock): Stream<NumassEvent> {
|
protected fun getAllEvents(block: NumassBlock): Stream<NumassEvent> {
|
||||||
return when {
|
return when {
|
||||||
block.frames.count() == 0L -> block.events
|
block.frames.count() == 0L -> block.events
|
||||||
processor == null -> throw IllegalArgumentException("Signal processor needed to analyze frames")
|
processor == null -> throw IllegalArgumentException("Signal processor needed to analyze frames")
|
||||||
else -> Stream.concat(block.events, block.frames.flatMap { processor.analyze(it) })
|
else -> Stream.concat(block.events, block.frames.flatMap { processor.process(block, it) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,14 +73,14 @@ abstract class AbstractAnalyzer @JvmOverloads constructor(private val processor:
|
|||||||
*/
|
*/
|
||||||
protected open fun getTableFormat(config: Meta): TableFormat {
|
protected open fun getTableFormat(config: Meta): TableFormat {
|
||||||
return TableFormatBuilder()
|
return TableFormatBuilder()
|
||||||
.addNumber(HV_KEY, X_VALUE_KEY)
|
.addNumber(HV_KEY, X_VALUE_KEY)
|
||||||
.addNumber(NumassAnalyzer.LENGTH_KEY)
|
.addNumber(NumassAnalyzer.LENGTH_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_KEY)
|
.addNumber(NumassAnalyzer.COUNT_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_RATE_KEY, Y_VALUE_KEY)
|
.addNumber(NumassAnalyzer.COUNT_RATE_KEY, Y_VALUE_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_RATE_ERROR_KEY, Y_ERROR_KEY)
|
.addNumber(NumassAnalyzer.COUNT_RATE_ERROR_KEY, Y_ERROR_KEY)
|
||||||
.addColumn(NumassAnalyzer.WINDOW_KEY)
|
.addColumn(NumassAnalyzer.WINDOW_KEY)
|
||||||
.addTime()
|
.addTime()
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -85,18 +88,18 @@ abstract class AbstractAnalyzer @JvmOverloads constructor(private val processor:
|
|||||||
val format = getTableFormat(config)
|
val format = getTableFormat(config)
|
||||||
|
|
||||||
return ListTable.Builder(format)
|
return ListTable.Builder(format)
|
||||||
.rows(set.points.map { point -> analyzeParent(point, config) })
|
.rows(set.points.map { point -> analyzeParent(point, config) })
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val NAME_LIST = arrayOf(
|
val NAME_LIST = arrayOf(
|
||||||
NumassAnalyzer.LENGTH_KEY,
|
NumassAnalyzer.LENGTH_KEY,
|
||||||
NumassAnalyzer.COUNT_KEY,
|
NumassAnalyzer.COUNT_KEY,
|
||||||
NumassAnalyzer.COUNT_RATE_KEY,
|
NumassAnalyzer.COUNT_RATE_KEY,
|
||||||
NumassAnalyzer.COUNT_RATE_ERROR_KEY,
|
NumassAnalyzer.COUNT_RATE_ERROR_KEY,
|
||||||
NumassAnalyzer.WINDOW_KEY,
|
NumassAnalyzer.WINDOW_KEY,
|
||||||
NumassAnalyzer.TIME_KEY
|
NumassAnalyzer.TIME_KEY
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ import java.util.*
|
|||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
import java.util.stream.IntStream
|
import java.util.stream.IntStream
|
||||||
import java.util.stream.Stream
|
|
||||||
import kotlin.streams.asSequence
|
import kotlin.streams.asSequence
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,10 +52,19 @@ interface NumassAnalyzer {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun analyzeParent(point: ParentBlock, config: Meta = Meta.empty()): Values {
|
fun analyzeParent(point: ParentBlock, config: Meta = Meta.empty()): Values {
|
||||||
|
// //Add properties to config
|
||||||
|
// val newConfig = config.builder.apply {
|
||||||
|
// if (point is NumassPoint) {
|
||||||
|
// setValue("voltage", point.voltage)
|
||||||
|
// setValue("index", point.index)
|
||||||
|
// }
|
||||||
|
// setValue("channel", point.channel)
|
||||||
|
// }
|
||||||
val map = HashMap(analyze(point, config).asMap())
|
val map = HashMap(analyze(point, config).asMap())
|
||||||
if(point is NumassPoint) {
|
if (point is NumassPoint) {
|
||||||
map[HV_KEY] = Value.of(point.voltage)
|
map[HV_KEY] = Value.of(point.voltage)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ValueMap(map)
|
return ValueMap(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +74,7 @@ interface NumassAnalyzer {
|
|||||||
* @param block
|
* @param block
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun getEvents(block: NumassBlock, meta: Meta = Meta.empty()): Stream<NumassEvent>
|
fun getEvents(block: NumassBlock, meta: Meta = Meta.empty()): List<NumassEvent>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyze the whole set. And return results as a table
|
* Analyze the whole set. And return results as a table
|
||||||
@ -101,7 +109,7 @@ interface NumassAnalyzer {
|
|||||||
|
|
||||||
fun getAmplitudeSpectrum(block: NumassBlock, config: Meta = Meta.empty()): Table {
|
fun getAmplitudeSpectrum(block: NumassBlock, config: Meta = Meta.empty()): Table {
|
||||||
val seconds = block.length.toMillis().toDouble() / 1000.0
|
val seconds = block.length.toMillis().toDouble() / 1000.0
|
||||||
return getAmplitudeSpectrum(getEvents(block, config).asSequence(), seconds, config)
|
return getEvents(block, config).asSequence().getAmplitudeSpectrum(seconds, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -114,8 +122,6 @@ interface NumassAnalyzer {
|
|||||||
const val WINDOW_KEY = "window"
|
const val WINDOW_KEY = "window"
|
||||||
const val TIME_KEY = "timestamp"
|
const val TIME_KEY = "timestamp"
|
||||||
|
|
||||||
val DEFAULT_ANALYZER: NumassAnalyzer = SmartAnalyzer()
|
|
||||||
|
|
||||||
val AMPLITUDE_ADAPTER: ValuesAdapter = Adapters.buildXYAdapter(CHANNEL_KEY, COUNT_RATE_KEY)
|
val AMPLITUDE_ADAPTER: ValuesAdapter = Adapters.buildXYAdapter(CHANNEL_KEY, COUNT_RATE_KEY)
|
||||||
|
|
||||||
// val MAX_CHANNEL = 10000
|
// val MAX_CHANNEL = 10000
|
||||||
@ -139,23 +145,26 @@ fun Table.countInWindow(loChannel: Short, upChannel: Short): Long {
|
|||||||
/**
|
/**
|
||||||
* Calculate the amplitude spectrum for a given block. The s
|
* Calculate the amplitude spectrum for a given block. The s
|
||||||
*
|
*
|
||||||
* @param events
|
* @param this@getAmplitudeSpectrum
|
||||||
* @param length length in seconds, used for count rate calculation
|
* @param length length in seconds, used for count rate calculation
|
||||||
* @param config
|
* @param config
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun getAmplitudeSpectrum(events: Sequence<NumassEvent>, length: Double, config: Meta = Meta.empty()): Table {
|
fun Sequence<NumassEvent>.getAmplitudeSpectrum(
|
||||||
|
length: Double,
|
||||||
|
config: Meta = Meta.empty()
|
||||||
|
): Table {
|
||||||
val format = TableFormatBuilder()
|
val format = TableFormatBuilder()
|
||||||
.addNumber(NumassAnalyzer.CHANNEL_KEY, X_VALUE_KEY)
|
.addNumber(NumassAnalyzer.CHANNEL_KEY, X_VALUE_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_KEY)
|
.addNumber(NumassAnalyzer.COUNT_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_RATE_KEY, Y_VALUE_KEY)
|
.addNumber(NumassAnalyzer.COUNT_RATE_KEY, Y_VALUE_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_RATE_ERROR_KEY, Y_ERROR_KEY)
|
.addNumber(NumassAnalyzer.COUNT_RATE_ERROR_KEY, Y_ERROR_KEY)
|
||||||
.updateMeta { metaBuilder -> metaBuilder.setNode("config", config) }
|
.updateMeta { metaBuilder -> metaBuilder.setNode("config", config) }
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
//optimized for fastest computation
|
//optimized for fastest computation
|
||||||
val spectrum: MutableMap<Int, AtomicLong> = HashMap()
|
val spectrum: MutableMap<Int, AtomicLong> = HashMap()
|
||||||
events.forEach { event ->
|
forEach { event ->
|
||||||
val channel = event.amplitude.toInt()
|
val channel = event.amplitude.toInt()
|
||||||
spectrum.getOrPut(channel) {
|
spectrum.getOrPut(channel) {
|
||||||
AtomicLong(0)
|
AtomicLong(0)
|
||||||
@ -163,22 +172,22 @@ fun getAmplitudeSpectrum(events: Sequence<NumassEvent>, length: Double, config:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val minChannel = config.getInt("window.lo") { spectrum.keys.min()?:0 }
|
val minChannel = config.getInt("window.lo") { spectrum.keys.min() ?: 0 }
|
||||||
val maxChannel = config.getInt("window.up") { spectrum.keys.max()?: 4096 }
|
val maxChannel = config.getInt("window.up") { spectrum.keys.max() ?: 4096 }
|
||||||
|
|
||||||
return ListTable.Builder(format)
|
return ListTable.Builder(format)
|
||||||
.rows(IntStream.range(minChannel, maxChannel)
|
.rows(IntStream.range(minChannel, maxChannel)
|
||||||
.mapToObj { i ->
|
.mapToObj { i ->
|
||||||
val value = spectrum[i]?.get() ?: 0
|
val value = spectrum[i]?.get() ?: 0
|
||||||
ValueMap.of(
|
ValueMap.of(
|
||||||
format.namesAsArray(),
|
format.namesAsArray(),
|
||||||
i,
|
i,
|
||||||
value,
|
value,
|
||||||
value.toDouble() / length,
|
value.toDouble() / length,
|
||||||
Math.sqrt(value.toDouble()) / length
|
Math.sqrt(value.toDouble()) / length
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
).build()
|
).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -192,18 +201,18 @@ fun getAmplitudeSpectrum(events: Sequence<NumassEvent>, length: Double, config:
|
|||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun Table.withBinning(binSize: Int, loChannel: Int? = null, upChannel: Int? = null): Table {
|
fun Table.withBinning(binSize: Int, loChannel: Int? = null, upChannel: Int? = null): Table {
|
||||||
val format = TableFormatBuilder()
|
val format = TableFormatBuilder()
|
||||||
.addNumber(NumassAnalyzer.CHANNEL_KEY, X_VALUE_KEY)
|
.addNumber(NumassAnalyzer.CHANNEL_KEY, X_VALUE_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_KEY, Y_VALUE_KEY)
|
.addNumber(NumassAnalyzer.COUNT_KEY, Y_VALUE_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_RATE_KEY)
|
.addNumber(NumassAnalyzer.COUNT_RATE_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_RATE_ERROR_KEY)
|
.addNumber(NumassAnalyzer.COUNT_RATE_ERROR_KEY)
|
||||||
.addNumber("binSize")
|
.addNumber("binSize")
|
||||||
val builder = ListTable.Builder(format)
|
val builder = ListTable.Builder(format)
|
||||||
|
|
||||||
var chan = loChannel
|
var chan = loChannel
|
||||||
?: this.getColumn(NumassAnalyzer.CHANNEL_KEY).stream().mapToInt { it.int }.min().orElse(0)
|
?: this.getColumn(NumassAnalyzer.CHANNEL_KEY).stream().mapToInt { it.int }.min().orElse(0)
|
||||||
|
|
||||||
val top = upChannel
|
val top = upChannel
|
||||||
?: this.getColumn(NumassAnalyzer.CHANNEL_KEY).stream().mapToInt { it.int }.max().orElse(1)
|
?: this.getColumn(NumassAnalyzer.CHANNEL_KEY).stream().mapToInt { it.int }.max().orElse(1)
|
||||||
|
|
||||||
while (chan < top - binSize) {
|
while (chan < top - binSize) {
|
||||||
val count = AtomicLong(0)
|
val count = AtomicLong(0)
|
||||||
@ -218,10 +227,21 @@ fun Table.withBinning(binSize: Int, loChannel: Int? = null, upChannel: Int? = nu
|
|||||||
}.forEach { row ->
|
}.forEach { row ->
|
||||||
count.addAndGet(row.getValue(NumassAnalyzer.COUNT_KEY, 0).long)
|
count.addAndGet(row.getValue(NumassAnalyzer.COUNT_KEY, 0).long)
|
||||||
countRate.accumulateAndGet(row.getDouble(NumassAnalyzer.COUNT_RATE_KEY, 0.0)) { d1, d2 -> d1 + d2 }
|
countRate.accumulateAndGet(row.getDouble(NumassAnalyzer.COUNT_RATE_KEY, 0.0)) { d1, d2 -> d1 + d2 }
|
||||||
countRateDispersion.accumulateAndGet(Math.pow(row.getDouble(NumassAnalyzer.COUNT_RATE_ERROR_KEY, 0.0), 2.0)) { d1, d2 -> d1 + d2 }
|
countRateDispersion.accumulateAndGet(
|
||||||
|
Math.pow(
|
||||||
|
row.getDouble(NumassAnalyzer.COUNT_RATE_ERROR_KEY, 0.0),
|
||||||
|
2.0
|
||||||
|
)
|
||||||
|
) { d1, d2 -> d1 + d2 }
|
||||||
}
|
}
|
||||||
val bin = Math.min(binSize, top - chan)
|
val bin = Math.min(binSize, top - chan)
|
||||||
builder.row(chan.toDouble() + bin.toDouble() / 2.0, count.get(), countRate.get(), Math.sqrt(countRateDispersion.get()), bin)
|
builder.row(
|
||||||
|
chan.toDouble() + bin.toDouble() / 2.0,
|
||||||
|
count.get(),
|
||||||
|
countRate.get(),
|
||||||
|
Math.sqrt(countRateDispersion.get()),
|
||||||
|
bin
|
||||||
|
)
|
||||||
chan += binSize
|
chan += binSize
|
||||||
}
|
}
|
||||||
return builder.build()
|
return builder.build()
|
||||||
@ -236,26 +256,24 @@ fun Table.withBinning(binSize: Int, loChannel: Int? = null, upChannel: Int? = nu
|
|||||||
*/
|
*/
|
||||||
fun subtractAmplitudeSpectrum(sp1: Table, sp2: Table): Table {
|
fun subtractAmplitudeSpectrum(sp1: Table, sp2: Table): Table {
|
||||||
val format = TableFormatBuilder()
|
val format = TableFormatBuilder()
|
||||||
.addNumber(NumassAnalyzer.CHANNEL_KEY, X_VALUE_KEY)
|
.addNumber(NumassAnalyzer.CHANNEL_KEY, X_VALUE_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_RATE_KEY, Y_VALUE_KEY)
|
.addNumber(NumassAnalyzer.COUNT_RATE_KEY, Y_VALUE_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_RATE_ERROR_KEY, Y_ERROR_KEY)
|
.addNumber(NumassAnalyzer.COUNT_RATE_ERROR_KEY, Y_ERROR_KEY)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val builder = ListTable.Builder(format)
|
val builder = ListTable.Builder(format)
|
||||||
|
|
||||||
sp1.forEach { row1 ->
|
sp1.forEach { row1 ->
|
||||||
val channel = row1.getDouble(NumassAnalyzer.CHANNEL_KEY)
|
val channel = row1.getDouble(NumassAnalyzer.CHANNEL_KEY)
|
||||||
val row2 = sp2.rows.asSequence().find { it.getDouble(NumassAnalyzer.CHANNEL_KEY) == channel } //t2[channel]
|
val row2 = sp2.rows.asSequence().find { it.getDouble(NumassAnalyzer.CHANNEL_KEY) == channel }
|
||||||
if (row2 == null) {
|
?: ValueMap.ofPairs(NumassAnalyzer.COUNT_RATE_KEY to 0.0, NumassAnalyzer.COUNT_RATE_ERROR_KEY to 0.0)
|
||||||
throw RuntimeException("Reference for channel $channel not found");
|
|
||||||
|
|
||||||
} else {
|
val value =
|
||||||
val value = Math.max(row1.getDouble(NumassAnalyzer.COUNT_RATE_KEY) - row2.getDouble(NumassAnalyzer.COUNT_RATE_KEY), 0.0)
|
Math.max(row1.getDouble(NumassAnalyzer.COUNT_RATE_KEY) - row2.getDouble(NumassAnalyzer.COUNT_RATE_KEY), 0.0)
|
||||||
val error1 = row1.getDouble(NumassAnalyzer.COUNT_RATE_ERROR_KEY)
|
val error1 = row1.getDouble(NumassAnalyzer.COUNT_RATE_ERROR_KEY)
|
||||||
val error2 = row2.getDouble(NumassAnalyzer.COUNT_RATE_ERROR_KEY)
|
val error2 = row2.getDouble(NumassAnalyzer.COUNT_RATE_ERROR_KEY)
|
||||||
val error = Math.sqrt(error1 * error1 + error2 * error2)
|
val error = Math.sqrt(error1 * error1 + error2 * error2)
|
||||||
builder.row(channel, value, error)
|
builder.row(channel, value, error)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
@ -32,10 +32,18 @@ import inr.numass.data.api.*
|
|||||||
import inr.numass.data.api.NumassPoint.Companion.HV_KEY
|
import inr.numass.data.api.NumassPoint.Companion.HV_KEY
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
import java.util.stream.Stream
|
import kotlin.collections.List
|
||||||
import kotlin.math.sqrt
|
import kotlin.collections.asSequence
|
||||||
|
import kotlin.collections.count
|
||||||
|
import kotlin.collections.first
|
||||||
|
import kotlin.collections.map
|
||||||
|
import kotlin.collections.set
|
||||||
|
import kotlin.collections.sortBy
|
||||||
|
import kotlin.collections.sumBy
|
||||||
|
import kotlin.collections.sumByDouble
|
||||||
|
import kotlin.collections.toMutableList
|
||||||
|
import kotlin.math.*
|
||||||
import kotlin.streams.asSequence
|
import kotlin.streams.asSequence
|
||||||
import kotlin.streams.asStream
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,10 +51,19 @@ import kotlin.streams.asStream
|
|||||||
* Created by darksnake on 11.07.2017.
|
* Created by darksnake on 11.07.2017.
|
||||||
*/
|
*/
|
||||||
@ValueDefs(
|
@ValueDefs(
|
||||||
ValueDef(key = "separateParallelBlocks", type = [ValueType.BOOLEAN], info = "If true, then parallel blocks will be forced to be evaluated separately"),
|
ValueDef(
|
||||||
ValueDef(key = "chunkSize", type = [ValueType.NUMBER], def = "-1", info = "The number of events in chunk to split the chain into. If negative, no chunks are used")
|
key = "separateParallelBlocks",
|
||||||
|
type = [ValueType.BOOLEAN],
|
||||||
|
info = "If true, then parallel blocks will be forced to be evaluated separately"
|
||||||
|
),
|
||||||
|
ValueDef(
|
||||||
|
key = "chunkSize",
|
||||||
|
type = [ValueType.NUMBER],
|
||||||
|
def = "-1",
|
||||||
|
info = "The number of events in chunk to split the chain into. If negative, no chunks are used"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
class TimeAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(processor) {
|
open class TimeAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(processor) {
|
||||||
|
|
||||||
override fun analyze(block: NumassBlock, config: Meta): Values {
|
override fun analyze(block: NumassBlock, config: Meta): Values {
|
||||||
//In case points inside points
|
//In case points inside points
|
||||||
@ -54,27 +71,33 @@ class TimeAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(proces
|
|||||||
return analyzeParent(block, config)
|
return analyzeParent(block, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val loChannel = config.getInt("window.lo", 0)
|
|
||||||
val upChannel = config.getInt("window.up", Integer.MAX_VALUE)
|
|
||||||
val t0 = getT0(block, config).toLong()
|
val t0 = getT0(block, config).toLong()
|
||||||
|
|
||||||
val chunkSize = config.getInt("chunkSize", -1)
|
val chunkSize = config.getInt("chunkSize", -1)
|
||||||
|
|
||||||
val res = if (chunkSize > 0) {
|
val count = super.getEvents(block, config).count()
|
||||||
getEventsWithDelay(block, config)
|
val length = block.length.toNanos().toDouble() / 1e9
|
||||||
.chunked(chunkSize) { analyzeSequence(it.asSequence(), t0) }
|
|
||||||
.toList()
|
val res = when {
|
||||||
.mean(config.getEnum("mean", WEIGHTED))
|
count < 1000 -> ValueMap.ofPairs(
|
||||||
} else {
|
LENGTH_KEY to length,
|
||||||
analyzeSequence(getEventsWithDelay(block, config), t0)
|
COUNT_KEY to count,
|
||||||
|
COUNT_RATE_KEY to count.toDouble() / length,
|
||||||
|
COUNT_RATE_ERROR_KEY to sqrt(count.toDouble()) / length
|
||||||
|
)
|
||||||
|
chunkSize > 0 -> getEventsWithDelay(block, config)
|
||||||
|
.chunked(chunkSize) { analyzeSequence(it.asSequence(), t0) }
|
||||||
|
.toList()
|
||||||
|
.mean(config.getEnum("mean", WEIGHTED))
|
||||||
|
else -> analyzeSequence(getEventsWithDelay(block, config), t0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ValueMap.Builder(res)
|
return ValueMap.Builder(res)
|
||||||
.putValue(NumassAnalyzer.WINDOW_KEY, arrayOf(loChannel, upChannel))
|
.putValue("blockLength", length)
|
||||||
.putValue(NumassAnalyzer.TIME_KEY, block.startTime)
|
.putValue(NumassAnalyzer.WINDOW_KEY, config.getRange())
|
||||||
.putValue(T0_KEY, t0.toDouble() / 1000.0)
|
.putValue(NumassAnalyzer.TIME_KEY, block.startTime)
|
||||||
.build()
|
.putValue(T0_KEY, t0.toDouble() / 1000.0)
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -82,22 +105,27 @@ class TimeAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(proces
|
|||||||
val totalN = AtomicLong(0)
|
val totalN = AtomicLong(0)
|
||||||
val totalT = AtomicLong(0)
|
val totalT = AtomicLong(0)
|
||||||
sequence.filter { pair -> pair.second >= t0 }
|
sequence.filter { pair -> pair.second >= t0 }
|
||||||
.forEach { pair ->
|
.forEach { pair ->
|
||||||
totalN.incrementAndGet()
|
totalN.incrementAndGet()
|
||||||
//TODO add progress listener here
|
//TODO add progress listener here
|
||||||
totalT.addAndGet(pair.second)
|
totalT.addAndGet(pair.second)
|
||||||
}
|
}
|
||||||
|
|
||||||
val countRate = 1e6 * totalN.get() / (totalT.get() / 1000 - t0 * totalN.get() / 1000)//1e9 / (totalT.get() / totalN.get() - t0);
|
if (totalN.toInt() == 0) {
|
||||||
val countRateError = countRate / Math.sqrt(totalN.get().toDouble())
|
error("Zero number of intervals")
|
||||||
|
}
|
||||||
|
|
||||||
|
val countRate =
|
||||||
|
1e6 * totalN.get() / (totalT.get() / 1000 - t0 * totalN.get() / 1000)//1e9 / (totalT.get() / totalN.get() - t0);
|
||||||
|
val countRateError = countRate / sqrt(totalN.get().toDouble())
|
||||||
val length = totalT.get() / 1e9
|
val length = totalT.get() / 1e9
|
||||||
val count = (length * countRate).toLong()
|
val count = (length * countRate).toLong()
|
||||||
|
|
||||||
return ValueMap.ofPairs(
|
return ValueMap.ofPairs(
|
||||||
NumassAnalyzer.LENGTH_KEY to length,
|
LENGTH_KEY to length,
|
||||||
NumassAnalyzer.COUNT_KEY to count,
|
COUNT_KEY to count,
|
||||||
NumassAnalyzer.COUNT_RATE_KEY to countRate,
|
COUNT_RATE_KEY to countRate,
|
||||||
NumassAnalyzer.COUNT_RATE_ERROR_KEY to countRateError
|
COUNT_RATE_ERROR_KEY to countRateError
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -128,45 +156,53 @@ class TimeAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(proces
|
|||||||
|
|
||||||
if (this.isEmpty()) {
|
if (this.isEmpty()) {
|
||||||
return ValueMap.Builder()
|
return ValueMap.Builder()
|
||||||
.putValue(LENGTH_KEY, 0)
|
.putValue(LENGTH_KEY, 0)
|
||||||
.putValue(COUNT_KEY, 0)
|
.putValue(COUNT_KEY, 0)
|
||||||
.putValue(COUNT_RATE_KEY, 0)
|
.putValue(COUNT_RATE_KEY, 0)
|
||||||
.putValue(COUNT_RATE_ERROR_KEY, 0)
|
.putValue(COUNT_RATE_ERROR_KEY, 0)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
val totalTime = sumByDouble { it.getDouble(LENGTH_KEY) }
|
val totalTime = sumByDouble { it.getDouble(LENGTH_KEY) }
|
||||||
|
|
||||||
val (countRate, countRateDispersion) = when (method) {
|
val (countRate, countRateDispersion) = when (method) {
|
||||||
ARITHMETIC -> Pair(
|
ARITHMETIC -> Pair(
|
||||||
sumByDouble { it.getDouble(COUNT_RATE_KEY) } / size,
|
sumByDouble { it.getDouble(COUNT_RATE_KEY) } / size,
|
||||||
sumByDouble { Math.pow(it.getDouble(COUNT_RATE_ERROR_KEY), 2.0) } / size / size
|
sumByDouble { it.getDouble(COUNT_RATE_ERROR_KEY).pow(2.0) } / size / size
|
||||||
)
|
)
|
||||||
WEIGHTED -> Pair(
|
WEIGHTED -> Pair(
|
||||||
sumByDouble { it.getDouble(COUNT_RATE_KEY) * it.getDouble(LENGTH_KEY) } / totalTime,
|
sumByDouble { it.getDouble(COUNT_RATE_KEY) * it.getDouble(LENGTH_KEY) } / totalTime,
|
||||||
sumByDouble { Math.pow(it.getDouble(COUNT_RATE_ERROR_KEY) * it.getDouble(LENGTH_KEY) / totalTime, 2.0) }
|
sumByDouble { (it.getDouble(COUNT_RATE_ERROR_KEY) * it.getDouble(LENGTH_KEY) / totalTime).pow(2.0) }
|
||||||
)
|
)
|
||||||
GEOMETRIC -> {
|
GEOMETRIC -> {
|
||||||
val mean = Math.exp(sumByDouble { Math.log(it.getDouble(COUNT_RATE_KEY)) } / size)
|
val mean = exp(sumByDouble { ln(it.getDouble(COUNT_RATE_KEY)) } / size)
|
||||||
val variance = Math.pow(mean / size, 2.0) * sumByDouble { Math.pow(it.getDouble(COUNT_RATE_ERROR_KEY) / it.getDouble(COUNT_RATE_KEY), 2.0) }
|
val variance = (mean / size).pow(2.0) * sumByDouble {
|
||||||
|
(it.getDouble(COUNT_RATE_ERROR_KEY) / it.getDouble(
|
||||||
|
COUNT_RATE_KEY
|
||||||
|
)).pow(2.0)
|
||||||
|
}
|
||||||
Pair(mean, variance)
|
Pair(mean, variance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ValueMap.Builder(first())
|
return ValueMap.Builder(first())
|
||||||
.putValue(LENGTH_KEY, totalTime)
|
.putValue(LENGTH_KEY, totalTime)
|
||||||
.putValue(COUNT_KEY, sumBy { it.getInt(COUNT_KEY) })
|
.putValue(COUNT_KEY, sumBy { it.getInt(COUNT_KEY) })
|
||||||
.putValue(COUNT_RATE_KEY, countRate)
|
.putValue(COUNT_RATE_KEY, countRate)
|
||||||
.putValue(COUNT_RATE_ERROR_KEY, sqrt(countRateDispersion))
|
.putValue(COUNT_RATE_ERROR_KEY, sqrt(countRateDispersion))
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ValueDefs(
|
@ValueDefs(
|
||||||
ValueDef(key = "t0", type = arrayOf(ValueType.NUMBER), info = "Constant t0 cut"),
|
ValueDef(key = "t0", type = arrayOf(ValueType.NUMBER), info = "Constant t0 cut"),
|
||||||
ValueDef(key = "t0.crFraction", type = arrayOf(ValueType.NUMBER), info = "The relative fraction of events that should be removed by time cut"),
|
ValueDef(
|
||||||
ValueDef(key = "t0.min", type = arrayOf(ValueType.NUMBER), def = "0", info = "Minimal t0")
|
key = "t0.crFraction",
|
||||||
|
type = arrayOf(ValueType.NUMBER),
|
||||||
|
info = "The relative fraction of events that should be removed by time cut"
|
||||||
|
),
|
||||||
|
ValueDef(key = "t0.min", type = arrayOf(ValueType.NUMBER), def = "0", info = "Minimal t0")
|
||||||
)
|
)
|
||||||
private fun getT0(block: NumassBlock, meta: Meta): Int {
|
protected fun getT0(block: NumassBlock, meta: Meta): Int {
|
||||||
return if (meta.hasValue("t0")) {
|
return if (meta.hasValue("t0")) {
|
||||||
meta.getInt("t0")
|
meta.getInt("t0")
|
||||||
} else if (meta.hasMeta("t0")) {
|
} else if (meta.hasMeta("t0")) {
|
||||||
@ -175,7 +211,7 @@ class TimeAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(proces
|
|||||||
if (cr < meta.getDouble("t0.minCR", 0.0)) {
|
if (cr < meta.getDouble("t0.minCR", 0.0)) {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
Math.max(-1e9 / cr * Math.log(1.0 - fraction), meta.getDouble("t0.min", 0.0)).toInt()
|
max(-1e9 / cr * ln(1.0 - fraction), meta.getDouble("t0.min", 0.0)).toInt()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
@ -200,16 +236,16 @@ class TimeAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(proces
|
|||||||
*/
|
*/
|
||||||
fun getEventsWithDelay(block: NumassBlock, config: Meta): Sequence<Pair<NumassEvent, Long>> {
|
fun getEventsWithDelay(block: NumassBlock, config: Meta): Sequence<Pair<NumassEvent, Long>> {
|
||||||
val inverted = config.getBoolean("inverted", true)
|
val inverted = config.getBoolean("inverted", true)
|
||||||
val events: Stream<NumassEvent> = super.getEvents(block, config).let { stream ->
|
//range is included in super.getEvents
|
||||||
if (block is ParentBlock && !block.isSequential) {
|
val events = super.getEvents(block, config).toMutableList()
|
||||||
stream.sorted(compareBy { it.timeOffset })
|
|
||||||
} else {
|
if (config.getBoolean("sortEvents", false) || (block is ParentBlock && !block.isSequential)) {
|
||||||
stream
|
//sort in place if needed
|
||||||
}
|
events.sortBy { it.timeOffset }
|
||||||
}
|
}
|
||||||
|
|
||||||
return events.asSequence().zipWithNext { prev, next ->
|
return events.asSequence().zipWithNext { prev, next ->
|
||||||
val delay = Math.max(next.timeOffset - prev.timeOffset, 0)
|
val delay = max(next.timeOffset - prev.timeOffset, 0)
|
||||||
if (inverted) {
|
if (inverted) {
|
||||||
Pair(next, delay)
|
Pair(next, delay)
|
||||||
} else {
|
} else {
|
||||||
@ -225,35 +261,37 @@ class TimeAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(proces
|
|||||||
* @param meta
|
* @param meta
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
override fun getEvents(block: NumassBlock, meta: Meta): Stream<NumassEvent> {
|
override fun getEvents(block: NumassBlock, meta: Meta): List<NumassEvent> {
|
||||||
val t0 = getT0(block, meta).toLong()
|
val t0 = getT0(block, meta).toLong()
|
||||||
return getEventsWithDelay(block, meta).filter { pair -> pair.second >= t0 }.asStream().map { it.first }
|
return getEventsWithDelay(block, meta)
|
||||||
|
.filter { pair -> pair.second >= t0 }
|
||||||
|
.map { it.first }.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun getTableFormat(config: Meta): TableFormat {
|
public override fun getTableFormat(config: Meta): TableFormat {
|
||||||
return TableFormatBuilder()
|
return TableFormatBuilder()
|
||||||
.addNumber(HV_KEY, X_VALUE_KEY)
|
.addNumber(HV_KEY, X_VALUE_KEY)
|
||||||
.addNumber(NumassAnalyzer.LENGTH_KEY)
|
.addNumber(LENGTH_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_KEY)
|
.addNumber(COUNT_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_RATE_KEY, Y_VALUE_KEY)
|
.addNumber(COUNT_RATE_KEY, Y_VALUE_KEY)
|
||||||
.addNumber(NumassAnalyzer.COUNT_RATE_ERROR_KEY, Y_ERROR_KEY)
|
.addNumber(COUNT_RATE_ERROR_KEY, Y_ERROR_KEY)
|
||||||
.addColumn(NumassAnalyzer.WINDOW_KEY)
|
.addColumn(NumassAnalyzer.WINDOW_KEY)
|
||||||
.addTime()
|
.addTime()
|
||||||
.addNumber(T0_KEY)
|
.addNumber(T0_KEY)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val T0_KEY = "t0"
|
const val T0_KEY = "t0"
|
||||||
|
|
||||||
val NAME_LIST = arrayOf(
|
val NAME_LIST = arrayOf(
|
||||||
NumassAnalyzer.LENGTH_KEY,
|
LENGTH_KEY,
|
||||||
NumassAnalyzer.COUNT_KEY,
|
COUNT_KEY,
|
||||||
NumassAnalyzer.COUNT_RATE_KEY,
|
COUNT_RATE_KEY,
|
||||||
NumassAnalyzer.COUNT_RATE_ERROR_KEY,
|
COUNT_RATE_ERROR_KEY,
|
||||||
NumassAnalyzer.WINDOW_KEY,
|
NumassAnalyzer.WINDOW_KEY,
|
||||||
NumassAnalyzer.TIME_KEY,
|
NumassAnalyzer.TIME_KEY,
|
||||||
T0_KEY
|
T0_KEY
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import java.nio.file.Path
|
|||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
import kotlin.streams.asStream
|
import java.util.stream.StreamSupport
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by darksnake on 08.07.2017.
|
* Created by darksnake on 08.07.2017.
|
||||||
@ -47,11 +47,12 @@ class ClassicNumassPoint(private val envelope: Envelope) : NumassPoint {
|
|||||||
|
|
||||||
//TODO split blocks using meta
|
//TODO split blocks using meta
|
||||||
private inner class ClassicBlock(
|
private inner class ClassicBlock(
|
||||||
override val startTime: Instant,
|
override val startTime: Instant,
|
||||||
override val length: Duration) : NumassBlock, Iterable<NumassEvent> {
|
override val length: Duration
|
||||||
|
) : NumassBlock, Iterable<NumassEvent> {
|
||||||
|
|
||||||
override val events: Stream<NumassEvent>
|
override val events: Stream<NumassEvent>
|
||||||
get() = this.asSequence().asStream()
|
get() = StreamSupport.stream(this.spliterator(), false)
|
||||||
|
|
||||||
override fun iterator(): Iterator<NumassEvent> {
|
override fun iterator(): Iterator<NumassEvent> {
|
||||||
val timeCoef = envelope.meta.getDouble("time_coeff", 50.0)
|
val timeCoef = envelope.meta.getDouble("time_coeff", 50.0)
|
||||||
@ -78,7 +79,8 @@ class ClassicNumassPoint(private val envelope: Envelope) : NumassPoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
LoggerFactory.getLogger(this@ClassicNumassPoint.javaClass).error("Unexpected IOException when reading block", e)
|
LoggerFactory.getLogger(this@ClassicNumassPoint.javaClass)
|
||||||
|
.error("Unexpected IOException when reading block", e)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,11 +35,11 @@ class NumassDataFactory : DataFactory<NumassSet>(NumassSet::class.java) {
|
|||||||
|
|
||||||
override fun fill(builder: DataNodeEditor<NumassSet>, context: Context, meta: Meta) {
|
override fun fill(builder: DataNodeEditor<NumassSet>, context: Context, meta: Meta) {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
val storage = NumassDirectory.read(context,meta.getString("path")) as Storage
|
val storage = NumassDirectory.read(context, meta.getString("path")) as Storage
|
||||||
storage.sequence().forEach { pair ->
|
storage.sequence().forEach { pair ->
|
||||||
val value = pair.second
|
val value = pair.second
|
||||||
if (value is NumassSet) {
|
if (value is NumassSet) {
|
||||||
builder.putStatic(pair.first.unescaped, value)
|
builder.putStatic(pair.first.unescaped, value, value.meta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,10 +44,10 @@ import kotlin.streams.toList
|
|||||||
* @author darksnake
|
* @author darksnake
|
||||||
*/
|
*/
|
||||||
class NumassDataLoader(
|
class NumassDataLoader(
|
||||||
override val context: Context,
|
override val context: Context,
|
||||||
override val parent: StorageElement?,
|
override val parent: StorageElement?,
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val path: Path
|
override val path: Path
|
||||||
) : Loader<NumassPoint>, NumassSet, Provider, FileStorageElement {
|
) : Loader<NumassPoint>, NumassSet, Provider, FileStorageElement {
|
||||||
|
|
||||||
override val type: KClass<NumassPoint> = NumassPoint::class
|
override val type: KClass<NumassPoint> = NumassPoint::class
|
||||||
@ -63,26 +63,24 @@ class NumassDataLoader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getHvData(): Table? {
|
override suspend fun getHvData(): Table? {
|
||||||
val hvEnvelope = path.resolve(HV_FRAGMENT_NAME)?.let {
|
val hvEnvelope = path.resolve(HV_FRAGMENT_NAME).let {
|
||||||
NumassEnvelopeType.infer(it)?.reader?.read(it) ?: error("Can't read hv file")
|
NumassEnvelopeType.infer(it)?.reader?.read(it) ?: error("Can't read hv file")
|
||||||
}
|
}
|
||||||
return hvEnvelope?.let {
|
return try {
|
||||||
try {
|
ColumnedDataReader(hvEnvelope.data.stream, "timestamp", "block", "value").toTable()
|
||||||
ColumnedDataReader(it.data.stream, "timestamp", "block", "value").toTable()
|
} catch (ex: IOException) {
|
||||||
} catch (ex: IOException) {
|
LoggerFactory.getLogger(javaClass).error("Failed to load HV data from file", ex)
|
||||||
LoggerFactory.getLogger(javaClass).error("Failed to load HV data from file", ex)
|
null
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private val pointEnvelopes: List<Envelope> by lazy {
|
private val pointEnvelopes: List<Envelope> by lazy {
|
||||||
Files.list(path)
|
Files.list(path)
|
||||||
.filter { it.fileName.toString().startsWith(POINT_FRAGMENT_NAME) }
|
.filter { it.fileName.toString().startsWith(POINT_FRAGMENT_NAME) }
|
||||||
.map {
|
.map {
|
||||||
NumassEnvelopeType.infer(it)?.reader?.read(it) ?: error("Can't read point file")
|
NumassEnvelopeType.infer(it)?.reader?.read(it) ?: error("Can't read point file")
|
||||||
}.toList()
|
}.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
val isReversed: Boolean
|
val isReversed: Boolean
|
||||||
@ -189,4 +187,8 @@ class NumassDataLoader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun Context.readNumassSet(path:Path):NumassDataLoader{
|
||||||
|
return NumassDataLoader(this,null,path.fileName.toString(),path)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package inr.numass.data;
|
|
||||||
|
|
||||||
message Point {
|
|
||||||
// A single channel for multichannel detector readout
|
|
||||||
message Channel {
|
|
||||||
//A continuous measurement block
|
|
||||||
message Block {
|
|
||||||
// Raw data frame
|
|
||||||
message Frame {
|
|
||||||
uint64 time = 1; // Time in nanos from the beginning of the block
|
|
||||||
bytes data = 2; // Frame data as an array of int16 mesured in arbitrary channels
|
|
||||||
}
|
|
||||||
// Event block obtained directly from device of from frame analysis
|
|
||||||
// In order to save space, times and amplitudes are in separate arrays.
|
|
||||||
// Amplitude and time with the same index correspond to the same event
|
|
||||||
message Events {
|
|
||||||
repeated uint64 times = 1; // Array of time in nanos from the beginning of the block
|
|
||||||
repeated uint64 amplitudes = 2; // Array of amplitudes of events in channels
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64 time = 1; // Block start in epoch nanos
|
|
||||||
repeated Frame frames = 2; // Frames array
|
|
||||||
Events events = 3; // Events array
|
|
||||||
uint64 length = 4; // block size in nanos. If missing, take from meta.
|
|
||||||
uint64 bin_size = 5; // tick size in nanos. Obsolete, to be removed
|
|
||||||
}
|
|
||||||
uint64 id = 1; // The number of measuring channel
|
|
||||||
repeated Block blocks = 2; // Blocks
|
|
||||||
}
|
|
||||||
repeated Channel channels = 1; // Array of measuring channels
|
|
||||||
}
|
|
@ -5,6 +5,12 @@ plugins {
|
|||||||
|
|
||||||
apply plugin: 'kotlin'
|
apply plugin: 'kotlin'
|
||||||
|
|
||||||
|
//apply plugin: 'org.openjfx.javafxplugin'
|
||||||
|
//
|
||||||
|
//javafx {
|
||||||
|
// modules = [ 'javafx.controls' ]
|
||||||
|
//}
|
||||||
|
|
||||||
//if (!hasProperty('mainClass')) {
|
//if (!hasProperty('mainClass')) {
|
||||||
// ext.mainClass = 'inr.numass.LaunchGrindShell'
|
// ext.mainClass = 'inr.numass.LaunchGrindShell'
|
||||||
//}
|
//}
|
||||||
@ -30,6 +36,8 @@ dependencies {
|
|||||||
compile group: 'commons-cli', name: 'commons-cli', version: '1.+'
|
compile group: 'commons-cli', name: 'commons-cli', version: '1.+'
|
||||||
compile group: 'commons-io', name: 'commons-io', version: '2.+'
|
compile group: 'commons-io', name: 'commons-io', version: '2.+'
|
||||||
compile project(':numass-core')
|
compile project(':numass-core')
|
||||||
|
compile project(':numass-core:numass-signal-processing')
|
||||||
|
compileOnly "org.jetbrains.kotlin:kotlin-main-kts:1.3.21"
|
||||||
compile "hep.dataforge:dataforge-minuit" //project(':dataforge-stat:dataforge-minuit')
|
compile "hep.dataforge:dataforge-minuit" //project(':dataforge-stat:dataforge-minuit')
|
||||||
compile "hep.dataforge:grind-terminal" //project(':dataforge-grind:grind-terminal')
|
compile "hep.dataforge:grind-terminal" //project(':dataforge-grind:grind-terminal')
|
||||||
compile "hep.dataforge:dataforge-gui"
|
compile "hep.dataforge:dataforge-gui"
|
||||||
|
@ -8,6 +8,7 @@ import hep.dataforge.grind.workspace.GrindWorkspace
|
|||||||
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
||||||
import hep.dataforge.workspace.FileBasedWorkspace
|
import hep.dataforge.workspace.FileBasedWorkspace
|
||||||
import hep.dataforge.workspace.Workspace
|
import hep.dataforge.workspace.Workspace
|
||||||
|
import groovy.cli.commons.CliBuilder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by darksnake on 29-Aug-16.
|
* Created by darksnake on 29-Aug-16.
|
||||||
|
@ -41,11 +41,11 @@ import org.apache.commons.math3.util.FastMath
|
|||||||
* @author Alexander Nozik
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
@PluginDef(
|
@PluginDef(
|
||||||
group = "inr.numass",
|
group = "inr.numass",
|
||||||
name = "numass",
|
name = "numass",
|
||||||
dependsOn = ["hep.dataforge:functions", "hep.dataforge:MINUIT", "hep.dataforge:actions"],
|
dependsOn = ["hep.dataforge:functions", "hep.dataforge:MINUIT", "hep.dataforge:actions"],
|
||||||
support = false,
|
support = false,
|
||||||
info = "Numass data analysis tools"
|
info = "Numass data analysis tools"
|
||||||
)
|
)
|
||||||
class NumassPlugin : BasicPlugin() {
|
class NumassPlugin : BasicPlugin() {
|
||||||
|
|
||||||
@ -58,20 +58,22 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val tasks = listOf(
|
private val tasks = listOf(
|
||||||
NumassFitScanSummaryTask,
|
NumassFitScanSummaryTask,
|
||||||
NumassFitSummaryTask,
|
NumassFitSummaryTask,
|
||||||
selectTask,
|
selectTask,
|
||||||
analyzeTask,
|
analyzeTask,
|
||||||
mergeTask,
|
mergeTask,
|
||||||
mergeEmptyTask,
|
mergeEmptyTask,
|
||||||
monitorTableTask,
|
monitorTableTask,
|
||||||
subtractEmptyTask,
|
subtractEmptyTask,
|
||||||
transformTask,
|
transformTask,
|
||||||
filterTask,
|
filterTask,
|
||||||
fitTask,
|
fitTask,
|
||||||
plotFitTask,
|
plotFitTask,
|
||||||
histogramTask,
|
histogramTask,
|
||||||
fitScanTask
|
fitScanTask,
|
||||||
|
sliceTask,
|
||||||
|
subThresholdTask
|
||||||
)
|
)
|
||||||
|
|
||||||
@Provides(Task.TASK_TARGET)
|
@Provides(Task.TASK_TARGET)
|
||||||
@ -109,7 +111,10 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
BivariateFunction { E: Double, U: Double ->
|
BivariateFunction { E: Double, U: Double ->
|
||||||
val D = E - U
|
val D = E - U
|
||||||
val factor = 7.33 - E / 1000.0 / 3.0
|
val factor = 7.33 - E / 1000.0 / 3.0
|
||||||
return@BivariateFunction 1.0 - (3.05346E-7 * D - 5.45738E-10 * Math.pow(D, 2.0) - 6.36105E-14 * Math.pow(D, 3.0)) * factor
|
return@BivariateFunction 1.0 - (3.05346E-7 * D - 5.45738E-10 * Math.pow(
|
||||||
|
D,
|
||||||
|
2.0
|
||||||
|
) - 6.36105E-14 * Math.pow(D, 3.0)) * factor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,11 +268,19 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
val transmissionFile = an.getString("transFile")
|
val transmissionFile = an.getString("transFile")
|
||||||
|
|
||||||
return TransmissionInterpolator
|
return TransmissionInterpolator
|
||||||
.fromFile(context, transmissionFile, transXName, transYName, nSmooth, w, stitchBorder)
|
.fromFile(context, transmissionFile, transXName, transYName, nSmooth, w, stitchBorder)
|
||||||
} else if (an.hasMeta("transBuildAction")) {
|
} else if (an.hasMeta("transBuildAction")) {
|
||||||
val transBuild = an.getMeta("transBuildAction")
|
val transBuild = an.getMeta("transBuildAction")
|
||||||
try {
|
try {
|
||||||
return TransmissionInterpolator.fromAction(context, transBuild, transXName, transYName, nSmooth, w, stitchBorder)
|
return TransmissionInterpolator.fromAction(
|
||||||
|
context,
|
||||||
|
transBuild,
|
||||||
|
transXName,
|
||||||
|
transYName,
|
||||||
|
nSmooth,
|
||||||
|
w,
|
||||||
|
stitchBorder
|
||||||
|
)
|
||||||
} catch (ex: InterruptedException) {
|
} catch (ex: InterruptedException) {
|
||||||
throw RuntimeException("Transmission builder failed")
|
throw RuntimeException("Transmission builder failed")
|
||||||
}
|
}
|
||||||
@ -281,7 +294,11 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
return if (an.hasMeta(ValuesAdapter.ADAPTER_KEY)) {
|
return if (an.hasMeta(ValuesAdapter.ADAPTER_KEY)) {
|
||||||
Adapters.buildAdapter(an.getMeta(ValuesAdapter.ADAPTER_KEY))
|
Adapters.buildAdapter(an.getMeta(ValuesAdapter.ADAPTER_KEY))
|
||||||
} else {
|
} else {
|
||||||
Adapters.buildXYAdapter(NumassPoint.HV_KEY, NumassAnalyzer.COUNT_RATE_KEY, NumassAnalyzer.COUNT_RATE_ERROR_KEY)
|
Adapters.buildXYAdapter(
|
||||||
|
NumassPoint.HV_KEY,
|
||||||
|
NumassAnalyzer.COUNT_RATE_KEY,
|
||||||
|
NumassAnalyzer.COUNT_RATE_ERROR_KEY
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +320,13 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun displayChart(title: String, context: Context = Global, width: Double = 800.0, height: Double = 600.0, meta: Meta = Meta.empty()): JFreeChartFrame {
|
fun displayChart(
|
||||||
|
title: String,
|
||||||
|
context: Context = Global,
|
||||||
|
width: Double = 800.0,
|
||||||
|
height: Double = 600.0,
|
||||||
|
meta: Meta = Meta.empty()
|
||||||
|
): JFreeChartFrame {
|
||||||
val frame = JFreeChartFrame()
|
val frame = JFreeChartFrame()
|
||||||
frame.configure(meta)
|
frame.configure(meta)
|
||||||
frame.configureValue("title", title)
|
frame.configureValue("title", title)
|
||||||
|
@ -48,6 +48,7 @@ import java.awt.Font
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.lang.Math.*
|
import java.lang.Math.*
|
||||||
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,11 +109,11 @@ object NumassUtils {
|
|||||||
fun writeEnvelope(stream: OutputStream, meta: Meta, dataWriter: (OutputStream) -> Unit) {
|
fun writeEnvelope(stream: OutputStream, meta: Meta, dataWriter: (OutputStream) -> Unit) {
|
||||||
try {
|
try {
|
||||||
TaglessEnvelopeType.INSTANCE.writer.write(
|
TaglessEnvelopeType.INSTANCE.writer.write(
|
||||||
stream,
|
stream,
|
||||||
EnvelopeBuilder()
|
EnvelopeBuilder()
|
||||||
.meta(meta)
|
.meta(meta)
|
||||||
.data(dataWriter)
|
.data(dataWriter)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
stream.flush()
|
stream.flush()
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
@ -148,10 +149,10 @@ object NumassUtils {
|
|||||||
builder.name = set.name
|
builder.name = set.name
|
||||||
set.points.forEach { point ->
|
set.points.forEach { point ->
|
||||||
val pointMeta = MetaBuilder("point")
|
val pointMeta = MetaBuilder("point")
|
||||||
.putValue("voltage", point.voltage)
|
.putValue("voltage", point.voltage)
|
||||||
.putValue("index", point.meta.getInt("external_meta.point_index", -1))
|
.putValue("index", point.meta.getInt("external_meta.point_index", -1))
|
||||||
.putValue("run", point.meta.getString("external_meta.session", ""))
|
.putValue("run", point.meta.getString("external_meta.session", ""))
|
||||||
.putValue("group", point.meta.getString("external_meta.group", ""))
|
.putValue("group", point.meta.getString("external_meta.group", ""))
|
||||||
val pointName = "point_" + point.meta.getInt("external_meta.point_index", point.hashCode())
|
val pointName = "point_" + point.meta.getInt("external_meta.point_index", point.hashCode())
|
||||||
builder.putData(pointName, point, pointMeta)
|
builder.putData(pointName, point, pointMeta)
|
||||||
}
|
}
|
||||||
@ -176,8 +177,8 @@ object NumassUtils {
|
|||||||
fun getFSS(context: Context, meta: Meta): FSS? {
|
fun getFSS(context: Context, meta: Meta): FSS? {
|
||||||
return if (meta.getBoolean("useFSS", true)) {
|
return if (meta.getBoolean("useFSS", true)) {
|
||||||
val fssBinary: Binary? = meta.optString("fssFile")
|
val fssBinary: Binary? = meta.optString("fssFile")
|
||||||
.map { fssFile -> context.getFile(fssFile).binary }
|
.map { fssFile -> context.getFile(fssFile).binary }
|
||||||
.orElse(context.getResource("data/FS.txt"))
|
.orElse(context.getResource("data/FS.txt"))
|
||||||
fssBinary?.let { FSS(it.stream) } ?: throw RuntimeException("Could not load FSS file")
|
fssBinary?.let { FSS(it.stream) } ?: throw RuntimeException("Could not load FSS file")
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
@ -189,16 +190,17 @@ fun getFSS(context: Context, meta: Meta): FSS? {
|
|||||||
* Evaluate groovy expression using numass point as parameter
|
* Evaluate groovy expression using numass point as parameter
|
||||||
*
|
*
|
||||||
* @param expression
|
* @param expression
|
||||||
* @param point
|
* @param values
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun pointExpression(expression: String, point: Values): Double {
|
fun pointExpression(expression: String, values: Values): Double {
|
||||||
val exprParams = HashMap<String, Any>()
|
val exprParams = HashMap<String, Any>()
|
||||||
//Adding all point values to expression parameters
|
//Adding all point values to expression parameters
|
||||||
point.names.forEach { name -> exprParams[name] = point.getValue(name).value }
|
values.names.forEach { name -> exprParams[name] = values.getValue(name).value }
|
||||||
//Adding aliases for commonly used parameters
|
//Adding aliases for commonly used parameters
|
||||||
exprParams["T"] = point.getDouble("length")
|
exprParams["T"] = values.getDouble("length")
|
||||||
exprParams["U"] = point.getDouble("voltage")
|
exprParams["U"] = values.getDouble("voltage")
|
||||||
|
exprParams["time"] = values.optTime("timestamp").orElse(Instant.EPOCH).epochSecond
|
||||||
|
|
||||||
return ExpressionUtils.function(expression, exprParams)
|
return ExpressionUtils.function(expression, exprParams)
|
||||||
}
|
}
|
||||||
@ -212,8 +214,8 @@ fun JFreeChartFrame.addSetMarkers(sets: Collection<NumassSet>) {
|
|||||||
sets.stream().forEach { set ->
|
sets.stream().forEach { set ->
|
||||||
val start = set.startTime;
|
val start = set.startTime;
|
||||||
val stop = set.meta.optValue("end_time").map { it.time }
|
val stop = set.meta.optValue("end_time").map { it.time }
|
||||||
.orElse(start.plusSeconds(300))
|
.orElse(start.plusSeconds(300))
|
||||||
.minusSeconds(60)
|
.minusSeconds(60)
|
||||||
val marker = IntervalMarker(start.toEpochMilli().toDouble(), stop.toEpochMilli().toDouble(), paint)
|
val marker = IntervalMarker(start.toEpochMilli().toDouble(), stop.toEpochMilli().toDouble(), paint)
|
||||||
marker.label = set.name
|
marker.label = set.name
|
||||||
marker.labelFont = Font("Verdana", Font.BOLD, 20);
|
marker.labelFont = Font("Verdana", Font.BOLD, 20);
|
||||||
@ -230,15 +232,25 @@ fun subtractSpectrum(merge: Table, empty: Table, logger: Logger? = null): Table
|
|||||||
merge.rows.forEach { point ->
|
merge.rows.forEach { point ->
|
||||||
val pointBuilder = ValueMap.Builder(point)
|
val pointBuilder = ValueMap.Builder(point)
|
||||||
val referencePoint = empty.rows
|
val referencePoint = empty.rows
|
||||||
.filter { p -> Math.abs(p.getDouble(NumassPoint.HV_KEY) - point.getDouble(NumassPoint.HV_KEY)) < 0.1 }.findFirst()
|
.filter { p -> Math.abs(p.getDouble(NumassPoint.HV_KEY) - point.getDouble(NumassPoint.HV_KEY)) < 0.1 }
|
||||||
|
.findFirst()
|
||||||
if (referencePoint.isPresent) {
|
if (referencePoint.isPresent) {
|
||||||
pointBuilder.putValue(
|
pointBuilder.putValue(
|
||||||
NumassAnalyzer.COUNT_RATE_KEY,
|
NumassAnalyzer.COUNT_RATE_KEY,
|
||||||
Math.max(0.0, point.getDouble(NumassAnalyzer.COUNT_RATE_KEY) - referencePoint.get().getDouble(NumassAnalyzer.COUNT_RATE_KEY))
|
Math.max(
|
||||||
|
0.0,
|
||||||
|
point.getDouble(NumassAnalyzer.COUNT_RATE_KEY) - referencePoint.get().getDouble(NumassAnalyzer.COUNT_RATE_KEY)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
pointBuilder.putValue(
|
pointBuilder.putValue(
|
||||||
NumassAnalyzer.COUNT_RATE_ERROR_KEY,
|
NumassAnalyzer.COUNT_RATE_ERROR_KEY,
|
||||||
Math.sqrt(Math.pow(point.getDouble(NumassAnalyzer.COUNT_RATE_ERROR_KEY), 2.0) + Math.pow(referencePoint.get().getDouble(NumassAnalyzer.COUNT_RATE_ERROR_KEY), 2.0)))
|
Math.sqrt(
|
||||||
|
Math.pow(
|
||||||
|
point.getDouble(NumassAnalyzer.COUNT_RATE_ERROR_KEY),
|
||||||
|
2.0
|
||||||
|
) + Math.pow(referencePoint.get().getDouble(NumassAnalyzer.COUNT_RATE_ERROR_KEY), 2.0)
|
||||||
|
)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
logger?.warn("No reference point found for voltage = {}", point.getDouble(NumassPoint.HV_KEY))
|
logger?.warn("No reference point found for voltage = {}", point.getDouble(NumassPoint.HV_KEY))
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import hep.dataforge.values.ValueType.STRING
|
|||||||
import inr.numass.NumassUtils
|
import inr.numass.NumassUtils
|
||||||
import inr.numass.data.analyzers.NumassAnalyzer
|
import inr.numass.data.analyzers.NumassAnalyzer
|
||||||
import inr.numass.data.api.NumassSet
|
import inr.numass.data.api.NumassSet
|
||||||
|
import inr.numass.data.analyzers.SmartAnalyzer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The action performs the readout of data and collection of count rate into a table
|
* The action performs the readout of data and collection of count rate into a table
|
||||||
@ -25,7 +26,7 @@ import inr.numass.data.api.NumassSet
|
|||||||
object AnalyzeDataAction : OneToOneAction<NumassSet, Table>("numass.analyze", NumassSet::class.java, Table::class.java) {
|
object AnalyzeDataAction : OneToOneAction<NumassSet, Table>("numass.analyze", NumassSet::class.java, Table::class.java) {
|
||||||
override fun execute(context: Context, name: String, input: NumassSet, inputMeta: Laminate): Table {
|
override fun execute(context: Context, name: String, input: NumassSet, inputMeta: Laminate): Table {
|
||||||
//TODO add processor here
|
//TODO add processor here
|
||||||
val analyzer = NumassAnalyzer.DEFAULT_ANALYZER
|
val analyzer: NumassAnalyzer = SmartAnalyzer()
|
||||||
val res = analyzer.analyzeSet(input, inputMeta)
|
val res = analyzer.analyzeSet(input, inputMeta)
|
||||||
|
|
||||||
render(context, name, NumassUtils.wrap(res, inputMeta))
|
render(context, name, NumassUtils.wrap(res, inputMeta))
|
||||||
|
@ -45,12 +45,11 @@ object MergeDataAction : ManyToOneAction<Table, Table>("numass.merge", Table::cl
|
|||||||
|
|
||||||
override fun buildGroups(context: Context, input: DataNode<Table>, actionMeta: Meta): List<DataNode<Table>> {
|
override fun buildGroups(context: Context, input: DataNode<Table>, actionMeta: Meta): List<DataNode<Table>> {
|
||||||
val meta = inputMeta(context, input.meta, actionMeta)
|
val meta = inputMeta(context, input.meta, actionMeta)
|
||||||
val groups: List<DataNode<Table>> = if (meta.hasValue("grouping.byValue")) {
|
return if (meta.hasValue("grouping.byValue")) {
|
||||||
super.buildGroups(context, input, actionMeta)
|
super.buildGroups(context, input, actionMeta)
|
||||||
} else {
|
} else {
|
||||||
GroupBuilder.byValue(MERGE_NAME, meta.getString(MERGE_NAME, input.name)).group(input)
|
GroupBuilder.byValue(MERGE_NAME, meta.getString(MERGE_NAME, input.name)).group(input)
|
||||||
}
|
}
|
||||||
return groups
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun execute(context: Context, nodeName: String, data: Map<String, Table>, meta: Laminate): Table {
|
override fun execute(context: Context, nodeName: String, data: Map<String, Table>, meta: Laminate): Table {
|
||||||
|
@ -52,7 +52,7 @@ object TimeAnalyzerAction : OneToOneAction<NumassPoint, Table>("timeSpectrum",Nu
|
|||||||
|
|
||||||
val histogram = UnivariateHistogram.buildUniform(0.0, binSize * binNum, binSize)
|
val histogram = UnivariateHistogram.buildUniform(0.0, binSize * binNum, binSize)
|
||||||
.fill(analyzer
|
.fill(analyzer
|
||||||
.getEventsWithDelay(input, inputMeta)
|
.getEventsWithDelay(input, analyzerMeta)
|
||||||
.asStream()
|
.asStream()
|
||||||
.mapToDouble { it.second.toDouble() / 1000.0 }
|
.mapToDouble { it.second.toDouble() / 1000.0 }
|
||||||
).asTable()
|
).asTable()
|
||||||
@ -128,6 +128,8 @@ object TimeAnalyzerAction : OneToOneAction<NumassPoint, Table>("timeSpectrum",Nu
|
|||||||
val minT0 = inputMeta.getDouble("t0.min", 0.0)
|
val minT0 = inputMeta.getDouble("t0.min", 0.0)
|
||||||
val maxT0 = inputMeta.getDouble("t0.max", 1e9 / cr)
|
val maxT0 = inputMeta.getDouble("t0.max", 1e9 / cr)
|
||||||
val steps = inputMeta.getInt("t0.steps", 100)
|
val steps = inputMeta.getInt("t0.steps", 100)
|
||||||
|
val t0Step = inputMeta.getDouble("t0.step", (maxT0-minT0)/(steps - 1))
|
||||||
|
|
||||||
|
|
||||||
val norm = if (inputMeta.getBoolean("normalize", false)) {
|
val norm = if (inputMeta.getBoolean("normalize", false)) {
|
||||||
cr
|
cr
|
||||||
@ -135,7 +137,7 @@ object TimeAnalyzerAction : OneToOneAction<NumassPoint, Table>("timeSpectrum",Nu
|
|||||||
1.0
|
1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
(0..steps).map { minT0 + (maxT0 - minT0) / steps * it }.map { t ->
|
(0..steps).map { minT0 + t0Step * it }.map { t ->
|
||||||
val result = analyzer.analyze(input, analyzerMeta.builder.setValue("t0", t))
|
val result = analyzer.analyze(input, analyzerMeta.builder.setValue("t0", t))
|
||||||
|
|
||||||
if (Thread.currentThread().isInterrupted) {
|
if (Thread.currentThread().isInterrupted) {
|
||||||
|
@ -11,17 +11,17 @@ import hep.dataforge.isAnonymous
|
|||||||
import hep.dataforge.meta.Laminate
|
import hep.dataforge.meta.Laminate
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.MetaUtils
|
import hep.dataforge.meta.MetaUtils
|
||||||
import hep.dataforge.tables.ColumnFormat
|
import hep.dataforge.tables.*
|
||||||
import hep.dataforge.tables.ColumnTable
|
|
||||||
import hep.dataforge.tables.ListColumn
|
|
||||||
import hep.dataforge.tables.Table
|
|
||||||
import hep.dataforge.values.ValueType.NUMBER
|
import hep.dataforge.values.ValueType.NUMBER
|
||||||
import hep.dataforge.values.ValueType.STRING
|
import hep.dataforge.values.ValueType.STRING
|
||||||
import hep.dataforge.values.Values
|
import hep.dataforge.values.Values
|
||||||
import inr.numass.data.analyzers.NumassAnalyzer.Companion.COUNT_RATE_ERROR_KEY
|
import inr.numass.data.analyzers.NumassAnalyzer.Companion.COUNT_RATE_ERROR_KEY
|
||||||
import inr.numass.data.analyzers.NumassAnalyzer.Companion.COUNT_RATE_KEY
|
import inr.numass.data.analyzers.NumassAnalyzer.Companion.COUNT_RATE_KEY
|
||||||
|
import inr.numass.data.analyzers.NumassAnalyzer.Companion.TIME_KEY
|
||||||
import inr.numass.pointExpression
|
import inr.numass.pointExpression
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.math.pow
|
||||||
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply corrections and transformations to analyzed data
|
* Apply corrections and transformations to analyzed data
|
||||||
@ -29,10 +29,17 @@ import java.util.*
|
|||||||
*/
|
*/
|
||||||
@TypedActionDef(name = "numass.transform", inputType = Table::class, outputType = Table::class)
|
@TypedActionDef(name = "numass.transform", inputType = Table::class, outputType = Table::class)
|
||||||
@ValueDefs(
|
@ValueDefs(
|
||||||
ValueDef(key = "correction", info = "An expression to correct count number depending on potential `U`, point length `T` and point itself as `point`"),
|
ValueDef(
|
||||||
ValueDef(key = "utransform", info = "Expression for voltage transformation. Uses U as input")
|
key = "correction",
|
||||||
|
info = "An expression to correct count number depending on potential `U`, point length `T` and point itself as `point`"
|
||||||
|
),
|
||||||
|
ValueDef(key = "utransform", info = "Expression for voltage transformation. Uses U as input")
|
||||||
|
)
|
||||||
|
@NodeDef(
|
||||||
|
key = "correction",
|
||||||
|
multiple = true,
|
||||||
|
descriptor = "method::inr.numass.actions.TransformDataAction.makeCorrection"
|
||||||
)
|
)
|
||||||
@NodeDef(key = "correction", multiple = true, descriptor = "method::inr.numass.actions.TransformDataAction.makeCorrection")
|
|
||||||
object TransformDataAction : OneToOneAction<Table, Table>("numass.transform", Table::class.java, Table::class.java) {
|
object TransformDataAction : OneToOneAction<Table, Table>("numass.transform", Table::class.java, Table::class.java) {
|
||||||
|
|
||||||
override fun execute(context: Context, name: String, input: Table, meta: Laminate): Table {
|
override fun execute(context: Context, name: String, input: Table, meta: Laminate): Table {
|
||||||
@ -43,9 +50,10 @@ object TransformDataAction : OneToOneAction<Table, Table>("numass.transform", Ta
|
|||||||
|
|
||||||
meta.optMeta("corrections").ifPresent { cors ->
|
meta.optMeta("corrections").ifPresent { cors ->
|
||||||
MetaUtils.nodeStream(cors)
|
MetaUtils.nodeStream(cors)
|
||||||
.map<Meta> { it.second }
|
.filter { it.first.length == 1 }
|
||||||
.map<Correction> { this.makeCorrection(it) }
|
.map<Meta> { it.second }
|
||||||
.forEach { corrections.add(it) }
|
.map { makeCorrection(it) }
|
||||||
|
.forEach { corrections.add(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (meta.hasValue("correction")) {
|
if (meta.hasValue("correction")) {
|
||||||
@ -64,28 +72,39 @@ object TransformDataAction : OneToOneAction<Table, Table>("numass.transform", Ta
|
|||||||
if (!correction.isAnonymous) {
|
if (!correction.isAnonymous) {
|
||||||
table = table.buildColumn(ColumnFormat.build(correction.name, NUMBER)) { correction.corr(this) }
|
table = table.buildColumn(ColumnFormat.build(correction.name, NUMBER)) { correction.corr(this) }
|
||||||
if (correction.hasError()) {
|
if (correction.hasError()) {
|
||||||
table = table.buildColumn(ColumnFormat.build(correction.name + ".err", NUMBER)) { correction.corrErr(this) }
|
table = table.buildColumn(ColumnFormat.build(correction.name + ".err", NUMBER)) {
|
||||||
|
correction.corrErr(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// adding original count rate and error columns
|
// adding original count rate and error columns
|
||||||
table = table.addColumn(ListColumn(ColumnFormat.build("$COUNT_RATE_KEY.orig", NUMBER), table.getColumn(COUNT_RATE_KEY).stream()))
|
table = table.addColumn(
|
||||||
table = table.addColumn(ListColumn(ColumnFormat.build("$COUNT_RATE_ERROR_KEY.orig", NUMBER), table
|
ListColumn(
|
||||||
.getColumn(COUNT_RATE_ERROR_KEY).stream()))
|
ColumnFormat.build("$COUNT_RATE_KEY.orig", NUMBER),
|
||||||
|
table.getColumn(COUNT_RATE_KEY).stream()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
table = table.addColumn(
|
||||||
|
ListColumn(
|
||||||
|
ColumnFormat.build("$COUNT_RATE_ERROR_KEY.orig", NUMBER), table
|
||||||
|
.getColumn(COUNT_RATE_ERROR_KEY).stream()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
val cr = ArrayList<Double>()
|
val cr = ArrayList<Double>()
|
||||||
val crErr = ArrayList<Double>()
|
val crErr = ArrayList<Double>()
|
||||||
|
|
||||||
table.rows.forEach { point ->
|
table.rows.forEach { point ->
|
||||||
val correctionFactor = corrections.stream()
|
val correctionFactor = corrections.stream()
|
||||||
.mapToDouble { cor -> cor.corr(point) }
|
.mapToDouble { cor -> cor.corr(point) }
|
||||||
.reduce { d1, d2 -> d1 * d2 }.orElse(1.0)
|
.reduce { d1, d2 -> d1 * d2 }.orElse(1.0)
|
||||||
val relativeCorrectionError = Math.sqrt(
|
val relativeCorrectionError = Math.sqrt(
|
||||||
corrections.stream()
|
corrections.stream()
|
||||||
.mapToDouble { cor -> cor.relativeErr(point) }
|
.mapToDouble { cor -> cor.relativeErr(point) }
|
||||||
.reduce { d1, d2 -> d1 * d1 + d2 * d2 }.orElse(0.0)
|
.reduce { d1, d2 -> d1 * d1 + d2 * d2 }.orElse(0.0)
|
||||||
)
|
)
|
||||||
val originalCR = point.getDouble(COUNT_RATE_KEY)
|
val originalCR = point.getDouble(COUNT_RATE_KEY)
|
||||||
val originalCRErr = point.getDouble(COUNT_RATE_ERROR_KEY)
|
val originalCRErr = point.getDouble(COUNT_RATE_ERROR_KEY)
|
||||||
@ -93,13 +112,15 @@ object TransformDataAction : OneToOneAction<Table, Table>("numass.transform", Ta
|
|||||||
if (relativeCorrectionError == 0.0) {
|
if (relativeCorrectionError == 0.0) {
|
||||||
crErr.add(originalCRErr * correctionFactor)
|
crErr.add(originalCRErr * correctionFactor)
|
||||||
} else {
|
} else {
|
||||||
crErr.add(Math.sqrt(Math.pow(originalCRErr / originalCR, 2.0) + Math.pow(relativeCorrectionError, 2.0)) * originalCR)
|
crErr.add(sqrt((originalCRErr / originalCR).pow(2.0) + relativeCorrectionError.pow(2.0)) * originalCR)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//replacing cr column
|
//replacing cr column
|
||||||
val res = table.addColumn(ListColumn.build(table.getColumn(COUNT_RATE_KEY).format, cr.stream()))
|
val res = table.addColumn(ListColumn.build(table.getColumn(COUNT_RATE_KEY).format, cr.stream()))
|
||||||
.addColumn(ListColumn.build(table.getColumn(COUNT_RATE_ERROR_KEY).format, crErr.stream()))
|
.addColumn(ListColumn.build(table.getColumn(COUNT_RATE_ERROR_KEY).format, crErr.stream()))
|
||||||
|
.sort(TIME_KEY)
|
||||||
|
|
||||||
|
|
||||||
context.output[this@TransformDataAction.name, name].render(res, meta)
|
context.output[this@TransformDataAction.name, name].render(res, meta)
|
||||||
return res
|
return res
|
||||||
@ -107,34 +128,23 @@ object TransformDataAction : OneToOneAction<Table, Table>("numass.transform", Ta
|
|||||||
|
|
||||||
|
|
||||||
@ValueDefs(
|
@ValueDefs(
|
||||||
ValueDef(key = "value", type = arrayOf(NUMBER, STRING), info = "Value or function to multiply count rate"),
|
ValueDef(key = "value", type = arrayOf(NUMBER, STRING), info = "Value or function to multiply count rate"),
|
||||||
ValueDef(key = "err", type = arrayOf(NUMBER, STRING), info = "error of the value")
|
ValueDef(key = "err", type = arrayOf(NUMBER, STRING), info = "error of the value")
|
||||||
)
|
)
|
||||||
private fun makeCorrection(corrMeta: Meta): Correction {
|
private fun makeCorrection(corrMeta: Meta): Correction {
|
||||||
val expr = corrMeta.getString("value")
|
val name = corrMeta.getString("name", corrMeta.name)
|
||||||
val errExpr = corrMeta.getString("err", "")
|
return if (corrMeta.hasMeta("table")) {
|
||||||
return object : Correction {
|
val x = corrMeta.getValue("table.u").list.map { it.double }
|
||||||
override val name = corrMeta.getString("name", corrMeta.name)
|
val corr = corrMeta.getValue("table.corr").list.map { it.double }
|
||||||
|
TableCorrection(name, x, corr)
|
||||||
override fun corr(point: Values): Double {
|
} else {
|
||||||
return pointExpression(expr, point)
|
val expr = corrMeta.getString("value")
|
||||||
}
|
val errExpr = corrMeta.getString("err", "")
|
||||||
|
ExpressionCorrection(name, expr, errExpr)
|
||||||
override fun corrErr(point: Values): Double {
|
|
||||||
return if (errExpr.isEmpty()) {
|
|
||||||
0.0
|
|
||||||
} else {
|
|
||||||
pointExpression(errExpr, point)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hasError(): Boolean {
|
|
||||||
return !errExpr.isEmpty()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface Correction : Named {
|
interface Correction : Named {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* correction coefficient
|
* correction coefficient
|
||||||
@ -168,4 +178,44 @@ object TransformDataAction : OneToOneAction<Table, Table>("numass.transform", Ta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ExpressionCorrection(override val name: String, val expr: String, val errExpr: String) : Correction {
|
||||||
|
override fun corr(point: Values): Double {
|
||||||
|
return pointExpression(expr, point)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun corrErr(point: Values): Double {
|
||||||
|
return if (errExpr.isEmpty()) {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
pointExpression(errExpr, point)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasError(): Boolean {
|
||||||
|
return errExpr.isNotEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TableCorrection(
|
||||||
|
override val name: String,
|
||||||
|
val x: List<Double>,
|
||||||
|
val y: List<Double>,
|
||||||
|
val yErr: List<Double>? = null
|
||||||
|
) : Correction {
|
||||||
|
override fun corr(point: Values): Double {
|
||||||
|
val voltage = point.getDouble("voltage")
|
||||||
|
val index = x.indexOfFirst { it > voltage }
|
||||||
|
//TODO add interpolation
|
||||||
|
return if (index < 0) {
|
||||||
|
y.last()
|
||||||
|
} else {
|
||||||
|
y[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// override fun corrErr(point: Values): Double = 0.0
|
||||||
|
//
|
||||||
|
// override fun hasError(): Boolean = yErr.isNullOrEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,11 @@ package inr.numass.data
|
|||||||
|
|
||||||
import hep.dataforge.configure
|
import hep.dataforge.configure
|
||||||
import hep.dataforge.context.Context
|
import hep.dataforge.context.Context
|
||||||
import hep.dataforge.context.Global
|
|
||||||
import hep.dataforge.meta.KMetaBuilder
|
import hep.dataforge.meta.KMetaBuilder
|
||||||
import hep.dataforge.meta.buildMeta
|
import hep.dataforge.meta.buildMeta
|
||||||
import hep.dataforge.nullable
|
import hep.dataforge.nullable
|
||||||
|
import hep.dataforge.plots.PlotFrame
|
||||||
|
import hep.dataforge.plots.PlotGroup
|
||||||
import hep.dataforge.plots.data.DataPlot
|
import hep.dataforge.plots.data.DataPlot
|
||||||
import hep.dataforge.plots.output.plotFrame
|
import hep.dataforge.plots.output.plotFrame
|
||||||
import hep.dataforge.tables.Adapters
|
import hep.dataforge.tables.Adapters
|
||||||
@ -30,20 +31,24 @@ import inr.numass.data.analyzers.SmartAnalyzer
|
|||||||
import inr.numass.data.analyzers.withBinning
|
import inr.numass.data.analyzers.withBinning
|
||||||
import inr.numass.data.api.NumassBlock
|
import inr.numass.data.api.NumassBlock
|
||||||
|
|
||||||
|
fun PlotGroup.plotAmplitudeSpectrum(
|
||||||
fun NumassBlock.plotAmplitudeSpectrum(plotName: String = "spectrum", frameName: String = "", context: Context = Global, metaAction: KMetaBuilder.() -> Unit = {}) {
|
numassBlock: NumassBlock,
|
||||||
val meta = buildMeta("meta", metaAction)
|
plotName: String = "spectrum",
|
||||||
|
analyzer: NumassAnalyzer = SmartAnalyzer(),
|
||||||
|
metaBuilder: KMetaBuilder.() -> Unit = {}
|
||||||
|
) {
|
||||||
|
val meta = buildMeta("meta", metaBuilder)
|
||||||
val binning = meta.getInt("binning", 20)
|
val binning = meta.getInt("binning", 20)
|
||||||
val lo = meta.optNumber("window.lo").nullable?.toInt()
|
val lo = meta.optNumber("window.lo").nullable?.toInt()
|
||||||
val up = meta.optNumber("window.up").nullable?.toInt()
|
val up = meta.optNumber("window.up").nullable?.toInt()
|
||||||
val data = SmartAnalyzer().getAmplitudeSpectrum(this, meta.getMetaOrEmpty("spectrum")).withBinning(binning, lo, up)
|
val data = analyzer.getAmplitudeSpectrum(numassBlock, meta).withBinning(binning, lo, up)
|
||||||
context.plotFrame(plotName) {
|
apply {
|
||||||
val valueAxis = if (meta.getBoolean("normalize", false)) {
|
val valueAxis = if (meta.getBoolean("normalize", false)) {
|
||||||
NumassAnalyzer.COUNT_RATE_KEY
|
NumassAnalyzer.COUNT_RATE_KEY
|
||||||
} else {
|
} else {
|
||||||
NumassAnalyzer.COUNT_KEY
|
NumassAnalyzer.COUNT_KEY
|
||||||
}
|
}
|
||||||
plots.configure {
|
configure {
|
||||||
"connectionType" to "step"
|
"connectionType" to "step"
|
||||||
"thickness" to 2
|
"thickness" to 2
|
||||||
"showLine" to true
|
"showLine" to true
|
||||||
@ -52,11 +57,31 @@ fun NumassBlock.plotAmplitudeSpectrum(plotName: String = "spectrum", frameName:
|
|||||||
}.setType<DataPlot>()
|
}.setType<DataPlot>()
|
||||||
|
|
||||||
val plot = DataPlot.plot(
|
val plot = DataPlot.plot(
|
||||||
plotName,
|
plotName,
|
||||||
data,
|
data,
|
||||||
Adapters.buildXYAdapter(NumassAnalyzer.CHANNEL_KEY, valueAxis)
|
Adapters.buildXYAdapter(NumassAnalyzer.CHANNEL_KEY, valueAxis)
|
||||||
)
|
)
|
||||||
plot.configure(meta)
|
plot.configure(meta)
|
||||||
add(plot)
|
add(plot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun PlotFrame.plotAmplitudeSpectrum(
|
||||||
|
numassBlock: NumassBlock,
|
||||||
|
plotName: String = "spectrum",
|
||||||
|
analyzer: NumassAnalyzer = SmartAnalyzer(),
|
||||||
|
metaBuilder: KMetaBuilder.() -> Unit = {}
|
||||||
|
) = plots.plotAmplitudeSpectrum(numassBlock, plotName, analyzer, metaBuilder)
|
||||||
|
|
||||||
|
fun Context.plotAmplitudeSpectrum(
|
||||||
|
numassBlock: NumassBlock,
|
||||||
|
plotName: String = "spectrum",
|
||||||
|
frameName: String = plotName,
|
||||||
|
analyzer: NumassAnalyzer = SmartAnalyzer(),
|
||||||
|
metaAction: KMetaBuilder.() -> Unit = {}
|
||||||
|
) {
|
||||||
|
plotFrame(frameName) {
|
||||||
|
plotAmplitudeSpectrum(numassBlock, plotName, analyzer, metaAction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -17,14 +17,16 @@
|
|||||||
package inr.numass.data.analyzers
|
package inr.numass.data.analyzers
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.tables.ListTable
|
||||||
|
import hep.dataforge.tables.Table
|
||||||
import hep.dataforge.tables.TableFormat
|
import hep.dataforge.tables.TableFormat
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
import hep.dataforge.values.ValueMap
|
import hep.dataforge.values.ValueMap
|
||||||
|
import hep.dataforge.values.ValueType
|
||||||
import hep.dataforge.values.Values
|
import hep.dataforge.values.Values
|
||||||
import inr.numass.data.api.NumassBlock
|
import inr.numass.data.ChernovProcessor
|
||||||
import inr.numass.data.api.NumassEvent
|
import inr.numass.data.api.*
|
||||||
import inr.numass.data.api.SignalProcessor
|
import inr.numass.utils.ExpressionUtils
|
||||||
import java.util.stream.Stream
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An analyzer dispatcher which uses different analyzer for different meta
|
* An analyzer dispatcher which uses different analyzer for different meta
|
||||||
@ -41,7 +43,7 @@ class SmartAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(proce
|
|||||||
"simple" -> simpleAnalyzer
|
"simple" -> simpleAnalyzer
|
||||||
"time" -> timeAnalyzer
|
"time" -> timeAnalyzer
|
||||||
"debunch" -> debunchAnalyzer
|
"debunch" -> debunchAnalyzer
|
||||||
else -> throw IllegalArgumentException("Analyzer not found")
|
else -> throw IllegalArgumentException("Analyzer ${config.getString("type")} not found")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (config.hasValue("t0") || config.hasMeta("t0")) {
|
if (config.hasValue("t0") || config.hasMeta("t0")) {
|
||||||
@ -59,7 +61,7 @@ class SmartAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(proce
|
|||||||
return ValueMap(map)
|
return ValueMap(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getEvents(block: NumassBlock, meta: Meta): Stream<NumassEvent> {
|
override fun getEvents(block: NumassBlock, meta: Meta): List<NumassEvent> {
|
||||||
return getAnalyzer(meta).getEvents(block, meta)
|
return getAnalyzer(meta).getEvents(block, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,4 +71,33 @@ class SmartAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(proce
|
|||||||
} else super.getTableFormat(config)
|
} else super.getTableFormat(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun analyzeSet(set: NumassSet, config: Meta): Table {
|
||||||
|
fun Value.computeExpression(point: NumassPoint): Int {
|
||||||
|
return when {
|
||||||
|
this.type == ValueType.NUMBER -> this.int
|
||||||
|
this.type == ValueType.STRING -> {
|
||||||
|
val exprParams = HashMap<String, Any>()
|
||||||
|
|
||||||
|
exprParams["U"] = point.voltage
|
||||||
|
|
||||||
|
ExpressionUtils.function(this.string, exprParams).toInt()
|
||||||
|
}
|
||||||
|
else -> error("Can't interpret $type as expression or number")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val lo = config.getValue("window.lo",0)
|
||||||
|
val up = config.getValue("window.up", Int.MAX_VALUE)
|
||||||
|
|
||||||
|
val format = getTableFormat(config)
|
||||||
|
|
||||||
|
return ListTable.Builder(format)
|
||||||
|
.rows(set.points.map { point ->
|
||||||
|
val newConfig = config.builder.apply{
|
||||||
|
setValue("window.lo", lo.computeExpression(point))
|
||||||
|
setValue("window.up", up.computeExpression(point))
|
||||||
|
}
|
||||||
|
analyzeParent(point, newConfig)
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
}
|
||||||
}
|
}
|
@ -32,7 +32,7 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val point = SimpleNumassPoint(blocks, 10000.0)
|
val point = SimpleNumassPoint.build(blocks, 10000.0)
|
||||||
|
|
||||||
val meta = buildMeta {
|
val meta = buildMeta {
|
||||||
"t0" to 1e7
|
"t0" to 1e7
|
||||||
|
@ -25,10 +25,9 @@ import inr.numass.data.api.NumassEvent
|
|||||||
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 org.apache.commons.math3.stat.correlation.PearsonsCorrelation
|
import org.apache.commons.math3.stat.correlation.PearsonsCorrelation
|
||||||
import java.util.stream.Stream
|
|
||||||
|
|
||||||
|
|
||||||
private fun correlation(sequence: Stream<NumassEvent>): Double {
|
private fun correlation(sequence: List<NumassEvent>): Double {
|
||||||
val amplitudes: MutableList<Double> = ArrayList()
|
val amplitudes: MutableList<Double> = ArrayList()
|
||||||
val times: MutableList<Double> = ArrayList()
|
val times: MutableList<Double> = ArrayList()
|
||||||
sequence.forEach {
|
sequence.forEach {
|
||||||
|
@ -108,7 +108,7 @@ fun main(args: Array<String>) {
|
|||||||
.filter { pair -> pair.second <= t0 }
|
.filter { pair -> pair.second <= t0 }
|
||||||
.map { it.first }
|
.map { it.first }
|
||||||
|
|
||||||
val pileupSpectrum = getAmplitudeSpectrum(sequence, point.length.toMillis().toDouble() / 1000.0).withBinning(20)
|
val pileupSpectrum = sequence.getAmplitudeSpectrum(point.length.toMillis().toDouble() / 1000.0).withBinning(20)
|
||||||
|
|
||||||
group.add(DataPlot.plot("pileup", pileupSpectrum, AMPLITUDE_ADAPTER))
|
group.add(DataPlot.plot("pileup", pileupSpectrum, AMPLITUDE_ADAPTER))
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ fun main(args: Array<String>) {
|
|||||||
.filter { pair -> pair.second <= t0 }
|
.filter { pair -> pair.second <= t0 }
|
||||||
.map { it.first }
|
.map { it.first }
|
||||||
|
|
||||||
val pileupSpectrum = getAmplitudeSpectrum(sequence, point.length.toMillis().toDouble() / 1000.0).withBinning(20)
|
val pileupSpectrum = sequence.getAmplitudeSpectrum(point.length.toMillis().toDouble() / 1000.0).withBinning(20)
|
||||||
|
|
||||||
group.add(DataPlot.plot("pileup", pileupSpectrum, AMPLITUDE_ADAPTER))
|
group.add(DataPlot.plot("pileup", pileupSpectrum, AMPLITUDE_ADAPTER))
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
//val rootDir = File("D:\\Work\\Numass\\data\\2017_05\\Fill_2")
|
//val rootDir = File("D:\\Work\\Numass\\data\\2017_05\\Fill_2")
|
||||||
|
|
||||||
val storage = NumassDirectory.read(context, "Fill_3_events") ?: error("Storage not found")
|
val storage = NumassDirectory.read(context, "Fill_3") ?: error("Storage not found")
|
||||||
|
|
||||||
|
|
||||||
val analyzer = SmartAnalyzer()
|
val analyzer = SmartAnalyzer()
|
||||||
@ -34,7 +34,7 @@ fun main(args: Array<String>) {
|
|||||||
// "window.up" to 1600
|
// "window.up" to 1600
|
||||||
}
|
}
|
||||||
|
|
||||||
val set = storage.provide("set_58", NumassSet::class.java).nullable ?: error("Set does not exist")
|
val set = storage.provide("set_4", NumassSet::class.java).nullable ?: error("Set does not exist")
|
||||||
|
|
||||||
val frame = displayChart("slices").apply {
|
val frame = displayChart("slices").apply {
|
||||||
plots.setType<DataPlot>()
|
plots.setType<DataPlot>()
|
||||||
|
@ -14,7 +14,7 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
//val meta = workspace.getTarget("group_3")
|
//val meta = workspace.getTarget("group_3")
|
||||||
|
|
||||||
val result = workspace.runTask("scansum", "group_3").first().get()
|
val result = workspace.runTask("fit", "group_5").first().get()
|
||||||
println("Complete!")
|
println("Complete!")
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package inr.numass.scripts.analysis
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.fx.output.FXOutputManager
|
||||||
|
import hep.dataforge.workspace.FileBasedWorkspace
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
FXOutputManager().startGlobal()
|
||||||
|
|
||||||
|
val configPath = File("D:\\Work\\Numass\\sterile2017_05_frames\\workspace.groovy").toPath()
|
||||||
|
val workspace = FileBasedWorkspace.build(Global, configPath)
|
||||||
|
workspace.context.setValue("cache.enabled", false)
|
||||||
|
|
||||||
|
//val meta = workspace.getTarget("group_3")
|
||||||
|
|
||||||
|
val result = workspace.runTask("fit", "group_5").first().get()
|
||||||
|
println("Complete!")
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package inr.numass.scripts.models
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.fx.output.FXOutputManager
|
||||||
|
import hep.dataforge.meta.buildMeta
|
||||||
|
import hep.dataforge.plots.data.DataPlot
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
||||||
|
import hep.dataforge.stat.fit.ParamSet
|
||||||
|
import hep.dataforge.step
|
||||||
|
import inr.numass.NumassPlugin
|
||||||
|
import inr.numass.displayChart
|
||||||
|
import inr.numass.models.NBkgSpectrum
|
||||||
|
import inr.numass.models.sterile.SterileNeutrinoSpectrum
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
NumassPlugin().startGlobal()
|
||||||
|
JFreeChartPlugin().startGlobal()
|
||||||
|
Global.output = FXOutputManager()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val params = ParamSet().apply {
|
||||||
|
setPar("N", 8e5, 6.0, 0.0, Double.POSITIVE_INFINITY)
|
||||||
|
setPar("bkg", 2.0, 0.03)
|
||||||
|
setPar("E0", 18575.0, 1.0)
|
||||||
|
setPar("mnu2", 0.0, 1.0)
|
||||||
|
setParValue("msterile2", (1000 * 1000).toDouble())
|
||||||
|
setPar("U2", 0.0, 1e-3)
|
||||||
|
setPar("X", 0.0, 0.01)
|
||||||
|
setPar("trap", 1.0, 0.01)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val meta1 = buildMeta {
|
||||||
|
"resolution.A" to 8.3e-5
|
||||||
|
}
|
||||||
|
val spectrum1 = NBkgSpectrum(SterileNeutrinoSpectrum(Global, meta1))
|
||||||
|
|
||||||
|
val meta2 = buildMeta {
|
||||||
|
"resolution.A" to 0
|
||||||
|
}
|
||||||
|
val spectrum2 = NBkgSpectrum(SterileNeutrinoSpectrum(Global, meta2))
|
||||||
|
|
||||||
|
displayChart("compare").apply {
|
||||||
|
val x = (14000.0..18600.0).step(100.0).toList()
|
||||||
|
val y1 = x.map { spectrum1.value(it, params) }
|
||||||
|
+DataPlot.plot("simple", x.toDoubleArray(), y1.toDoubleArray())
|
||||||
|
val y2 = x.map { spectrum2.value(it, params) }
|
||||||
|
+DataPlot.plot("normal", x.toDoubleArray(), y2.toDoubleArray())
|
||||||
|
val dif = x.mapIndexed{ index, _ -> 1 - y1[index]/y2[index] }
|
||||||
|
+DataPlot.plot("dif", x.toDoubleArray(), dif.toDoubleArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -29,7 +29,6 @@ import hep.dataforge.plots.plotData
|
|||||||
import hep.dataforge.storage.files.FileStorage
|
import hep.dataforge.storage.files.FileStorage
|
||||||
import hep.dataforge.tables.Adapters
|
import hep.dataforge.tables.Adapters
|
||||||
import hep.dataforge.tables.filter
|
import hep.dataforge.tables.filter
|
||||||
import hep.dataforge.tables.sort
|
|
||||||
import inr.numass.NumassPlugin
|
import inr.numass.NumassPlugin
|
||||||
import inr.numass.data.NumassDataUtils
|
import inr.numass.data.NumassDataUtils
|
||||||
import inr.numass.data.api.NumassSet
|
import inr.numass.data.api.NumassSet
|
||||||
@ -37,46 +36,47 @@ import inr.numass.data.storage.NumassDirectory
|
|||||||
import inr.numass.displayChart
|
import inr.numass.displayChart
|
||||||
import inr.numass.subthreshold.Threshold
|
import inr.numass.subthreshold.Threshold
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main() {
|
||||||
val context = buildContext("NUMASS", NumassPlugin::class.java, JFreeChartPlugin::class.java) {
|
val context = buildContext("NUMASS", NumassPlugin::class.java, JFreeChartPlugin::class.java) {
|
||||||
rootDir = "D:\\Work\\Numass\\sterile\\2017_05"
|
rootDir = "D:\\Work\\Numass\\sterile\\2017_05_frames"
|
||||||
dataDir = "D:\\Work\\Numass\\data\\2017_05"
|
dataDir = "D:\\Work\\Numass\\data\\2017_05_frames"
|
||||||
output = FXOutputManager() + DirectoryOutput()
|
output = FXOutputManager() + DirectoryOutput()
|
||||||
}
|
}
|
||||||
|
|
||||||
val storage = NumassDirectory.read(context, "Fill_2") as? FileStorage ?: error("Storage not found")
|
val storage = NumassDirectory.read(context, "Fill_3") as? FileStorage ?: error("Storage not found")
|
||||||
|
|
||||||
val meta = buildMeta {
|
val meta = buildMeta {
|
||||||
"delta" to -150
|
"delta" to -300
|
||||||
"method" to "pow"
|
"method" to "pow"
|
||||||
"t0" to 15e3
|
"t0" to 15e3
|
||||||
// "window.lo" to 400
|
// "window.lo" to 400
|
||||||
// "window.up" to 1600
|
// "window.up" to 1600
|
||||||
"xLow" to 450
|
"xLow" to 1000
|
||||||
"xHigh" to 700
|
"xHigh" to 1300
|
||||||
"upper" to 3100
|
"upper" to 6000
|
||||||
"binning" to 20
|
"binning" to 32
|
||||||
|
//"reference" to 18600
|
||||||
}
|
}
|
||||||
|
|
||||||
val frame = displayChart("correction").apply {
|
val frame = displayChart("correction").apply {
|
||||||
plots.setType<DataPlot>()
|
plots.setType<DataPlot>()
|
||||||
}
|
}
|
||||||
|
|
||||||
val sets = (1..18).map { "set_$it" }.map { setName ->
|
val sets = (1..14).map { "set_$it" }.mapNotNull { setName ->
|
||||||
storage.provide(setName, NumassSet::class.java).nullable
|
storage.provide(setName, NumassSet::class.java).nullable
|
||||||
}.filterNotNull()
|
}
|
||||||
|
|
||||||
val name = "fill_2[1-18]"
|
val name = "fill_3[1-14]"
|
||||||
|
|
||||||
val sum = NumassDataUtils.join(name, sets)
|
val sum = NumassDataUtils.join(name, sets)
|
||||||
|
|
||||||
val correctionTable = Threshold.calculateSubThreshold(sum, meta).filter {
|
val correctionTable = Threshold.calculateSubThreshold(sum, meta).filter {
|
||||||
it.getDouble("correction") in (1.0..1.2)
|
it.getDouble("correction") in (1.0..1.2)
|
||||||
}.sort("voltage")
|
}
|
||||||
|
|
||||||
frame.plotData("${name}_cor", correctionTable, Adapters.buildXYAdapter("U", "correction"))
|
frame.plotData("${name}_cor", correctionTable, Adapters.buildXYAdapter("U", "correction"))
|
||||||
frame.plotData("${name}_a", correctionTable, Adapters.buildXYAdapter("U", "a"))
|
frame.plotData("${name}_a", correctionTable, Adapters.buildXYAdapter("U", "a"))
|
||||||
frame.plotData("${name}_beta", correctionTable, Adapters.buildXYAdapter("U", "beta"))
|
frame.plotData("${name}_beta", correctionTable, Adapters.buildXYAdapter("U", "beta"))
|
||||||
|
|
||||||
context.output.render(correctionTable,"numass.correction", "fill_2[1-18]")
|
context.output.render(correctionTable,"numass.correction", name)
|
||||||
}
|
}
|
@ -35,19 +35,24 @@ import inr.numass.subthreshold.Threshold
|
|||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val context = buildContext("NUMASS", NumassPlugin::class.java, JFreeChartPlugin::class.java) {
|
val context = buildContext("NUMASS", NumassPlugin::class.java, JFreeChartPlugin::class.java) {
|
||||||
rootDir = "D:\\Work\\Numass\\sterile\\2017_05"
|
rootDir = "D:\\Work\\Numass\\sterile\\2017_05_frames"
|
||||||
dataDir = "D:\\Work\\Numass\\data\\2017_05"
|
dataDir = "D:\\Work\\Numass\\data\\2017_05_frames"
|
||||||
output = FXOutputManager() + DirectoryOutput()
|
output = FXOutputManager() + DirectoryOutput()
|
||||||
}
|
}
|
||||||
|
|
||||||
val storage = NumassDirectory.read(context, "Fill_2") as? FileStorage ?: error("Storage not found")
|
val storage = NumassDirectory.read(context, "Fill_3") as? FileStorage ?: error("Storage not found")
|
||||||
|
|
||||||
val meta = buildMeta {
|
val meta = buildMeta {
|
||||||
"delta" to -200
|
"delta" to -300
|
||||||
"method" to "pow"
|
"method" to "pow"
|
||||||
"t0" to 15e3
|
"t0" to 15e3
|
||||||
"window.lo" to 400
|
// "window.lo" to 400
|
||||||
"window.up" to 1600
|
// "window.up" to 1600
|
||||||
|
"xLow" to 1000
|
||||||
|
"xHigh" to 1300
|
||||||
|
"upper" to 6000
|
||||||
|
"binning" to 32
|
||||||
|
//"reference" to 18600
|
||||||
}
|
}
|
||||||
|
|
||||||
val frame = displayChart("correction").apply {
|
val frame = displayChart("correction").apply {
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import hep.dataforge.buildContext
|
||||||
|
import hep.dataforge.fx.output.FXOutputManager
|
||||||
|
import hep.dataforge.io.DirectoryOutput
|
||||||
|
import hep.dataforge.io.plus
|
||||||
|
import hep.dataforge.meta.buildMeta
|
||||||
|
import hep.dataforge.nullable
|
||||||
|
import hep.dataforge.plots.data.DataPlot
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
||||||
|
import hep.dataforge.plots.plotData
|
||||||
|
import hep.dataforge.storage.files.FileStorage
|
||||||
|
import hep.dataforge.tables.Adapters
|
||||||
|
import inr.numass.NumassPlugin
|
||||||
|
import inr.numass.data.api.NumassSet
|
||||||
|
import inr.numass.data.storage.NumassDirectory
|
||||||
|
import inr.numass.displayChart
|
||||||
|
import inr.numass.subthreshold.Threshold
|
||||||
|
|
||||||
|
fun main(){
|
||||||
|
val context = buildContext("NUMASS", NumassPlugin::class.java, JFreeChartPlugin::class.java) {
|
||||||
|
rootDir = "D:\\Work\\Numass\\sterile\\2017_05"
|
||||||
|
dataDir = "D:\\Work\\Numass\\data\\2017_05"
|
||||||
|
output = FXOutputManager() + DirectoryOutput()
|
||||||
|
}
|
||||||
|
|
||||||
|
val storage = NumassDirectory.read(context, "Fill_3") as? FileStorage ?: error("Storage not found")
|
||||||
|
|
||||||
|
val meta = buildMeta {
|
||||||
|
"delta" to -200
|
||||||
|
"method" to "pow"
|
||||||
|
"t0" to 15e3
|
||||||
|
// "window.lo" to 400
|
||||||
|
// "window.up" to 1600
|
||||||
|
"xLow" to 450
|
||||||
|
"xHigh" to 700
|
||||||
|
"upper" to 3000
|
||||||
|
"binning" to 20
|
||||||
|
//"reference" to 18600
|
||||||
|
}
|
||||||
|
|
||||||
|
val frame = displayChart("correction").apply {
|
||||||
|
plots.setType<DataPlot>()
|
||||||
|
}
|
||||||
|
|
||||||
|
listOf("set_2", "set_3", "set_4", "set_5").forEach { setName ->
|
||||||
|
val set = storage.provide(setName, NumassSet::class.java).nullable ?: error("Set does not exist")
|
||||||
|
|
||||||
|
val correctionTable = Threshold.calculateSubThreshold(set, meta).filter {
|
||||||
|
it.getDouble("correction") in (1.0..1.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.plotData(setName, correctionTable, Adapters.buildXYAdapter("U", "correction"))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package inr.numass.scripts.timeanalysis
|
||||||
|
|
||||||
|
import hep.dataforge.buildContext
|
||||||
|
import hep.dataforge.data.DataSet
|
||||||
|
import hep.dataforge.fx.output.FXOutputManager
|
||||||
|
import hep.dataforge.meta.buildMeta
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
||||||
|
import inr.numass.NumassPlugin
|
||||||
|
import inr.numass.actions.TimeAnalyzerAction
|
||||||
|
import inr.numass.data.api.NumassPoint
|
||||||
|
import inr.numass.data.api.NumassSet
|
||||||
|
import inr.numass.data.api.SimpleNumassPoint
|
||||||
|
import inr.numass.data.storage.NumassDirectory
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
|
||||||
|
val context = buildContext("NUMASS", NumassPlugin::class.java, JFreeChartPlugin::class.java) {
|
||||||
|
output = FXOutputManager()
|
||||||
|
rootDir = "D:\\Work\\Numass\\sterile2018_04"
|
||||||
|
dataDir = "D:\\Work\\Numass\\data\\2018_04"
|
||||||
|
}
|
||||||
|
|
||||||
|
val storage = NumassDirectory.read(context, "Fill_3")!!
|
||||||
|
|
||||||
|
val meta = buildMeta {
|
||||||
|
"binNum" to 200
|
||||||
|
//"chunkSize" to 10000
|
||||||
|
// "mean" to TimeAnalyzer.AveragingMethod.ARITHMETIC
|
||||||
|
//"separateParallelBlocks" to true
|
||||||
|
"t0" to {
|
||||||
|
"step" to 320
|
||||||
|
}
|
||||||
|
"analyzer" to {
|
||||||
|
"t0" to 16000
|
||||||
|
"window" to {
|
||||||
|
"lo" to 450
|
||||||
|
"up" to 1900
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//"plot.showErrors" to false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val loader = storage.provide("set_9",NumassSet::class.java).get()
|
||||||
|
|
||||||
|
val hvs = listOf(14000.0)//, 15000d, 15200d, 15400d, 15600d, 15800d]
|
||||||
|
//listOf(18500.0, 18600.0, 18995.0, 19000.0)
|
||||||
|
|
||||||
|
val data = DataSet.edit(NumassPoint::class).apply {
|
||||||
|
hvs.forEach { hv ->
|
||||||
|
val points = loader.points.filter {
|
||||||
|
it.voltage == hv
|
||||||
|
}.toList()
|
||||||
|
if (!points.isEmpty()) {
|
||||||
|
putStatic(
|
||||||
|
"point_${hv.toInt()}",
|
||||||
|
SimpleNumassPoint.build(points, hv)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
|
||||||
|
val result = TimeAnalyzerAction.run(context, data, meta);
|
||||||
|
|
||||||
|
result.nodeGoal().run()
|
||||||
|
|
||||||
|
readLine()
|
||||||
|
println("Canceling task")
|
||||||
|
result.nodeGoal().cancel()
|
||||||
|
}
|
@ -8,7 +8,6 @@ import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
|||||||
import inr.numass.NumassPlugin
|
import inr.numass.NumassPlugin
|
||||||
import inr.numass.actions.TimeAnalyzerAction
|
import inr.numass.actions.TimeAnalyzerAction
|
||||||
import inr.numass.data.NumassDataUtils
|
import inr.numass.data.NumassDataUtils
|
||||||
import inr.numass.data.analyzers.TimeAnalyzer
|
|
||||||
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.api.SimpleNumassPoint
|
import inr.numass.data.api.SimpleNumassPoint
|
||||||
@ -18,28 +17,33 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
val context = buildContext("NUMASS", NumassPlugin::class.java, JFreeChartPlugin::class.java) {
|
val context = buildContext("NUMASS", NumassPlugin::class.java, JFreeChartPlugin::class.java) {
|
||||||
output = FXOutputManager()
|
output = FXOutputManager()
|
||||||
rootDir = "D:\\Work\\Numass\\sterile2017_05"
|
rootDir = "D:\\Work\\Numass\\sterile2017_05_frames"
|
||||||
dataDir = "D:\\Work\\Numass\\data\\2017_05"
|
dataDir = "D:\\Work\\Numass\\data\\2017_05_frames"
|
||||||
}
|
}
|
||||||
|
|
||||||
val storage = NumassDirectory.read(context, "Fill_2")!!
|
val storage = NumassDirectory.read(context, "Fill_3")!!
|
||||||
|
|
||||||
val meta = buildMeta {
|
val meta = buildMeta {
|
||||||
"t0" to 3000
|
|
||||||
"binNum" to 200
|
"binNum" to 200
|
||||||
"t0Step" to 100
|
//"chunkSize" to 10000
|
||||||
"chunkSize" to 3000
|
// "mean" to TimeAnalyzer.AveragingMethod.ARITHMETIC
|
||||||
"mean" to TimeAnalyzer.AveragingMethod.ARITHMETIC
|
|
||||||
//"separateParallelBlocks" to true
|
//"separateParallelBlocks" to true
|
||||||
"window" to {
|
"t0" to {
|
||||||
"lo" to 0
|
"step" to 320
|
||||||
"up" to 4000
|
|
||||||
}
|
}
|
||||||
|
"analyzer" to {
|
||||||
|
"t0" to 16000
|
||||||
|
"window" to {
|
||||||
|
"lo" to 1500
|
||||||
|
"up" to 7000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//"plot.showErrors" to false
|
//"plot.showErrors" to false
|
||||||
}
|
}
|
||||||
|
|
||||||
//def sets = ((2..14) + (22..31)).collect { "set_$it" }
|
//def sets = ((2..14) + (22..31)).collect { "set_$it" }
|
||||||
val sets = (2..12).map { "set_$it" }
|
val sets = (11..11).map { "set_$it" }
|
||||||
//def sets = (16..31).collect { "set_$it" }
|
//def sets = (16..31).collect { "set_$it" }
|
||||||
//def sets = (20..28).collect { "set_$it" }
|
//def sets = (20..28).collect { "set_$it" }
|
||||||
|
|
||||||
@ -49,7 +53,7 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
val all = NumassDataUtils.join("sum", loaders)
|
val all = NumassDataUtils.join("sum", loaders)
|
||||||
|
|
||||||
val hvs = listOf(14500.0)//, 15000d, 15200d, 15400d, 15600d, 15800d]
|
val hvs = listOf(14000.0)//, 15000d, 15200d, 15400d, 15600d, 15800d]
|
||||||
//listOf(18500.0, 18600.0, 18995.0, 19000.0)
|
//listOf(18500.0, 18600.0, 18995.0, 19000.0)
|
||||||
|
|
||||||
val data = DataSet.edit(NumassPoint::class).apply {
|
val data = DataSet.edit(NumassPoint::class).apply {
|
||||||
@ -58,10 +62,7 @@ fun main(args: Array<String>) {
|
|||||||
it.voltage == hv && it.channel == 0
|
it.voltage == hv && it.channel == 0
|
||||||
}.toList()
|
}.toList()
|
||||||
if (!points.isEmpty()) {
|
if (!points.isEmpty()) {
|
||||||
putStatic(
|
putStatic("point_${hv.toInt()}", SimpleNumassPoint.build(points, hv))
|
||||||
"point_${hv.toInt()}",
|
|
||||||
SimpleNumassPoint(points, hv)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.build()
|
}.build()
|
||||||
|
@ -39,7 +39,7 @@ fun main(args: Array<String>) {
|
|||||||
.generateBlock(start.plusNanos(it * length), length)
|
.generateBlock(start.plusNanos(it * length), length)
|
||||||
}
|
}
|
||||||
}.join(Global) { blocks ->
|
}.join(Global) { blocks ->
|
||||||
SimpleNumassPoint(blocks, 12000.0)
|
SimpleNumassPoint.build(blocks, 12000.0)
|
||||||
}.get()
|
}.get()
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ fun main(args: Array<String>) {
|
|||||||
.generateBlock(start.plusNanos(it * length), length)
|
.generateBlock(start.plusNanos(it * length), length)
|
||||||
}
|
}
|
||||||
}.join(Global) { blocks ->
|
}.join(Global) { blocks ->
|
||||||
SimpleNumassPoint(blocks, 18000.0)
|
SimpleNumassPoint.build(blocks, 18000.0)
|
||||||
}.get()
|
}.get()
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
package inr.numass.scripts.timeanalysis
|
||||||
|
|
||||||
|
import hep.dataforge.buildContext
|
||||||
|
import hep.dataforge.fx.output.FXOutputManager
|
||||||
|
import hep.dataforge.meta.buildMeta
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
||||||
|
import inr.numass.NumassPlugin
|
||||||
|
import inr.numass.data.analyzers.TimeAnalyzer
|
||||||
|
import inr.numass.data.api.NumassSet
|
||||||
|
import inr.numass.data.storage.NumassDirectory
|
||||||
|
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
val context = buildContext("NUMASS", NumassPlugin::class.java, JFreeChartPlugin::class.java) {
|
||||||
|
output = FXOutputManager()
|
||||||
|
rootDir = "D:\\Work\\Numass\\sterile2017_05"
|
||||||
|
dataDir = "D:\\Work\\Numass\\data\\2017_05"
|
||||||
|
}
|
||||||
|
|
||||||
|
val storage = NumassDirectory.read(context, "Fill_3")!!
|
||||||
|
|
||||||
|
val loader = storage.provide("set_10", NumassSet::class.java).get()
|
||||||
|
|
||||||
|
val point = loader.getPoints(18050.00).first()
|
||||||
|
|
||||||
|
val analyzer = TimeAnalyzer()
|
||||||
|
|
||||||
|
val meta = buildMeta("analyzer") {
|
||||||
|
"t0" to 3000
|
||||||
|
"inverted" to false
|
||||||
|
//"chunkSize" to 5000
|
||||||
|
//"mean" to TimeAnalyzer.AveragingMethod.ARITHMETIC
|
||||||
|
}
|
||||||
|
|
||||||
|
println(analyzer.analyze(point, meta))
|
||||||
|
|
||||||
|
println(analyzer.getEventsWithDelay(point.firstBlock, meta ).count())
|
||||||
|
println(point.events.count())
|
||||||
|
println(point.firstBlock.events.count())
|
||||||
|
|
||||||
|
// val time = point.events.asSequence().zipWithNext().map { (p, n) ->
|
||||||
|
// n.timeOffset - p.timeOffset
|
||||||
|
// }.filter { it > 0 }.sum()
|
||||||
|
|
||||||
|
val time = analyzer.getEventsWithDelay(point.firstBlock, meta ).map { it.second }.filter { it > 0 }.sum()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// val totalN = AtomicLong(0)
|
||||||
|
// val totalT = AtomicLong(0)
|
||||||
|
//
|
||||||
|
// analyzer.getEventsWithDelay(point.firstBlock, meta ).filter { pair -> pair.second >= 3000 }
|
||||||
|
// .forEach { pair ->
|
||||||
|
// totalN.incrementAndGet()
|
||||||
|
// //TODO add progress listener here
|
||||||
|
// totalT.addAndGet(pair.second)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val time = totalT.get()
|
||||||
|
|
||||||
|
println(time / 1e9)
|
||||||
|
|
||||||
|
//
|
||||||
|
// val cr = 80.0
|
||||||
|
// val length = 5e9.toLong()
|
||||||
|
// val num = 6
|
||||||
|
// val dt = 6.5
|
||||||
|
//
|
||||||
|
// val start = Instant.now()
|
||||||
|
//
|
||||||
|
// val generator = SynchronizedRandomGenerator(JDKRandomGenerator(2223))
|
||||||
|
//
|
||||||
|
// repeat(100) {
|
||||||
|
//
|
||||||
|
// val point = (1..num).map {
|
||||||
|
// Global.generate {
|
||||||
|
// NumassGenerator
|
||||||
|
// .generateEvents(cr , rnd = generator)
|
||||||
|
//// .withDeadTime { (dt * 1000).toLong() }
|
||||||
|
// .generateBlock(start.plusNanos(it * length), length)
|
||||||
|
// }
|
||||||
|
// }.join(Global) { blocks ->
|
||||||
|
// SimpleNumassPoint.build(blocks, 12000.0)
|
||||||
|
// }.get()
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// println(analyzer.analyze(point, meta))
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package inr.numass.scripts.tristan
|
package inr.numass.scripts.tristan
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.fx.output.FXOutputManager
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
||||||
import inr.numass.data.ProtoNumassPoint
|
import inr.numass.data.ProtoNumassPoint
|
||||||
import inr.numass.data.plotAmplitudeSpectrum
|
import inr.numass.data.plotAmplitudeSpectrum
|
||||||
import inr.numass.data.transformChain
|
import inr.numass.data.transformChain
|
||||||
@ -7,19 +10,22 @@ import kotlinx.coroutines.runBlocking
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val file = File("D:\\Work\\Numass\\data\\TRISTAN_11_2017\\df\\gun_16_19.df").toPath()
|
Global.output = FXOutputManager()
|
||||||
|
JFreeChartPlugin().startGlobal()
|
||||||
|
|
||||||
|
val file = File("D:\\Work\\Numass\\data\\2018_04\\Fill_3\\set_4\\p129(30s)(HV1=13000)").toPath()
|
||||||
val point = ProtoNumassPoint.readFile(file)
|
val point = ProtoNumassPoint.readFile(file)
|
||||||
point.plotAmplitudeSpectrum()
|
Global.plotAmplitudeSpectrum(point)
|
||||||
|
|
||||||
point.blocks.firstOrNull { it.channel == 0 }?.let {
|
point.blocks.firstOrNull { it.channel == 0 }?.let {
|
||||||
it.plotAmplitudeSpectrum(plotName = "0") {
|
Global.plotAmplitudeSpectrum(it, plotName = "0") {
|
||||||
"title" to "pixel 0"
|
"title" to "pixel 0"
|
||||||
"binning" to 50
|
"binning" to 50
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
point.blocks.firstOrNull { it.channel == 4 }?.let {
|
point.blocks.firstOrNull { it.channel == 4 }?.let {
|
||||||
it.plotAmplitudeSpectrum(plotName = "4") {
|
Global.plotAmplitudeSpectrum(it, plotName = "4") {
|
||||||
"title" to "pixel 4"
|
"title" to "pixel 4"
|
||||||
"binning" to 50
|
"binning" to 50
|
||||||
}
|
}
|
||||||
@ -29,7 +35,7 @@ fun main(args: Array<String>) {
|
|||||||
runBlocking {
|
runBlocking {
|
||||||
listOf(0, 20, 50, 100, 200).forEach { window ->
|
listOf(0, 20, 50, 100, 200).forEach { window ->
|
||||||
|
|
||||||
point.transformChain { first, second ->
|
Global.plotAmplitudeSpectrum(point.transformChain { first, second ->
|
||||||
val dt = second.timeOffset - first.timeOffset
|
val dt = second.timeOffset - first.timeOffset
|
||||||
if (second.channel == 4 && first.channel == 0 && dt > window && dt < 1000) {
|
if (second.channel == 4 && first.channel == 0 && dt > window && dt < 1000) {
|
||||||
Pair((first.amplitude + second.amplitude).toShort(), second.timeOffset)
|
Pair((first.amplitude + second.amplitude).toShort(), second.timeOffset)
|
||||||
@ -38,7 +44,7 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
println("Number of events for $window is ${it.events.count()}")
|
println("Number of events for $window is ${it.events.count()}")
|
||||||
}.plotAmplitudeSpectrum(plotName = "filtered.before.$window") {
|
}, plotName = "filtered.before.$window") {
|
||||||
"binning" to 50
|
"binning" to 50
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +52,7 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
listOf(0, 20, 50, 100, 200).forEach { window ->
|
listOf(0, 20, 50, 100, 200).forEach { window ->
|
||||||
|
|
||||||
point.transformChain { first, second ->
|
Global.plotAmplitudeSpectrum(point.transformChain { first, second ->
|
||||||
val dt = second.timeOffset - first.timeOffset
|
val dt = second.timeOffset - first.timeOffset
|
||||||
if (second.channel == 0 && first.channel == 4 && dt > window && dt < 1000) {
|
if (second.channel == 0 && first.channel == 4 && dt > window && dt < 1000) {
|
||||||
Pair((first.amplitude + second.amplitude).toShort(), second.timeOffset)
|
Pair((first.amplitude + second.amplitude).toShort(), second.timeOffset)
|
||||||
@ -55,11 +61,13 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
println("Number of events for $window is ${it.events.count()}")
|
println("Number of events for $window is ${it.events.count()}")
|
||||||
}.plotAmplitudeSpectrum(plotName = "filtered.after.$window") {
|
}, plotName = "filtered.after.$window") {
|
||||||
"binning" to 50
|
"binning" to 50
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readLine()
|
||||||
}
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package inr.numass.scripts.tristan
|
||||||
|
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.meta.value
|
||||||
|
import hep.dataforge.useValue
|
||||||
|
import inr.numass.data.analyzers.TimeAnalyzer
|
||||||
|
import inr.numass.data.api.NumassBlock
|
||||||
|
import inr.numass.data.api.NumassEvent
|
||||||
|
|
||||||
|
object TristanAnalyzer : TimeAnalyzer() {
|
||||||
|
override fun getEvents(block: NumassBlock, meta: Meta): List<NumassEvent> {
|
||||||
|
val t0 = getT0(block, meta).toLong()
|
||||||
|
val summTime = meta.getInt("summTime", 200) //time limit in nanos for event summation
|
||||||
|
var sequence = sequence {
|
||||||
|
var last: NumassEvent? = null
|
||||||
|
var amp: Int = 0
|
||||||
|
getEventsWithDelay(block, meta).forEach { (event, time) ->
|
||||||
|
when {
|
||||||
|
last == null -> {
|
||||||
|
last = event
|
||||||
|
}
|
||||||
|
time < 0 -> error("Can't be")
|
||||||
|
time < summTime -> {
|
||||||
|
//add to amplitude
|
||||||
|
amp += event.amplitude
|
||||||
|
}
|
||||||
|
time > t0 -> {
|
||||||
|
//accept new event and reset summator
|
||||||
|
if (amp != 0) {
|
||||||
|
//construct new event with pileup
|
||||||
|
yield(NumassEvent(amp.toShort(), last!!.timeOffset, last!!.owner))
|
||||||
|
} else {
|
||||||
|
//yield event without changes if there is no pileup
|
||||||
|
yield(last!!)
|
||||||
|
}
|
||||||
|
last = event
|
||||||
|
amp = event.amplitude.toInt()
|
||||||
|
}
|
||||||
|
//else ignore event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.useValue("allowedChannels"){
|
||||||
|
val list = it.list.map { it.int }
|
||||||
|
sequence = sequence.filter { it.channel in list }
|
||||||
|
}
|
||||||
|
|
||||||
|
return sequence.toList()
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package inr.numass.scripts.tristan
|
package inr.numass.scripts.tristan
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.fx.output.FXOutputManager
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
||||||
import inr.numass.data.ProtoNumassPoint
|
import inr.numass.data.ProtoNumassPoint
|
||||||
import inr.numass.data.api.MetaBlock
|
import inr.numass.data.api.MetaBlock
|
||||||
import inr.numass.data.api.NumassBlock
|
import inr.numass.data.api.NumassBlock
|
||||||
@ -18,11 +21,17 @@ private fun NumassPoint.getChannels(): Map<Int, NumassBlock> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main() {
|
||||||
val file = File("D:\\Work\\Numass\\data\\17kV\\processed.df").toPath()
|
val file = File("D:\\Work\\Numass\\data\\2018_04\\Fill_3\\set_4\\p129(30s)(HV1=13000)").toPath()
|
||||||
val point = ProtoNumassPoint.readFile(file)
|
val point = ProtoNumassPoint.readFile(file)
|
||||||
println(point.meta)
|
println(point.meta)
|
||||||
point.getChannels().forEach{ num, block ->
|
|
||||||
block.plotAmplitudeSpectrum(plotName = num.toString())
|
Global.output = FXOutputManager()
|
||||||
|
JFreeChartPlugin().startGlobal()
|
||||||
|
|
||||||
|
point.getChannels().forEach{ (num, block) ->
|
||||||
|
Global.plotAmplitudeSpectrum(numassBlock = block, plotName = num.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readLine()
|
||||||
}
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package inr.numass.scripts.tristan
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.fx.output.FXOutputManager
|
||||||
|
import hep.dataforge.fx.plots.group
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
||||||
|
import hep.dataforge.plots.output.plotFrame
|
||||||
|
import inr.numass.data.plotAmplitudeSpectrum
|
||||||
|
import inr.numass.data.storage.readNumassSet
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
Global.output = FXOutputManager()
|
||||||
|
JFreeChartPlugin().startGlobal()
|
||||||
|
|
||||||
|
val file = File("D:\\Work\\Numass\\data\\2018_04\\Fill_3\\set_36").toPath()
|
||||||
|
val set = Global.readNumassSet(file)
|
||||||
|
|
||||||
|
|
||||||
|
Global.plotFrame("compare") {
|
||||||
|
listOf(12000.0, 13000.0, 14000.0, 14900.0).forEach {voltage->
|
||||||
|
val point = set.optPoint(voltage).get()
|
||||||
|
|
||||||
|
group("${set.name}/p${point.index}[${point.voltage}]") {
|
||||||
|
plotAmplitudeSpectrum(point, "cut", analyzer = TristanAnalyzer) {
|
||||||
|
// "t0" to 3e3
|
||||||
|
"summTime" to 200
|
||||||
|
"sortEvents" to true
|
||||||
|
"inverted" to false
|
||||||
|
}
|
||||||
|
plotAmplitudeSpectrum(point, "uncut",analyzer = TristanAnalyzer){
|
||||||
|
"summTime" to 0
|
||||||
|
"sortEvents" to true
|
||||||
|
"inverted" to false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readLine()
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package inr.numass.scripts.tristan
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.fx.output.FXOutputManager
|
||||||
|
import hep.dataforge.fx.plots.group
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
||||||
|
import hep.dataforge.plots.output.plotFrame
|
||||||
|
import inr.numass.data.plotAmplitudeSpectrum
|
||||||
|
import inr.numass.data.storage.readNumassSet
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
Global.output = FXOutputManager()
|
||||||
|
JFreeChartPlugin().startGlobal()
|
||||||
|
|
||||||
|
val file = File("D:\\Work\\Numass\\data\\2018_04\\Fill_3\\set_36").toPath()
|
||||||
|
val set = Global.readNumassSet(file)
|
||||||
|
|
||||||
|
|
||||||
|
Global.plotFrame("compare") {
|
||||||
|
listOf(12000.0, 13000.0, 14000.0, 14900.0).forEach {voltage->
|
||||||
|
val point = set.optPoint(voltage).get()
|
||||||
|
|
||||||
|
group("${set.name}/p${point.index}[${point.voltage}]") {
|
||||||
|
plotAmplitudeSpectrum(point, "cut") {
|
||||||
|
"t0" to 3e3
|
||||||
|
"sortEvents" to true
|
||||||
|
}
|
||||||
|
plotAmplitudeSpectrum(point, "uncut")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readLine()
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package inr.numass.scripts.tristan
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.fx.output.FXOutputManager
|
||||||
|
import hep.dataforge.fx.plots.group
|
||||||
|
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
|
||||||
|
import hep.dataforge.plots.output.plotFrame
|
||||||
|
import inr.numass.data.plotAmplitudeSpectrum
|
||||||
|
import inr.numass.data.storage.readNumassSet
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
Global.output = FXOutputManager()
|
||||||
|
JFreeChartPlugin().startGlobal()
|
||||||
|
|
||||||
|
val file = File("D:\\Work\\Numass\\data\\2018_04\\Fill_3\\set_36").toPath()
|
||||||
|
val set = Global.readNumassSet(file)
|
||||||
|
|
||||||
|
|
||||||
|
Global.plotFrame("compare") {
|
||||||
|
listOf(12000.0, 13000.0, 14000.0, 14900.0).forEach {voltage->
|
||||||
|
val point = set.optPoint(voltage).get()
|
||||||
|
val block = point.channel(0)!!
|
||||||
|
|
||||||
|
group("${set.name}/p${point.index}[${point.voltage}]") {
|
||||||
|
plotAmplitudeSpectrum(block, "cut") {
|
||||||
|
"t0" to 3e3
|
||||||
|
"sortEvents" to true
|
||||||
|
}
|
||||||
|
plotAmplitudeSpectrum(block, "uncut")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readLine()
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
package inr.numass.scripts.utils
|
||||||
|
|
@ -6,17 +6,16 @@ import hep.dataforge.data.DataNode
|
|||||||
import hep.dataforge.data.DataSet
|
import hep.dataforge.data.DataSet
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.buildMeta
|
import hep.dataforge.meta.buildMeta
|
||||||
|
import hep.dataforge.nullable
|
||||||
import hep.dataforge.storage.Storage
|
import hep.dataforge.storage.Storage
|
||||||
import hep.dataforge.tables.ListTable
|
import hep.dataforge.tables.ListTable
|
||||||
import hep.dataforge.tables.Table
|
import hep.dataforge.tables.Table
|
||||||
|
import hep.dataforge.toList
|
||||||
import hep.dataforge.values.ValueMap
|
import hep.dataforge.values.ValueMap
|
||||||
import hep.dataforge.values.Values
|
import hep.dataforge.values.Values
|
||||||
import inr.numass.data.analyzers.NumassAnalyzer
|
import inr.numass.data.analyzers.*
|
||||||
import inr.numass.data.analyzers.NumassAnalyzer.Companion.CHANNEL_KEY
|
import inr.numass.data.analyzers.NumassAnalyzer.Companion.CHANNEL_KEY
|
||||||
import inr.numass.data.analyzers.NumassAnalyzer.Companion.COUNT_RATE_KEY
|
import inr.numass.data.analyzers.NumassAnalyzer.Companion.COUNT_RATE_KEY
|
||||||
import inr.numass.data.analyzers.SmartAnalyzer
|
|
||||||
import inr.numass.data.analyzers.TimeAnalyzer
|
|
||||||
import inr.numass.data.analyzers.withBinning
|
|
||||||
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.api.SimpleNumassPoint
|
import inr.numass.data.api.SimpleNumassPoint
|
||||||
@ -27,7 +26,9 @@ import org.apache.commons.math3.analysis.ParametricUnivariateFunction
|
|||||||
import org.apache.commons.math3.exception.DimensionMismatchException
|
import org.apache.commons.math3.exception.DimensionMismatchException
|
||||||
import org.apache.commons.math3.fitting.SimpleCurveFitter
|
import org.apache.commons.math3.fitting.SimpleCurveFitter
|
||||||
import org.apache.commons.math3.fitting.WeightedObservedPoint
|
import org.apache.commons.math3.fitting.WeightedObservedPoint
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import java.util.stream.Collectors
|
import java.util.stream.Collectors
|
||||||
|
import java.util.stream.StreamSupport
|
||||||
|
|
||||||
|
|
||||||
object Threshold {
|
object Threshold {
|
||||||
@ -37,13 +38,13 @@ object Threshold {
|
|||||||
//creating storage instance
|
//creating storage instance
|
||||||
val storage = NumassDirectory.read(context, meta.getString("data.dir")) as Storage
|
val storage = NumassDirectory.read(context, meta.getString("data.dir")) as Storage
|
||||||
|
|
||||||
fun Storage.loaders(): Sequence<NumassDataLoader>{
|
fun Storage.loaders(): Sequence<NumassDataLoader> {
|
||||||
return sequence<NumassDataLoader> {
|
return sequence<NumassDataLoader> {
|
||||||
print("Reading ${this@loaders.fullName}")
|
print("Reading ${this@loaders.fullName}")
|
||||||
runBlocking { this@loaders.children }.forEach {
|
runBlocking { this@loaders.children }.forEach {
|
||||||
if(it is NumassDataLoader){
|
if (it is NumassDataLoader) {
|
||||||
yield(it)
|
yield(it)
|
||||||
} else if (it is Storage){
|
} else if (it is Storage) {
|
||||||
yieldAll(it.loaders())
|
yieldAll(it.loaders())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,19 +54,19 @@ object Threshold {
|
|||||||
//Reading points
|
//Reading points
|
||||||
//Free operation. No reading done
|
//Free operation. No reading done
|
||||||
val sets = storage.loaders()
|
val sets = storage.loaders()
|
||||||
.filter { it.fullName.toString().matches(meta.getString("data.mask").toRegex()) }
|
.filter { it.fullName.toString().matches(meta.getString("data.mask").toRegex()) }
|
||||||
|
|
||||||
val analyzer = TimeAnalyzer();
|
val analyzer = TimeAnalyzer();
|
||||||
|
|
||||||
val data = DataSet.edit(NumassPoint::class).also { dataBuilder ->
|
val data = DataSet.edit(NumassPoint::class).also { dataBuilder ->
|
||||||
sets.sortedBy { it.startTime }
|
sets.sortedBy { it.startTime }
|
||||||
.flatMap { set -> set.points.asSequence() }
|
.flatMap { set -> set.points.asSequence() }
|
||||||
.groupBy { it.voltage }
|
.groupBy { it.voltage }
|
||||||
.forEach { key, value ->
|
.forEach { key, value ->
|
||||||
val point = SimpleNumassPoint(value, key)
|
val point = SimpleNumassPoint.build(value, key)
|
||||||
val name = key.toInt().toString()
|
val name = key.toInt().toString()
|
||||||
dataBuilder.putStatic(name, point, buildMeta("meta", "voltage" to key));
|
dataBuilder.putStatic(name, point, buildMeta("meta", "voltage" to key));
|
||||||
}
|
}
|
||||||
}.build()
|
}.build()
|
||||||
|
|
||||||
return data.pipe(context, meta) {
|
return data.pipe(context, meta) {
|
||||||
@ -92,13 +93,14 @@ object Threshold {
|
|||||||
// )
|
// )
|
||||||
|
|
||||||
return binned.rows
|
return binned.rows
|
||||||
.map {
|
.map {
|
||||||
WeightedObservedPoint(
|
WeightedObservedPoint(
|
||||||
1.0,//1d / p.getValue() , //weight
|
1.0,//1d / p.getValue() , //weight
|
||||||
it.getDouble(CHANNEL_KEY), // x
|
it.getDouble(CHANNEL_KEY), // x
|
||||||
it.getDouble(COUNT_RATE_KEY) / binning) //y
|
it.getDouble(COUNT_RATE_KEY) / binning
|
||||||
}
|
) //y
|
||||||
.collect(Collectors.toList())
|
}
|
||||||
|
.collect(Collectors.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun norm(spectrum: Table, xLow: Int, upper: Int): Double {
|
private fun norm(spectrum: Table, xLow: Int, upper: Int): Double {
|
||||||
@ -134,11 +136,10 @@ object Threshold {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exponential function $a e^{\frac{x}{\sigma}}$
|
* Exponential function $a e^{\frac{x}{\sigma}}$
|
||||||
*/
|
*/
|
||||||
private fun exponential(spectrum: Table, voltage: Double, config: Meta): Values {
|
private fun exponential(point: NumassPoint, spectrum: Table, config: Meta): Values {
|
||||||
val xLow: Int = config.getInt("xLow", 400)
|
val xLow: Int = config.getInt("xLow", 400)
|
||||||
val xHigh: Int = config.getInt("xHigh", 700)
|
val xHigh: Int = config.getInt("xHigh", 700)
|
||||||
val upper: Int = config.getInt("upper", 3100)
|
val upper: Int = config.getInt("upper", 3100)
|
||||||
@ -151,10 +152,11 @@ object Threshold {
|
|||||||
val norm = norm(spectrum, xLow, upper)
|
val norm = norm(spectrum, xLow, upper)
|
||||||
|
|
||||||
return ValueMap.ofPairs(
|
return ValueMap.ofPairs(
|
||||||
"U" to voltage,
|
"index" to point.index,
|
||||||
"a" to a,
|
"U" to point.voltage,
|
||||||
"sigma" to sigma,
|
"a" to a,
|
||||||
"correction" to a * sigma * Math.exp(xLow / sigma) / norm + 1.0
|
"sigma" to sigma,
|
||||||
|
"correction" to a * sigma * Math.exp(xLow / sigma) / norm + 1.0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,14 +177,14 @@ object Threshold {
|
|||||||
val delta = shift ?: parameters[2]
|
val delta = shift ?: parameters[2]
|
||||||
return if (parameters.size > 2) {
|
return if (parameters.size > 2) {
|
||||||
doubleArrayOf(
|
doubleArrayOf(
|
||||||
Math.pow(x - delta, beta),
|
Math.pow(x - delta, beta),
|
||||||
a * Math.pow(x - delta, beta) * Math.log(x - delta),
|
a * Math.pow(x - delta, beta) * Math.log(x - delta),
|
||||||
-a * beta * Math.pow(x - delta, beta - 1)
|
-a * beta * Math.pow(x - delta, beta - 1)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
doubleArrayOf(
|
doubleArrayOf(
|
||||||
Math.pow(x - delta, beta),
|
Math.pow(x - delta, beta),
|
||||||
a * Math.pow(x - delta, beta) * Math.log(x - delta)
|
a * Math.pow(x - delta, beta) * Math.log(x - delta)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,7 +193,7 @@ object Threshold {
|
|||||||
/**
|
/**
|
||||||
* Power function $a (x-\delta)^{\beta}
|
* Power function $a (x-\delta)^{\beta}
|
||||||
*/
|
*/
|
||||||
private fun power(spectrum: Table, voltage: Double, config: Meta): Values {
|
private fun power(point: NumassPoint, spectrum: Table, config: Meta): Values {
|
||||||
val xLow: Int = config.getInt("xLow", 400)
|
val xLow: Int = config.getInt("xLow", 400)
|
||||||
val xHigh: Int = config.getInt("xHigh", 700)
|
val xHigh: Int = config.getInt("xHigh", 700)
|
||||||
val upper: Int = config.getInt("upper", 3100)
|
val upper: Int = config.getInt("upper", 3100)
|
||||||
@ -208,27 +210,51 @@ object Threshold {
|
|||||||
val norm = norm(spectrum, xLow, upper)
|
val norm = norm(spectrum, xLow, upper)
|
||||||
|
|
||||||
return ValueMap.ofPairs(
|
return ValueMap.ofPairs(
|
||||||
"U" to voltage,
|
"index" to point.index,
|
||||||
"a" to a,
|
"U" to point.voltage,
|
||||||
"beta" to beta,
|
"a" to a,
|
||||||
"delta" to delta,
|
"beta" to beta,
|
||||||
"correction" to a / (beta + 1) * Math.pow(xLow - delta, beta + 1.0) / norm + 1.0
|
"delta" to delta,
|
||||||
|
"correction" to a / (beta + 1) * Math.pow(xLow - delta, beta + 1.0) / norm + 1.0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateSubThreshold(spectrum: Table, voltage: Double, config: Meta): Values {
|
fun calculateSubThreshold(point: NumassPoint, spectrum: Table, config: Meta): Values {
|
||||||
return when (config.getString("method", "exp")) {
|
return when (config.getString("method", "exp")) {
|
||||||
"exp" -> exponential(spectrum, voltage, config)
|
"exp" -> exponential(point, spectrum, config)
|
||||||
"pow" -> power(spectrum, voltage, config)
|
"pow" -> power(point, spectrum, config)
|
||||||
else -> throw RuntimeException("Unknown sub threshold calculation method")
|
else -> throw RuntimeException("Unknown sub threshold calculation method")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateSubThreshold(set: NumassSet, config: Meta, analyzer: NumassAnalyzer = SmartAnalyzer()): Table {
|
fun calculateSubThreshold(set: NumassSet, config: Meta, analyzer: NumassAnalyzer = SmartAnalyzer()): Table {
|
||||||
|
val reference = config.optNumber("reference").nullable?.let {
|
||||||
|
set.getPoints(it.toDouble()).firstOrNull() ?: error("Reference point not found")
|
||||||
|
}?.let {
|
||||||
|
println("Using reference point ${it.voltage}")
|
||||||
|
analyzer.getAmplitudeSpectrum(it, config)
|
||||||
|
}
|
||||||
|
|
||||||
return ListTable.Builder().apply {
|
return ListTable.Builder().apply {
|
||||||
set.forEach{
|
StreamSupport.stream(set.spliterator(), true).map { point ->
|
||||||
val spectrum = analyzer.getAmplitudeSpectrum(it,config)
|
LoggerFactory.getLogger(Threshold.javaClass).info("Starting point ${point.voltage}")
|
||||||
row(calculateSubThreshold(spectrum,it.voltage,config))
|
val spectrum = analyzer.getAmplitudeSpectrum(point, config).let {
|
||||||
|
if (reference == null) {
|
||||||
|
it
|
||||||
|
} else {
|
||||||
|
subtractAmplitudeSpectrum(it, reference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LoggerFactory.getLogger(Threshold.javaClass).info("Calculating threshold ${point.voltage}")
|
||||||
|
return@map try {
|
||||||
|
calculateSubThreshold(point, spectrum, config)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
LoggerFactory.getLogger(Threshold.javaClass).error("Failed to fit point ${point.voltage}", ex)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}.toList().filterNotNull().forEach {
|
||||||
|
println(it.toString())
|
||||||
|
row(it)
|
||||||
}
|
}
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
package inr.numass.tasks
|
package inr.numass.tasks
|
||||||
|
|
||||||
import hep.dataforge.configure
|
import hep.dataforge.configure
|
||||||
import hep.dataforge.data.CustomDataFilter
|
import hep.dataforge.data.*
|
||||||
import hep.dataforge.data.DataSet
|
|
||||||
import hep.dataforge.data.DataTree
|
|
||||||
import hep.dataforge.data.DataUtils
|
|
||||||
import hep.dataforge.io.output.stream
|
import hep.dataforge.io.output.stream
|
||||||
import hep.dataforge.io.render
|
import hep.dataforge.io.render
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.meta.MetaUtils
|
|
||||||
import hep.dataforge.meta.buildMeta
|
import hep.dataforge.meta.buildMeta
|
||||||
import hep.dataforge.nullable
|
import hep.dataforge.nullable
|
||||||
import hep.dataforge.plots.data.DataPlot
|
import hep.dataforge.plots.data.DataPlot
|
||||||
@ -22,19 +17,21 @@ import hep.dataforge.stat.fit.FitResult
|
|||||||
import hep.dataforge.stat.models.XYModel
|
import hep.dataforge.stat.models.XYModel
|
||||||
import hep.dataforge.tables.*
|
import hep.dataforge.tables.*
|
||||||
import hep.dataforge.useMeta
|
import hep.dataforge.useMeta
|
||||||
|
import hep.dataforge.useValue
|
||||||
import hep.dataforge.values.ValueType
|
import hep.dataforge.values.ValueType
|
||||||
import hep.dataforge.values.Values
|
import hep.dataforge.values.Values
|
||||||
import hep.dataforge.values.asValue
|
import hep.dataforge.values.asValue
|
||||||
|
import hep.dataforge.values.edit
|
||||||
import hep.dataforge.workspace.tasks.task
|
import hep.dataforge.workspace.tasks.task
|
||||||
import inr.numass.NumassUtils
|
import inr.numass.NumassUtils
|
||||||
import inr.numass.actions.MergeDataAction
|
import inr.numass.actions.MergeDataAction
|
||||||
import inr.numass.actions.MergeDataAction.MERGE_NAME
|
import inr.numass.actions.MergeDataAction.MERGE_NAME
|
||||||
import inr.numass.actions.TransformDataAction
|
import inr.numass.actions.TransformDataAction
|
||||||
import inr.numass.addSetMarkers
|
import inr.numass.addSetMarkers
|
||||||
import inr.numass.data.analyzers.NumassAnalyzer
|
|
||||||
import inr.numass.data.analyzers.NumassAnalyzer.Companion.CHANNEL_KEY
|
import inr.numass.data.analyzers.NumassAnalyzer.Companion.CHANNEL_KEY
|
||||||
import inr.numass.data.analyzers.NumassAnalyzer.Companion.COUNT_KEY
|
import inr.numass.data.analyzers.NumassAnalyzer.Companion.COUNT_KEY
|
||||||
import inr.numass.data.analyzers.SmartAnalyzer
|
import inr.numass.data.analyzers.SmartAnalyzer
|
||||||
|
import inr.numass.data.analyzers.countInWindow
|
||||||
import inr.numass.data.api.MetaBlock
|
import inr.numass.data.api.MetaBlock
|
||||||
import inr.numass.data.api.NumassPoint
|
import inr.numass.data.api.NumassPoint
|
||||||
import inr.numass.data.api.NumassSet
|
import inr.numass.data.api.NumassSet
|
||||||
@ -49,10 +46,17 @@ import java.util.stream.StreamSupport
|
|||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
|
|
||||||
|
private val filterForward = DataFilter.byMetaValue("iteration_info.reverse") {
|
||||||
|
!(it?.boolean ?: false)
|
||||||
|
}
|
||||||
|
private val filterReverse = DataFilter.byMetaValue("iteration_info.reverse") {
|
||||||
|
it?.boolean ?: false
|
||||||
|
}
|
||||||
|
|
||||||
val selectTask = task("select") {
|
val selectTask = task("select") {
|
||||||
descriptor {
|
descriptor {
|
||||||
info = "Select data from initial data pool"
|
info = "Select data from initial data pool"
|
||||||
|
value("forward", types = listOf(ValueType.BOOLEAN), info = "Select only forward or only backward sets")
|
||||||
}
|
}
|
||||||
model { meta ->
|
model { meta ->
|
||||||
data("*")
|
data("*")
|
||||||
@ -60,9 +64,18 @@ val selectTask = task("select") {
|
|||||||
}
|
}
|
||||||
transform<NumassSet> { data ->
|
transform<NumassSet> { data ->
|
||||||
logger.info("Starting selection from data node with size ${data.size}")
|
logger.info("Starting selection from data node with size ${data.size}")
|
||||||
CustomDataFilter(meta).filter(data.checked(NumassSet::class.java)).also {
|
var res = data.checked(NumassSet::class.java).filter(CustomDataFilter(meta))
|
||||||
logger.info("Selected ${it.size} elements")
|
|
||||||
|
meta.useValue("forward") {
|
||||||
|
res = if (it.boolean) {
|
||||||
|
res.filter(filterForward)
|
||||||
|
} else {
|
||||||
|
res.filter(filterReverse)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info("Selected ${res.size} elements")
|
||||||
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,41 +84,57 @@ val analyzeTask = task("analyze") {
|
|||||||
info = "Count the number of events for each voltage and produce a table with the results"
|
info = "Count the number of events for each voltage and produce a table with the results"
|
||||||
}
|
}
|
||||||
model { meta ->
|
model { meta ->
|
||||||
dependsOn(selectTask, meta);
|
dependsOn(selectTask, meta)
|
||||||
configure(MetaUtils.optEither(meta, "analyzer", "prepare").orElse(Meta.empty()))
|
configure {
|
||||||
|
"analyzer" to meta.getMetaOrEmpty("analyzer")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pipe<NumassSet, Table> { set ->
|
pipe<NumassSet, Table> { set ->
|
||||||
SmartAnalyzer().analyzeSet(set, meta).also { res ->
|
val res = SmartAnalyzer().analyzeSet(set, meta.getMeta("analyzer"))
|
||||||
val outputMeta = meta.builder.putNode("data", set.meta)
|
val outputMeta = meta.builder.putNode("data", set.meta)
|
||||||
context.output.render(res, stage = "numass.analyze", name = name, meta = outputMeta)
|
context.output.render(res, stage = "numass.analyze", name = name, meta = outputMeta)
|
||||||
}
|
return@pipe res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val monitorTableTask = task("monitor") {
|
val monitorTableTask = task("monitor") {
|
||||||
descriptor {
|
descriptor {
|
||||||
value("showPlot", types = listOf(ValueType.BOOLEAN), info = "Show plot after complete")
|
value("showPlot", types = listOf(ValueType.BOOLEAN), info = "Show plot after complete")
|
||||||
value("monitorVoltage", types = listOf(ValueType.NUMBER), info = "The voltage for monitor point")
|
value("monitorPoint", types = listOf(ValueType.NUMBER), info = "The voltage for monitor point")
|
||||||
}
|
}
|
||||||
model { meta ->
|
model { meta ->
|
||||||
dependsOn(selectTask, meta)
|
dependsOn(selectTask, meta)
|
||||||
|
// if (meta.getBoolean("monitor.correctForThreshold", false)) {
|
||||||
|
// dependsOn(subThresholdTask, meta, "threshold")
|
||||||
|
// }
|
||||||
configure(meta.getMetaOrEmpty("monitor"))
|
configure(meta.getMetaOrEmpty("monitor"))
|
||||||
configure {
|
configure {
|
||||||
meta.useMeta("analyzer") { putNode(it) }
|
meta.useMeta("analyzer") { putNode(it) }
|
||||||
|
setValue("@target", meta.getString("@target", meta.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
join<NumassSet, Table> { data ->
|
join<NumassSet, Table> { data ->
|
||||||
val monitorVoltage = meta.getDouble("monitorVoltage", 16000.0);
|
val monitorVoltage = meta.getDouble("monitorPoint", 16000.0);
|
||||||
val analyzer = SmartAnalyzer()
|
val analyzer = SmartAnalyzer()
|
||||||
val analyzerMeta = meta.getMetaOrEmpty("analyzer")
|
val analyzerMeta = meta.getMetaOrEmpty("analyzer")
|
||||||
|
|
||||||
|
//val thresholdCorrection = da
|
||||||
//TODO add separator labels
|
//TODO add separator labels
|
||||||
val res = ListTable.Builder("timestamp", "count", "cr", "crErr")
|
val res = ListTable.Builder("timestamp", "count", "cr", "crErr", "index", "set")
|
||||||
.rows(
|
.rows(
|
||||||
data.values.stream().parallel()
|
data.values.stream().flatMap { set ->
|
||||||
.flatMap { it.points.stream() }
|
set.points.stream()
|
||||||
.filter { it.voltage == monitorVoltage }
|
.filter { it.voltage == monitorVoltage }
|
||||||
.map { it -> analyzer.analyzeParent(it, analyzerMeta) }
|
.parallel()
|
||||||
).build()
|
.map { point ->
|
||||||
|
analyzer.analyzeParent(point, analyzerMeta).edit {
|
||||||
|
"index" to point.index
|
||||||
|
"set" to set.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
).build()
|
||||||
|
|
||||||
if (meta.getBoolean("showPlot", true)) {
|
if (meta.getBoolean("showPlot", true)) {
|
||||||
val plot = DataPlot.plot(name, res, Adapters.buildXYAdapter("timestamp", "cr", "crErr"))
|
val plot = DataPlot.plot(name, res, Adapters.buildXYAdapter("timestamp", "cr", "crErr"))
|
||||||
@ -115,10 +144,11 @@ val monitorTableTask = task("monitor") {
|
|||||||
"yAxis.title" to "Count rate"
|
"yAxis.title" to "Count rate"
|
||||||
"yAxis.units" to "Hz"
|
"yAxis.units" to "Hz"
|
||||||
}
|
}
|
||||||
|
|
||||||
((context.output["numass.monitor", name] as? PlotOutput)?.frame as? JFreeChartFrame)?.addSetMarkers(data.values)
|
((context.output["numass.monitor", name] as? PlotOutput)?.frame as? JFreeChartFrame)?.addSetMarkers(data.values)
|
||||||
}
|
}
|
||||||
|
|
||||||
context.output["numass.monitor", name].render(NumassUtils.wrap(res, meta))
|
context.output.render(res, stage = "numass.monitor", name = name, meta = meta)
|
||||||
|
|
||||||
return@join res;
|
return@join res;
|
||||||
}
|
}
|
||||||
@ -126,7 +156,7 @@ val monitorTableTask = task("monitor") {
|
|||||||
|
|
||||||
val mergeTask = task("merge") {
|
val mergeTask = task("merge") {
|
||||||
model { meta ->
|
model { meta ->
|
||||||
dependsOn(analyzeTask, meta)
|
dependsOn(transformTask, meta)
|
||||||
configure(meta.getMetaOrEmpty("merge"))
|
configure(meta.getMetaOrEmpty("merge"))
|
||||||
}
|
}
|
||||||
action(MergeDataAction)
|
action(MergeDataAction)
|
||||||
@ -139,10 +169,10 @@ val mergeEmptyTask = task("empty") {
|
|||||||
}
|
}
|
||||||
//replace data node by "empty" node
|
//replace data node by "empty" node
|
||||||
val newMeta = meta.builder
|
val newMeta = meta.builder
|
||||||
.removeNode("data")
|
.removeNode("data")
|
||||||
.removeNode("empty")
|
.removeNode("empty")
|
||||||
.setNode("data", meta.getMeta("empty"))
|
.setNode("data", meta.getMeta("empty"))
|
||||||
.setValue("merge.$MERGE_NAME", meta.getString("merge.$MERGE_NAME", "") + "_empty");
|
.setValue("merge.$MERGE_NAME", meta.getString("merge.$MERGE_NAME", "") + "_empty")
|
||||||
dependsOn(mergeTask, newMeta)
|
dependsOn(mergeTask, newMeta)
|
||||||
}
|
}
|
||||||
transform<Table> { data ->
|
transform<Table> { data ->
|
||||||
@ -158,13 +188,18 @@ val mergeEmptyTask = task("empty") {
|
|||||||
val subtractEmptyTask = task("dif") {
|
val subtractEmptyTask = task("dif") {
|
||||||
model { meta ->
|
model { meta ->
|
||||||
dependsOn(mergeTask, meta, "data")
|
dependsOn(mergeTask, meta, "data")
|
||||||
dependsOn(mergeEmptyTask, meta, "empty")
|
if (meta.hasMeta("empty")) {
|
||||||
|
dependsOn(mergeEmptyTask, meta, "empty")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
transform<Table> { data ->
|
transform<Table> { data ->
|
||||||
|
//ignore if there is no empty data
|
||||||
|
if (!meta.hasMeta("empty")) return@transform data
|
||||||
|
|
||||||
val builder = DataTree.edit(Table::class)
|
val builder = DataTree.edit(Table::class)
|
||||||
val rootNode = data.getCheckedNode("data", Table::class.java)
|
val rootNode = data.getCheckedNode("data", Table::class.java)
|
||||||
val empty = data.getCheckedNode("empty", Table::class.java).data
|
val empty = data.getCheckedNode("empty", Table::class.java).data
|
||||||
?: throw RuntimeException("No empty data found")
|
?: throw RuntimeException("No empty data found")
|
||||||
|
|
||||||
rootNode.visit(Table::class.java) { input ->
|
rootNode.visit(Table::class.java) { input ->
|
||||||
val resMeta = buildMeta {
|
val resMeta = buildMeta {
|
||||||
@ -185,34 +220,36 @@ val subtractEmptyTask = task("dif") {
|
|||||||
|
|
||||||
val transformTask = task("transform") {
|
val transformTask = task("transform") {
|
||||||
model { meta ->
|
model { meta ->
|
||||||
if (meta.hasMeta("merge")) {
|
dependsOn(analyzeTask, meta)
|
||||||
if (meta.hasMeta("empty")) {
|
|
||||||
dependsOn(subtractEmptyTask, meta)
|
|
||||||
} else {
|
|
||||||
dependsOn(mergeTask, meta);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dependsOn(analyzeTask, meta);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
action<Table, Table>(TransformDataAction)
|
action(TransformDataAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
val filterTask = task("filter") {
|
val filterTask = task("filter") {
|
||||||
model { meta ->
|
model { meta ->
|
||||||
dependsOn(transformTask, meta)
|
if (meta.hasMeta("merge")) {
|
||||||
|
dependsOn(subtractEmptyTask, meta)
|
||||||
|
} else {
|
||||||
|
dependsOn(analyzeTask, meta)
|
||||||
|
}
|
||||||
|
configure(meta.getMetaOrEmpty("filter"))
|
||||||
}
|
}
|
||||||
pipe<Table, Table> { data ->
|
pipe<Table, Table> { data ->
|
||||||
if (meta.hasValue("from") || meta.hasValue("to")) {
|
|
||||||
|
if(meta.isEmpty) return@pipe data
|
||||||
|
|
||||||
|
val result = if (meta.hasValue("from") || meta.hasValue("to")) {
|
||||||
val uLo = meta.getDouble("from", 0.0)
|
val uLo = meta.getDouble("from", 0.0)
|
||||||
val uHi = meta.getDouble("to", java.lang.Double.POSITIVE_INFINITY)
|
val uHi = meta.getDouble("to", java.lang.Double.POSITIVE_INFINITY)
|
||||||
this.log.report("Filtering finished")
|
|
||||||
Tables.filter(data, NumassPoint.HV_KEY, uLo, uHi)
|
Tables.filter(data, NumassPoint.HV_KEY, uLo, uHi)
|
||||||
} else if (meta.hasValue("condition")) {
|
} else if (meta.hasValue("condition")) {
|
||||||
Tables.filter(data, Predicate { ExpressionUtils.condition(meta.getString("condition"), it.unbox()) })
|
Tables.filter(data, Predicate { ExpressionUtils.condition(meta.getString("condition"), it.unbox()) })
|
||||||
} else {
|
} else {
|
||||||
throw RuntimeException("No filtering condition specified")
|
throw RuntimeException("No filtering condition specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.output.render(result, name = this.name, stage = "numass.filter")
|
||||||
|
return@pipe result
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -230,16 +267,16 @@ val fitTask = task("fit") {
|
|||||||
writer.flush()
|
writer.flush()
|
||||||
|
|
||||||
FitHelper(context).fit(data, meta)
|
FitHelper(context).fit(data, meta)
|
||||||
.setListenerStream(out)
|
.setListenerStream(out)
|
||||||
.report(log)
|
.report(log)
|
||||||
.run()
|
.run()
|
||||||
.also {
|
.also {
|
||||||
if (meta.getBoolean("printLog", true)) {
|
if (meta.getBoolean("printLog", true)) {
|
||||||
writer.println()
|
writer.println()
|
||||||
log.entries.forEach { entry -> writer.println(entry.toString()) }
|
log.entries.forEach { entry -> writer.println(entry.toString()) }
|
||||||
writer.println()
|
writer.println()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,7 +299,7 @@ val plotFitTask = task("plotFit") {
|
|||||||
|
|
||||||
// ensuring all data points are calculated explicitly
|
// ensuring all data points are calculated explicitly
|
||||||
StreamSupport.stream<Values>(data.spliterator(), false)
|
StreamSupport.stream<Values>(data.spliterator(), false)
|
||||||
.map { dp -> Adapters.getXValue(adapter, dp).double }.sorted().forEach { fit.calculateIn(it) }
|
.map { dp -> Adapters.getXValue(adapter, dp).double }.sorted().forEach { fit.calculateIn(it) }
|
||||||
|
|
||||||
val dataPlot = DataPlot.plot("data", data, adapter)
|
val dataPlot = DataPlot.plot("data", data, adapter)
|
||||||
|
|
||||||
@ -275,9 +312,24 @@ val plotFitTask = task("plotFit") {
|
|||||||
val histogramTask = task("histogram") {
|
val histogramTask = task("histogram") {
|
||||||
descriptor {
|
descriptor {
|
||||||
value("plot", types = listOf(ValueType.BOOLEAN), defaultValue = false, info = "Show plot of the spectra")
|
value("plot", types = listOf(ValueType.BOOLEAN), defaultValue = false, info = "Show plot of the spectra")
|
||||||
value("points", multiple = true, types = listOf(ValueType.NUMBER), info = "The list of point voltages to build histogram")
|
value(
|
||||||
value("binning", types = listOf(ValueType.NUMBER), defaultValue = 20, info = "The binning of resulting histogram")
|
"points",
|
||||||
value("normalize", types = listOf(ValueType.BOOLEAN), defaultValue = true, info = "If true reports the count rate in each bin, otherwise total count")
|
multiple = true,
|
||||||
|
types = listOf(ValueType.NUMBER),
|
||||||
|
info = "The list of point voltages to build histogram"
|
||||||
|
)
|
||||||
|
value(
|
||||||
|
"binning",
|
||||||
|
types = listOf(ValueType.NUMBER),
|
||||||
|
defaultValue = 16,
|
||||||
|
info = "The binning of resulting histogram"
|
||||||
|
)
|
||||||
|
value(
|
||||||
|
"normalize",
|
||||||
|
types = listOf(ValueType.BOOLEAN),
|
||||||
|
defaultValue = true,
|
||||||
|
info = "If true reports the count rate in each bin, otherwise total count"
|
||||||
|
)
|
||||||
info = "Combine amplitude spectra from multiple sets, but with the same U"
|
info = "Combine amplitude spectra from multiple sets, but with the same U"
|
||||||
}
|
}
|
||||||
model { meta ->
|
model { meta ->
|
||||||
@ -299,41 +351,41 @@ val histogramTask = task("histogram") {
|
|||||||
|
|
||||||
//Fill values to table
|
//Fill values to table
|
||||||
data.flatMap { it.value.points }
|
data.flatMap { it.value.points }
|
||||||
.filter { points == null || points.contains(it.voltage) }
|
.filter { points == null || points.contains(it.voltage) }
|
||||||
.groupBy { it.voltage }
|
.groupBy { it.voltage }
|
||||||
.mapValues {
|
.mapValues { (_, value) ->
|
||||||
analyzer.getAmplitudeSpectrum(MetaBlock(it.value))
|
analyzer.getAmplitudeSpectrum(MetaBlock(value), meta.getMetaOrEmpty("analyzer"))
|
||||||
}
|
}
|
||||||
.forEach { u, spectrum ->
|
.forEach { (u, spectrum) ->
|
||||||
log.report("Aggregating data from U = $u")
|
log.report("Aggregating data from U = $u")
|
||||||
spectrum.forEach {
|
spectrum.forEach {
|
||||||
val channel = it[CHANNEL_KEY].int
|
val channel = it[CHANNEL_KEY].int
|
||||||
val count = it[COUNT_KEY].long
|
val count = it[COUNT_KEY].long
|
||||||
aggregator.getOrPut(channel) { HashMap() }
|
aggregator.getOrPut(channel) { HashMap() }
|
||||||
.getOrPut(u) { AtomicLong() }
|
.getOrPut(u) { AtomicLong() }
|
||||||
.addAndGet(count)
|
.addAndGet(count)
|
||||||
}
|
|
||||||
names.add("U$u")
|
|
||||||
}
|
}
|
||||||
|
names.add("U$u")
|
||||||
|
}
|
||||||
|
|
||||||
val times: Map<Double, Double> = data.flatMap { it.value.points }
|
val times: Map<Double, Double> = data.flatMap { it.value.points }
|
||||||
.filter { points == null || points.contains(it.voltage) }
|
.filter { points == null || points.contains(it.voltage) }
|
||||||
.groupBy { it.voltage }
|
.groupBy { it.voltage }
|
||||||
.mapValues {
|
.mapValues {
|
||||||
it.value.sumByDouble { it.length.toMillis().toDouble() / 1000 }
|
it.value.sumByDouble { it.length.toMillis().toDouble() / 1000 }
|
||||||
}
|
}
|
||||||
|
|
||||||
val normalize = meta.getBoolean("normalize", true)
|
val normalize = meta.getBoolean("normalize", true)
|
||||||
|
|
||||||
log.report("Combining spectra")
|
log.report("Combining spectra")
|
||||||
val format = MetaTableFormat.forNames(names)
|
val format = MetaTableFormat.forNames(names)
|
||||||
val table = buildTable(format) {
|
val table = buildTable(format) {
|
||||||
aggregator.forEach { channel, counters ->
|
aggregator.forEach { (channel, counters) ->
|
||||||
val values: MutableMap<String, Any> = HashMap()
|
val values: MutableMap<String, Any> = HashMap()
|
||||||
values[NumassAnalyzer.CHANNEL_KEY] = channel
|
values[CHANNEL_KEY] = channel
|
||||||
counters.forEach { u, counter ->
|
counters.forEach { (u, counter) ->
|
||||||
if (normalize) {
|
if (normalize) {
|
||||||
values["U$u"] = counter.get().toDouble() / times[u]!!
|
values["U$u"] = counter.get().toDouble() / times.getValue(u)
|
||||||
} else {
|
} else {
|
||||||
values["U$u"] = counter.get()
|
values["U$u"] = counter.get()
|
||||||
}
|
}
|
||||||
@ -343,10 +395,18 @@ val histogramTask = task("histogram") {
|
|||||||
}
|
}
|
||||||
row(values)
|
row(values)
|
||||||
}
|
}
|
||||||
}.sumByStep(NumassAnalyzer.CHANNEL_KEY, meta.getDouble("binning", 20.0)) //apply binning
|
}.sumByStep(CHANNEL_KEY, meta.getDouble("binning", 16.0)) //apply binning
|
||||||
|
|
||||||
// send raw table to the output
|
// send raw table to the output
|
||||||
context.output.render(table, stage = "numass.histogram", name = name, meta = meta)
|
context.output.render(table, stage = "numass.histogram", name = name) {
|
||||||
|
update(meta)
|
||||||
|
data.toSortedMap().forEach { (name, set) ->
|
||||||
|
putNode("data", buildMeta {
|
||||||
|
"name" to name
|
||||||
|
set.meta.useMeta("iteration_info") { "iteration" to it }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (meta.getBoolean("plot", false)) {
|
if (meta.getBoolean("plot", false)) {
|
||||||
context.plotFrame("$name.plot", stage = "numass.histogram") {
|
context.plotFrame("$name.plot", stage = "numass.histogram") {
|
||||||
@ -363,6 +423,57 @@ val histogramTask = task("histogram") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return@join table
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val sliceTask = task("slice") {
|
||||||
|
model { meta ->
|
||||||
|
dependsOn(selectTask, meta)
|
||||||
|
configure(meta.getMetaOrEmpty("slice"))
|
||||||
|
configure {
|
||||||
|
meta.useMeta("analyzer") { putNode(it) }
|
||||||
|
setValue("@target", meta.getString("@target", meta.name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
join<NumassSet, Table> { data ->
|
||||||
|
val analyzer = SmartAnalyzer()
|
||||||
|
val slices = HashMap<String, IntRange>()
|
||||||
|
val formatBuilder = TableFormatBuilder()
|
||||||
|
formatBuilder.addColumn("set", ValueType.STRING)
|
||||||
|
formatBuilder.addColumn("time", ValueType.TIME)
|
||||||
|
meta.getMetaList("range").forEach {
|
||||||
|
val range = IntRange(it.getInt("from"), it.getInt("to"))
|
||||||
|
val name = it.getString("name", range.toString())
|
||||||
|
slices[name] = range
|
||||||
|
formatBuilder.addColumn(name, ValueType.NUMBER)
|
||||||
|
}
|
||||||
|
|
||||||
|
val table = buildTable(formatBuilder.build()) {
|
||||||
|
data.forEach { (setName, set) ->
|
||||||
|
val point = set.find {
|
||||||
|
it.index == meta.getInt("index", -1) ||
|
||||||
|
it.voltage == meta.getDouble("voltage", -1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (point != null) {
|
||||||
|
val amplitudeSpectrum = analyzer.getAmplitudeSpectrum(point, meta.getMetaOrEmpty("analyzer"))
|
||||||
|
val map = HashMap<String, Any>()
|
||||||
|
map["set"] = setName
|
||||||
|
map["time"] = point.startTime
|
||||||
|
slices.mapValuesTo(map) { (_, range) ->
|
||||||
|
amplitudeSpectrum.countInWindow(
|
||||||
|
range.start.toShort(),
|
||||||
|
range.endInclusive.toShort()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
row(map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// send raw table to the output
|
||||||
|
context.output.render(table, stage = "numass.table", name = name, meta = meta)
|
||||||
|
|
||||||
return@join table
|
return@join table
|
||||||
}
|
}
|
||||||
@ -371,21 +482,20 @@ val histogramTask = task("histogram") {
|
|||||||
val fitScanTask = task("fitscan") {
|
val fitScanTask = task("fitscan") {
|
||||||
model { meta ->
|
model { meta ->
|
||||||
dependsOn(filterTask, meta)
|
dependsOn(filterTask, meta)
|
||||||
configure{
|
configure {
|
||||||
setNode(meta.getMetaOrEmpty("scan"))
|
setNode(meta.getMetaOrEmpty("scan"))
|
||||||
setNode(meta.getMeta("fit"))
|
setNode(meta.getMeta("fit"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
splitAction<Table, FitResult> {
|
splitAction<Table, FitResult> {
|
||||||
val scanMeta = meta.getMeta("scan")
|
val scanValues = if (meta.hasValue("scan.masses")) {
|
||||||
val scanValues = if (scanMeta.hasValue("masses")) {
|
meta.getValue("scan.masses").list.map { it -> Math.pow(it.double * 1000, 2.0).asValue() }
|
||||||
scanMeta.getValue("masses").list.map { it -> Math.pow(it.double * 1000, 2.0).asValue() }
|
|
||||||
} else {
|
} else {
|
||||||
scanMeta.getValue("values", listOf(2.5e5, 1e6, 2.25e6, 4e6, 6.25e6, 9e6)).list
|
meta.getValue("scan.values", listOf(2.5e5, 1e6, 2.25e6, 4e6, 6.25e6, 9e6)).list
|
||||||
}
|
}
|
||||||
|
|
||||||
val scanParameter = scanMeta.getString("parameter", "msterile2")
|
val scanParameter = meta.getString("parameter", "msterile2")
|
||||||
scanValues.forEach { scanValue ->
|
scanValues.forEach { scanValue ->
|
||||||
val resultName = String.format("%s[%s=%s]", this.name, scanParameter, scanValue.string)
|
val resultName = String.format("%s[%s=%s]", this.name, scanParameter, scanValue.string)
|
||||||
val fitMeta = meta.getMeta("fit").builder.apply {
|
val fitMeta = meta.getMeta("fit").builder.apply {
|
||||||
@ -394,8 +504,8 @@ val fitScanTask = task("fitscan") {
|
|||||||
setValue("params.$scanParameter.value", scanValue)
|
setValue("params.$scanParameter.value", scanValue)
|
||||||
} else {
|
} else {
|
||||||
getMetaList("params.param").stream()
|
getMetaList("params.param").stream()
|
||||||
.filter { par -> par.getString("name") == scanParameter }
|
.filter { par -> par.getString("name") == scanParameter }
|
||||||
.forEach { it.setValue("value", it) }
|
.forEach { it.setValue("value", it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,16 +518,16 @@ val fitScanTask = task("fitscan") {
|
|||||||
writer.flush()
|
writer.flush()
|
||||||
|
|
||||||
FitHelper(context).fit(data, fitMeta)
|
FitHelper(context).fit(data, fitMeta)
|
||||||
.setListenerStream(out)
|
.setListenerStream(out)
|
||||||
.report(log)
|
.report(log)
|
||||||
.run()
|
.run()
|
||||||
.also {
|
.also {
|
||||||
if (fitMeta.getBoolean("printLog", true)) {
|
if (fitMeta.getBoolean("printLog", true)) {
|
||||||
writer.println()
|
writer.println()
|
||||||
log.entries.forEach { entry -> writer.println(entry.toString()) }
|
log.entries.forEach { entry -> writer.println(entry.toString()) }
|
||||||
writer.println()
|
writer.println()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package inr.numass.tasks
|
||||||
|
|
||||||
|
import hep.dataforge.io.render
|
||||||
|
import hep.dataforge.plots.data.DataPlot
|
||||||
|
import hep.dataforge.plots.output.plotFrame
|
||||||
|
import hep.dataforge.plots.plotData
|
||||||
|
import hep.dataforge.tables.Adapters
|
||||||
|
import hep.dataforge.tables.Table
|
||||||
|
import hep.dataforge.tables.filter
|
||||||
|
import hep.dataforge.useMeta
|
||||||
|
import hep.dataforge.values.ValueType
|
||||||
|
import hep.dataforge.workspace.tasks.task
|
||||||
|
import inr.numass.data.NumassDataUtils
|
||||||
|
import inr.numass.data.api.NumassSet
|
||||||
|
import inr.numass.subthreshold.Threshold
|
||||||
|
|
||||||
|
val subThresholdTask = task("threshold") {
|
||||||
|
descriptor {
|
||||||
|
value("plot", types = listOf(ValueType.BOOLEAN), defaultValue = false, info = "Show threshold correction plot")
|
||||||
|
value(
|
||||||
|
"binning",
|
||||||
|
types = listOf(ValueType.NUMBER),
|
||||||
|
defaultValue = 16,
|
||||||
|
info = "The binning used for fit"
|
||||||
|
)
|
||||||
|
info = "Calculate sub threshold correction"
|
||||||
|
}
|
||||||
|
model { meta ->
|
||||||
|
dependsOn(selectTask, meta)
|
||||||
|
configure(meta.getMetaOrEmpty("threshold"))
|
||||||
|
configure {
|
||||||
|
meta.useMeta("analyzer") { putNode(it) }
|
||||||
|
setValue("@target", meta.getString("@target", meta.name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
join<NumassSet, Table> { data ->
|
||||||
|
val sum = NumassDataUtils.joinByIndex(name, data.values)
|
||||||
|
|
||||||
|
val correctionTable = Threshold.calculateSubThreshold(sum, meta).filter {
|
||||||
|
it.getDouble("correction") in (1.0..1.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meta.getBoolean("plot", false)) {
|
||||||
|
context.plotFrame("$name.plot", stage = "numass.threshold") {
|
||||||
|
plots.setType<DataPlot>()
|
||||||
|
plotData("${name}_cor", correctionTable, Adapters.buildXYAdapter("U", "correction"))
|
||||||
|
plotData("${name}_a", correctionTable, Adapters.buildXYAdapter("U", "a"))
|
||||||
|
plotData("${name}_beta", correctionTable, Adapters.buildXYAdapter("U", "beta"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.output.render(correctionTable, "numass.correction", name, meta = meta)
|
||||||
|
return@join correctionTable
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,11 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//apply plugin: 'org.openjfx.javafxplugin'
|
||||||
|
//
|
||||||
|
//javafx {
|
||||||
|
// modules = [ 'javafx.controls' ]
|
||||||
|
//}
|
||||||
|
|
||||||
if (!hasProperty('mainClass')) {
|
if (!hasProperty('mainClass')) {
|
||||||
ext.mainClass = 'inr.numass.viewer.Viewer'//"inr.numass.viewer.test.TestApp"
|
ext.mainClass = 'inr.numass.viewer.Viewer'//"inr.numass.viewer.test.TestApp"
|
||||||
|
@ -58,7 +58,7 @@ class AmplitudeView : View(title = "Numass amplitude spectrum plot", icon = Imag
|
|||||||
|
|
||||||
|
|
||||||
private val container = PlotContainer(frame).apply {
|
private val container = PlotContainer(frame).apply {
|
||||||
val binningSelector: ChoiceBox<Int> = ChoiceBox(FXCollections.observableArrayList(1, 2, 5, 10, 20, 50)).apply {
|
val binningSelector: ChoiceBox<Int> = ChoiceBox(FXCollections.observableArrayList(1, 2, 8, 16, 32, 50)).apply {
|
||||||
minWidth = 0.0
|
minWidth = 0.0
|
||||||
selectionModel.selectLast()
|
selectionModel.selectLast()
|
||||||
binningProperty.bind(this.selectionModel.selectedItemProperty())
|
binningProperty.bind(this.selectionModel.selectedItemProperty())
|
||||||
|
@ -15,6 +15,7 @@ include ":numass-core"
|
|||||||
|
|
||||||
include 'numass-core:numass-data-api'
|
include 'numass-core:numass-data-api'
|
||||||
include 'numass-core:numass-data-proto'
|
include 'numass-core:numass-data-proto'
|
||||||
|
include 'numass-core:numass-signal-processing'
|
||||||
|
|
||||||
//include ":numass-server"
|
//include ":numass-server"
|
||||||
//
|
//
|
||||||
|
Loading…
Reference in New Issue
Block a user