Analyzers for Tristan

This commit is contained in:
Alexander Nozik 2018-03-19 16:57:07 +03:00
parent cf3268244e
commit ae97c0be68
43 changed files with 932 additions and 1041 deletions

View File

@ -12,7 +12,6 @@ version = "0.2.0";
dependencies { dependencies {
compile project(':numass-control') compile project(':numass-control')
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
} }
task testDevice(dependsOn: classes, type: JavaExec) { task testDevice(dependsOn: classes, type: JavaExec) {
@ -22,28 +21,7 @@ task testDevice(dependsOn: classes, type: JavaExec) {
description "Start application in debug mode with default virtual port" description "Start application in debug mode with default virtual port"
group "test" group "test"
} }
buildscript {
ext.kotlin_version = '1.1.60'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
repositories {
mavenCentral()
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
//task testRun(dependsOn: classes, type: JavaExec) { //task testRun(dependsOn: classes, type: JavaExec) {
// main mainClass // main mainClass

View File

@ -33,13 +33,9 @@ internal fun createChannel(meta: Meta): PKT8Channel {
when (transformationType) { when (transformationType) {
"default", "hyperbolic" -> { "default", "hyperbolic" -> {
val coefs = meta.getValue("coefs").listValue() val coefs = meta.getValue("coefs").listValue()
val r0 = meta.getDouble("r0", 1000.0)!! val r0 = meta.getDouble("r0", 1000.0)
return PKT8Channel(meta) { r -> return PKT8Channel(meta) { r ->
if (coefs == null) { coefs?.indices?.sumByDouble { coefs[it].doubleValue() * Math.pow(r0 / r, it.toDouble()) } ?: -1.0
-1.0
} else {
coefs.indices.sumByDouble { coefs[it].doubleValue() * Math.pow(r0 / r, it.toDouble()) }
}
} }
} }
else -> throw RuntimeException("Unknown transformation type") else -> throw RuntimeException("Unknown transformation type")
@ -50,13 +46,6 @@ internal fun createChannel(meta: Meta): PKT8Channel {
} }
} }
data class PKT8Result(val channel: String, val rawValue: Double, val temperature: Double) {
val rawString: String = String.format("%.2f", rawValue)
val temperatureString: String = String.format("%.2f", temperature)
}
/** /**
* Created by darksnake on 28-Sep-16. * Created by darksnake on 28-Sep-16.
*/ */

View File

@ -39,6 +39,7 @@ import hep.dataforge.utils.DateTimeUtils
import inr.numass.control.DeviceView import inr.numass.control.DeviceView
import inr.numass.control.StorageHelper import inr.numass.control.StorageHelper
import java.time.Duration import java.time.Duration
import java.time.Instant
import java.util.* import java.util.*
@ -52,7 +53,7 @@ import java.util.*
RoleDef(name = Roles.VIEW_ROLE) RoleDef(name = Roles.VIEW_ROLE)
) )
@ValueDef(name = "port", def = "virtual", info = "The name of the port for this PKT8") @ValueDef(name = "port", def = "virtual", info = "The name of the port for this PKT8")
@StateDef(ValueDef(name = "storing")) @StateDef(value = ValueDef(name = "storing", info = "Define if this device is currently writes to storage"), writable = true)
@DeviceView(PKT8Display::class) @DeviceView(PKT8Display::class)
class PKT8Device(context: Context, meta: Meta) : PortSensor(context, meta) { class PKT8Device(context: Context, meta: Meta) : PortSensor(context, meta) {
/** /**
@ -103,9 +104,9 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor(context, meta) {
//read channel configuration //read channel configuration
if (meta.hasMeta("channel")) { if (meta.hasMeta("channel")) {
for (node in getMeta().getMetaList("channel")) { for (node in meta.getMetaList("channel")) {
val designation = node.getString("designation", "default") val designation = node.getString("designation", "default")
this.channels.put(designation, createChannel(node)) this.channels[designation] = createChannel(node)
} }
} else { } else {
//set default channel configuration //set default channel configuration
@ -229,13 +230,18 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor(context, meta) {
} }
private fun notifyChannelResult(designation: String, rawValue: Double) { private fun notifyChannelResult(designation: String, rawValue: Double) {
updateLogicalState("raw.$designation", rawValue)
val channel = channels[designation] val channel = channels[designation]
if (channel != null) { val temperature = channel?.let {
collector.put(channel.name, channel.getTemperature(rawValue)) val temp = it.getTemperature(rawValue)
} else { updateLogicalState("temp.$designation", temp)
result(PKT8Result(designation, rawValue, -1.0)) collector.put(it.name, temp)
temp
}
forEachConnection(PKT8ValueListener::class.java) {
it.report(PKT8Reading(channel?.name ?: designation, rawValue, temperature))
} }
} }
@ -313,5 +319,15 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor(context, meta) {
const val ABUF = "abuf" const val ABUF = "abuf"
private val CHANNEL_DESIGNATIONS = arrayOf("a", "b", "c", "d", "e", "f", "g", "h") private val CHANNEL_DESIGNATIONS = arrayOf("a", "b", "c", "d", "e", "f", "g", "h")
} }
}
data class PKT8Reading(val channel: String, val rawValue: Double, val temperature: Double?) {
val rawString: String = String.format("%.2f", rawValue)
val temperatureString: String = String.format("%.2f", temperature)
}
interface PKT8ValueListener {
fun report(reading: PKT8Reading, time: Instant = Instant.now())
} }

View File

@ -1,8 +1,6 @@
package inr.numass.control.cryotemp package inr.numass.control.cryotemp
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.description.Descriptors import hep.dataforge.description.Descriptors
import hep.dataforge.fx.bindWindow import hep.dataforge.fx.bindWindow
import hep.dataforge.fx.dfIconView import hep.dataforge.fx.dfIconView
@ -15,7 +13,6 @@ import hep.dataforge.plots.PlotUtils
import hep.dataforge.plots.data.TimePlot import hep.dataforge.plots.data.TimePlot
import hep.dataforge.plots.jfreechart.JFreeChartFrame import hep.dataforge.plots.jfreechart.JFreeChartFrame
import inr.numass.control.DeviceDisplay import inr.numass.control.DeviceDisplay
import javafx.application.Platform
import javafx.beans.binding.ListBinding import javafx.beans.binding.ListBinding
import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleObjectProperty
import javafx.collections.FXCollections import javafx.collections.FXCollections
@ -33,11 +30,11 @@ import java.time.Instant
/** /**
* Created by darksnake on 30-May-17. * Created by darksnake on 30-May-17.
*/ */
class PKT8Display : DeviceDisplay<PKT8Device>(), MeasurementListener { class PKT8Display : DeviceDisplay<PKT8Device>(), PKT8ValueListener {
override fun buildView(device: PKT8Device) = CryoView() override fun buildView(device: PKT8Device) = CryoView()
internal val table = FXCollections.observableHashMap<String, PKT8Result>() internal val table = FXCollections.observableHashMap<String, PKT8Reading>()
val lastUpdateProperty = SimpleObjectProperty<String>("NEVER") val lastUpdateProperty = SimpleObjectProperty<String>("NEVER")
@ -47,16 +44,24 @@ class PKT8Display : DeviceDisplay<PKT8Device>(), MeasurementListener {
} }
} }
override fun onMeasurementFailed(measurement: Measurement<*>, exception: Throwable) { // override fun onMeasurementFailed(measurement: Measurement<*>, exception: Throwable) {
//
// }
//
// override fun onMeasurementResult(measurement: Measurement<*>, result: Any, time: Instant) {
// if (result is PKT8Result) {
// Platform.runLater {
// lastUpdateProperty.set(time.toString())
// table[result.channel] = result;
// }
// }
// }
//
} override fun report(reading: PKT8Reading, time: Instant) {
runLater {
override fun onMeasurementResult(measurement: Measurement<*>, result: Any, time: Instant) {
if (result is PKT8Result) {
Platform.runLater {
lastUpdateProperty.set(time.toString()) lastUpdateProperty.set(time.toString())
table.put(result.channel, result); table[reading.channel] = reading;
}
} }
} }
@ -104,24 +109,24 @@ class PKT8Display : DeviceDisplay<PKT8Device>(), MeasurementListener {
} }
} }
center { center {
tableview<PKT8Result> { tableview<PKT8Reading> {
items = object : ListBinding<PKT8Result>() { items = object : ListBinding<PKT8Reading>() {
init { init {
bind(table) bind(table)
} }
override fun computeValue(): ObservableList<PKT8Result> { override fun computeValue(): ObservableList<PKT8Reading> {
return FXCollections.observableArrayList(table.values).apply { return FXCollections.observableArrayList(table.values).apply {
sortBy { it.channel } sortBy { it.channel }
} }
} }
} }
column("Sensor", PKT8Result::channel); column("Sensor", PKT8Reading::channel);
column("Resistance", PKT8Result::rawValue).cellFormat { column("Resistance", PKT8Reading::rawValue).cellFormat {
text = String.format("%.2f", it) text = String.format("%.2f", it)
} }
column("Temperature", PKT8Result::temperature).cellFormat { column("Temperature", PKT8Reading::temperature).cellFormat {
text = String.format("%.2f", it) text = String.format("%.2f", it)
} }
} }

View File

@ -18,26 +18,29 @@ import java.util.function.Supplier
/** /**
* @author Alexander Nozik * @author Alexander Nozik
*/ */
class PKT8VirtualPort(portName: String, meta: Meta) : VirtualPort(meta), Metoid { class PKT8VirtualPort(private val portName: String, meta: Meta) : VirtualPort(meta), Metoid {
private val generator = Random() private val generator = Random()
init { // init {
super.configureValue("id", portName) // super.configureValue("id", portName)
} // }
override fun getName(): String = portName
@Synchronized override fun evaluateRequest(request: String) { @Synchronized override fun evaluateRequest(request: String) {
when (request) { when (request) {
"s" -> { "s" -> {
val letters = arrayOf("a", "b", "c", "d", "e", "f", "g", "h") val letters = arrayOf("a", "b", "c", "d", "e", "f", "g", "h")
for (letter in letters) { for (letter in letters) {
val channelMeta = MetaUtils.findNodeByValue(getMeta(), "channel", "letter", Value.of(letter)).orElse(Meta.empty()) val channelMeta = MetaUtils.findNodeByValue(meta, "channel", "letter", Value.of(letter)).orElse(Meta.empty())
val average: Double val average: Double
val sigma: Double val sigma: Double
if (channelMeta != null) { if (channelMeta != null) {
average = channelMeta.getDouble("av", 1200.0)!! average = channelMeta.getDouble("av", 1200.0)
sigma = channelMeta.getDouble("sigma", 50.0)!! sigma = channelMeta.getDouble("sigma", 50.0)
} else { } else {
average = 1200.0 average = 1200.0
sigma = 50.0 sigma = 50.0
@ -56,7 +59,7 @@ class PKT8VirtualPort(portName: String, meta: Meta) : VirtualPort(meta), Metoid
} }
"p" -> { "p" -> {
cancelByTag("measurement") cancelByTag("measurement")
this.receivePhrase("Stopped") planResponse("Stopped", Duration.ofMillis(50))
} }
} }
} }

View File

@ -61,7 +61,7 @@ import java.util.function.Consumer
StateDef(ValueDef(name = "filamentStatus", info = "Filament status")) StateDef(ValueDef(name = "filamentStatus", info = "Filament status"))
) )
@DeviceView(MspDisplay::class) @DeviceView(MspDisplay::class)
class MspDevice(context: Context, meta: Meta) : PortSensor<Values>(context, meta) { class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
private var measurementDelegate: Consumer<MspResponse>? = null private var measurementDelegate: Consumer<MspResponse>? = null

View File

@ -5,13 +5,13 @@ import hep.dataforge.control.connections.Roles
import hep.dataforge.control.devices.Device import hep.dataforge.control.devices.Device
import hep.dataforge.control.devices.DeviceFactory import hep.dataforge.control.devices.DeviceFactory
import hep.dataforge.exceptions.ControlException import hep.dataforge.exceptions.ControlException
import hep.dataforge.kodex.optional
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import javafx.scene.Scene import javafx.scene.Scene
import javafx.stage.Stage import javafx.stage.Stage
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import tornadofx.* import tornadofx.*
import java.util.* import java.util.*
import java.util.function.Predicate
/** /**
* Created by darksnake on 14-May-17. * Created by darksnake on 14-May-17.
@ -25,6 +25,7 @@ abstract class NumassControlApplication<in D : Device> : App() {
rootLogger.level = Level.INFO rootLogger.level = Level.INFO
device = setupDevice() device = setupDevice()
val controller = device.getDisplay() val controller = device.getDisplay()
device.connect(controller, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE) device.connect(controller, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE)
val scene = Scene(controller.view?.root ?: controller.getBoardView()) val scene = Scene(controller.view?.root ?: controller.getBoardView())
@ -47,12 +48,11 @@ abstract class NumassControlApplication<in D : Device> : App() {
protected abstract fun acceptDevice(meta: Meta): Boolean protected abstract fun acceptDevice(meta: Meta): Boolean
private fun setupDevice(): D { private fun setupDevice(): D {
val config = getConfig(this) val config = getConfig(this).optional.orElseGet { readResourceMeta("/config/devices.xml") }
.orElseGet { readResourceMeta("/config/devices.xml") }
val ctx = setupContext(config) val ctx = setupContext(config)
val deviceConfig = findDeviceMeta(config, Predicate<Meta> { this.acceptDevice(it) }) val deviceConfig = findDeviceMeta(config) { this.acceptDevice(it) }
.orElseThrow { RuntimeException("Device configuration not found") } ?: throw RuntimeException("Device configuration not found")
try { try {

View File

@ -8,6 +8,7 @@ import hep.dataforge.exceptions.StorageException
import hep.dataforge.fx.dfIcon import hep.dataforge.fx.dfIcon
import hep.dataforge.io.MetaFileReader import hep.dataforge.io.MetaFileReader
import hep.dataforge.io.XMLMetaReader import hep.dataforge.io.XMLMetaReader
import hep.dataforge.kodex.nullable
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.storage.commons.StorageConnection import hep.dataforge.storage.commons.StorageConnection
import hep.dataforge.storage.commons.StorageManager import hep.dataforge.storage.commons.StorageManager
@ -19,8 +20,6 @@ import java.io.IOException
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Paths import java.nio.file.Paths
import java.text.ParseException import java.text.ParseException
import java.util.*
import java.util.function.Predicate
/** /**
* Created by darksnake on 08-May-17. * Created by darksnake on 08-May-17.
@ -70,10 +69,10 @@ fun readResourceMeta(path: String): Meta {
} }
fun getConfig(app: Application): Optional<Meta> { fun getConfig(app: Application): Meta? {
val debugConfig = app.parameters.named["config.resource"] val debugConfig = app.parameters.named["config.resource"]
if (debugConfig != null) { if (debugConfig != null) {
return Optional.ofNullable(readResourceMeta(debugConfig)) return readResourceMeta(debugConfig)
} }
var configFileName: String? = app.parameters.named["config"] var configFileName: String? = app.parameters.named["config"]
@ -84,25 +83,17 @@ fun getConfig(app: Application): Optional<Meta> {
} }
val configFile = Paths.get(configFileName) val configFile = Paths.get(configFileName)
if (Files.exists(configFile)) { return if (Files.exists(configFile)) {
try { MetaFileReader.read(configFile)
val config = MetaFileReader.read(configFile)
return Optional.of(config)
} catch (e: IOException) {
throw RuntimeException(e)
} catch (e: ParseException) {
throw RuntimeException(e)
}
} else { } else {
logger.warn("Configuration file not found") logger.warn("Configuration file not found")
return Optional.empty<Meta>() null
} }
} }
fun findDeviceMeta(config: Meta, criterion: Predicate<Meta>): Optional<Meta> { fun findDeviceMeta(config: Meta, criterion: (Meta) -> Boolean): Meta? {
return config.getMetaList("device").stream().filter(criterion).findFirst().map { it -> it } return config.getMetaList("device").stream().filter(criterion).findFirst().nullable
} }
fun setupContext(meta: Meta): Context { fun setupContext(meta: Meta): Context {

View File

@ -1,112 +0,0 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.tables.BasicAdapter;
import hep.dataforge.tables.ValueMap;
import hep.dataforge.tables.ValuesAdapter;
import hep.dataforge.values.Value;
import hep.dataforge.values.Values;
import java.util.Optional;
import java.util.stream.Stream;
import static hep.dataforge.tables.Adapters.*;
/**
* @author Darksnake
*/
public class SpectrumAdapter extends BasicAdapter {
private static final String POINT_LENGTH_NAME = "time";
public SpectrumAdapter(Meta meta) {
super(meta);
}
public SpectrumAdapter(String xName, String yName, String yErrName, String measurementTime) {
super(new MetaBuilder(ValuesAdapter.ADAPTER_KEY)
.setValue(X_VALUE_KEY, xName)
.setValue(Y_VALUE_KEY, yName)
.setValue(Y_ERROR_KEY, yErrName)
.setValue(POINT_LENGTH_NAME, measurementTime)
.build()
);
}
public SpectrumAdapter(String xName, String yName, String measurementTime) {
super(new MetaBuilder(ValuesAdapter.ADAPTER_KEY)
.setValue(X_VALUE_KEY, xName)
.setValue(Y_VALUE_KEY, yName)
.setValue(POINT_LENGTH_NAME, measurementTime)
.build()
);
}
public double getTime(Values point) {
return this.optComponent(point, POINT_LENGTH_NAME).map(Value::doubleValue).orElse(1d);
}
public Values buildSpectrumDataPoint(double x, long count, double t) {
return ValueMap.of(new String[]{getComponentName(X_VALUE_KEY), getComponentName(Y_VALUE_KEY),
getComponentName(POINT_LENGTH_NAME)},
x, count, t);
}
public Values buildSpectrumDataPoint(double x, long count, double countErr, double t) {
return ValueMap.of(new String[]{getComponentName(X_VALUE_KEY), getComponentName(Y_VALUE_KEY),
getComponentName(Y_ERROR_KEY), getComponentName(POINT_LENGTH_NAME)},
x, count, countErr, t);
}
@Override
public Optional<Value> optComponent(Values values, String component) {
switch (component) {
case "count":
return super.optComponent(values, Y_VALUE_KEY);
case Y_VALUE_KEY:
return super.optComponent(values, Y_VALUE_KEY)
.map(it -> it.doubleValue() / getTime(values))
.map(Value::of);
case Y_ERROR_KEY:
Optional<Value> err = super.optComponent(values, Y_ERROR_KEY);
if (err.isPresent()) {
return Optional.of(Value.of(err.get().doubleValue() / getTime(values)));
} else {
double y = getComponent(values, Y_VALUE_KEY).doubleValue();
if (y < 0) {
return Optional.empty();
} else if (y == 0) {
//avoid infinite weights
return Optional.of(Value.of(1d / getTime(values)));
} else {
return Optional.of(Value.of(Math.sqrt(y) / getTime(values)));
}
}
default:
return super.optComponent(values, component);
}
}
@Override
public Stream<String> listComponents() {
return Stream.concat(super.listComponents(), Stream.of(X_VALUE_KEY, Y_VALUE_KEY, POINT_LENGTH_NAME)).distinct();
}
}

View File

@ -1,46 +0,0 @@
package inr.numass.data.api;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.stream.Stream;
/**
* A block constructed from a set of other blocks. Internal blocks are not necessary subsequent. Blocks are automatically sorted.
* Created by darksnake on 16.07.2017.
*/
public class MetaBlock implements NumassBlock {
private SortedSet<NumassBlock> blocks = new TreeSet<>(Comparator.comparing(NumassBlock::getStartTime));
public MetaBlock(NumassBlock... blocks) {
this.blocks.addAll(Arrays.asList(blocks));
}
public MetaBlock(Collection<NumassBlock> blocks) {
this.blocks.addAll(blocks);
}
@Override
public Instant getStartTime() {
return blocks.first().getStartTime();
}
@Override
public Duration getLength() {
return Duration.ofNanos(blocks.stream().mapToLong(block -> block.getLength().toNanos()).sum());
}
@Override
public Stream<NumassEvent> getEvents() {
return blocks.stream()
.sorted(Comparator.comparing(NumassBlock::getStartTime))
.flatMap(NumassBlock::getEvents);
}
@Override
public Stream<NumassFrame> getFrames() {
return blocks.stream()
.sorted(Comparator.comparing(NumassBlock::getStartTime))
.flatMap(NumassBlock::getFrames);
}
}

View File

@ -1,36 +0,0 @@
package inr.numass.data.api;
import java.time.Duration;
import java.time.Instant;
import java.util.stream.Stream;
/**
* A single continuous measurement block. The block can contain both isolated events and signal frames
* <p>
* Created by darksnake on 06-Jul-17.
*/
public interface NumassBlock {
/**
* The absolute start time of the block
* @return
*/
Instant getStartTime();
/**
* The length of the block
* @return
*/
Duration getLength();
/**
* Stream of isolated events. Could be empty
* @return
*/
Stream<NumassEvent> getEvents();
/**
* Stream of frames. Could be empty
* @return
*/
Stream<NumassFrame> getFrames();
}

View File

@ -1,66 +0,0 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data.api;
import java.io.Serializable;
import java.time.Instant;
/**
* A single numass event with given amplitude and time.
*
* @author Darksnake
*/
public class NumassEvent implements Serializable {
// channel
private final short chanel;
//The time of the block start
private final Instant blockTime;
//time in nanoseconds relative to block start
private final long timeOffset;
public NumassEvent(short chanel, Instant blockTime, long offset) {
this.chanel = chanel;
this.blockTime = blockTime;
this.timeOffset = offset;
}
public NumassEvent(short chanel, long offset) {
this(chanel, Instant.EPOCH, offset);
}
/**
* @return the chanel
*/
public short getChanel() {
return chanel;
}
/**
* time in nanoseconds relative to block start
* @return the time
*/
public long getTimeOffset() {
return timeOffset;
}
public Instant getBlockTime() {
return blockTime;
}
public Instant getTime() {
return blockTime.plusNanos(timeOffset);
}
}

View File

@ -1,50 +0,0 @@
package inr.numass.data.api;
import java.nio.ShortBuffer;
import java.time.Duration;
import java.time.Instant;
/**
* The continuous frame of digital detector data
* Created by darksnake on 06-Jul-17.
*/
public class NumassFrame {
/**
* The absolute start time of the frame
*/
private final Instant startTime;
/**
* The buffered signal shape in ticks
*/
private final ShortBuffer signal;
/**
* The time interval per tick
*/
private final Duration tickSize;
public NumassFrame(Instant startTime, Duration tickSize, ShortBuffer signal) {
this.startTime = startTime;
this.signal = signal;
this.tickSize = tickSize;
}
public Instant getTime() {
return startTime;
}
public ShortBuffer getSignal() {
return signal;
}
public Duration getTickSize() {
return tickSize;
}
public Duration getLength() {
return tickSize.multipliedBy(signal.capacity());
}
}

View File

@ -1,94 +0,0 @@
package inr.numass.data.api;
import hep.dataforge.meta.Metoid;
import hep.dataforge.values.Value;
import java.time.Duration;
import java.time.Instant;
import java.util.stream.Stream;
/**
* Created by darksnake on 06-Jul-17.
*/
public interface NumassPoint extends Metoid, NumassBlock {
String START_TIME_KEY = "start";
String LENGTH_KEY = "length";
String HV_KEY = "voltage";
String INDEX_KEY = "index";
Stream<NumassBlock> getBlocks();
/**
* Get the voltage setting for the point
*
* @return
*/
default double getVoltage() {
return getMeta().getDouble(HV_KEY, 0);
}
/**
* Get the index for this point in the set
* @return
*/
default int getIndex() {
return getMeta().getInt(INDEX_KEY, -1);
}
/**
* Get the first block if it exists. Throw runtime exception otherwise.
*
* @return
*/
default NumassBlock getFirstBlock() {
return getBlocks().findFirst().orElseThrow(() -> new RuntimeException("The point is empty"));
}
/**
* Get the starting time from meta or from first block
*
* @return
*/
@Override
default Instant getStartTime() {
return getMeta().optValue(START_TIME_KEY).map(Value::timeValue).orElseGet(() -> getFirstBlock().getStartTime());
}
/**
* Get the length key of meta or calculate length as a sum of block lengths. The latter could be a bit slow
*
* @return
*/
@Override
default Duration getLength() {
return Duration.ofNanos(
getMeta().optValue(LENGTH_KEY).map(Value::longValue)
.orElseGet(() -> getBlocks().mapToLong(it -> it.getLength().toNanos()).sum())
);
}
/**
* Get all events it all blocks as a single sequence
* <p>
* Some performance analysis of different stream concatenation approaches is given here: https://www.techempower.com/blog/2016/10/19/efficient-multiple-stream-concatenation-in-java/
* </p>
*
* @return
*/
@Override
default Stream<NumassEvent> getEvents() {
return getBlocks().flatMap(NumassBlock::getEvents);
}
/**
* Get all frames in all blocks as a single sequence
*
* @return
*/
@Override
default Stream<NumassFrame> getFrames() {
return getBlocks().flatMap(NumassBlock::getFrames);
}
}

View File

@ -1,101 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.data.api;
import hep.dataforge.meta.Metoid;
import hep.dataforge.names.Named;
import hep.dataforge.providers.Provider;
import hep.dataforge.providers.Provides;
import hep.dataforge.providers.ProvidesNames;
import hep.dataforge.tables.Table;
import hep.dataforge.values.Value;
import org.jetbrains.annotations.NotNull;
import java.time.Instant;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* A single set of numass points previously called file.
*
* @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a>
*/
public interface NumassSet extends Named, Metoid, Iterable<NumassPoint>, Provider {
String DESCRIPTION_KEY = "info";
String NUMASS_POINT_PROVIDER_KEY = "point";
Stream<NumassPoint> getPoints();
// default String getDescription() {
// return getMeta().getString(DESCRIPTION_KEY, "");
// }
@NotNull
@Override
default Iterator<NumassPoint> iterator() {
return getPoints().iterator();
}
/**
* Get the first point if it exists. Throw runtime exception otherwise.
*
* @return
*/
default NumassPoint getFirstPoint() {
return getPoints().findFirst().orElseThrow(() -> new RuntimeException("The set is empty"));
}
/**
* Get the starting time from meta or from first point
*
* @return
*/
default Instant getStartTime() {
return getMeta().optValue(NumassPoint.START_TIME_KEY).map(Value::timeValue).orElseGet(() -> getFirstPoint().getStartTime());
}
/**
* Find first point with given voltage
*
* @param voltage
* @return
*/
default Optional<NumassPoint> optPoint(double voltage) {
return getPoints().filter(it -> it.getVoltage() == voltage).findFirst();
}
/**
* List all points with given voltage
*
* @param voltage
* @return
*/
default List<NumassPoint> getPoints(double voltage) {
return getPoints().filter(it -> it.getVoltage() == voltage).collect(Collectors.toList());
}
@Provides(NUMASS_POINT_PROVIDER_KEY)
default Optional<NumassPoint> optPoint(String voltage) {
return optPoint(Double.parseDouble(voltage));
}
@Override
default String defaultTarget() {
return NUMASS_POINT_PROVIDER_KEY;
}
@ProvidesNames(NUMASS_POINT_PROVIDER_KEY)
default Stream<String> listPoints() {
return getPoints().map(it -> Double.toString(it.getVoltage()));
}
default Optional<Table> getHvData() {
return Optional.empty();
}
}

View File

@ -1,11 +0,0 @@
package inr.numass.data.api;
import java.util.stream.Stream;
/**
* An ancestor to numass frame analyzers
* Created by darksnake on 07.07.2017.
*/
public interface SignalProcessor {
Stream<NumassEvent> analyze(NumassFrame frame);
}

View File

@ -1,43 +0,0 @@
package inr.numass.data.api;
import java.io.Serializable;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.stream.Stream;
/**
* A simple in-memory implementation of block of events. No frames are allowed
* Created by darksnake on 08.07.2017.
*/
public class SimpleBlock implements NumassBlock, Serializable {
private final Instant startTime;
private final Duration length;
private final List<NumassEvent> events;
public SimpleBlock(Instant startTime, Duration length, List<NumassEvent> events) {
this.startTime = startTime;
this.length = length;
this.events = events;
}
@Override
public Instant getStartTime() {
return startTime;
}
@Override
public Duration getLength() {
return length;
}
@Override
public Stream<NumassEvent> getEvents() {
return events.stream();
}
@Override
public Stream<NumassFrame> getFrames() {
return Stream.empty();
}
}

View File

@ -1,41 +0,0 @@
package inr.numass.data.api;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.meta.MetaHolder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;
/**
* A simple static implementation of NumassPoint
* Created by darksnake on 08.07.2017.
*/
public class SimpleNumassPoint extends MetaHolder implements NumassPoint {
private final List<NumassBlock> blocks;
/**
* Input blocks must be sorted
* @param voltage
* @param blocks
*/
public SimpleNumassPoint(double voltage, Collection<? extends NumassBlock> blocks) {
super(new MetaBuilder("point").setValue(HV_KEY, voltage));
this.blocks = new ArrayList<>(blocks);
this.blocks.sort(Comparator.comparing(NumassBlock::getStartTime));
}
public SimpleNumassPoint(Meta meta, Collection<? extends NumassBlock> blocks) {
super(meta);
this.blocks = new ArrayList<>(blocks);
this.blocks.sort(Comparator.comparing(NumassBlock::getStartTime));
}
@Override
public Stream<NumassBlock> getBlocks() {
return blocks.stream();
}
}

View File

@ -1,265 +0,0 @@
package inr.numass.data.legacy;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import inr.numass.data.api.*;
import org.apache.commons.io.FilenameUtils;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Stream;
import static inr.numass.data.api.NumassPoint.HV_KEY;
import static java.nio.file.StandardOpenOption.READ;
/**
* Created by darksnake on 08.07.2017.
*/
public class NumassDatFile implements NumassSet {
private final String name;
private final Path path;
private final Meta meta;
public NumassDatFile(Path path, Meta meta) throws IOException {
this(FilenameUtils.getBaseName(path.getFileName().toString()),path,meta);
}
public NumassDatFile(String name, Path path, Meta meta) throws IOException {
this.name = name;
this.path = path;
String head = readHead(path);//2048
this.meta = new MetaBuilder(meta)
.setValue("info", head)
.setValue(NumassPoint.START_TIME_KEY, readDate(head))
.build();
}
@Override
public Meta getMeta() {
return meta;
}
@Override
public String getName() {
return name;
}
private double getHVdev() {
return getMeta().getDouble("dat.hvDev", 2.468555393226049);
}
private boolean hasUset() {
return getMeta().getBoolean("dat.uSet", true);
}
private static String readHead(Path path) throws IOException {
try (SeekableByteChannel channel = Files.newByteChannel(path, READ)) {
channel.position(0);
ByteBuffer buffer = ByteBuffer.allocate(2048);
channel.read(buffer);
return new String(buffer.array()).replaceAll("\u0000", "");
}
}
/**
* Read the block at current position
*
* @param channel
* @param length
* @return
* @throws IOException
*/
private ByteBuffer readBlock(SeekableByteChannel channel, int length) throws IOException {
ByteBuffer res = ByteBuffer.allocate(length);
channel.read(res);
res.order(ByteOrder.LITTLE_ENDIAN);
res.flip();
return res;
}
/**
* Read the point at current position
*
* @param channel
* @return
* @throws IOException
*/
private synchronized NumassPoint readPoint(SeekableByteChannel channel) throws
IOException {
ByteBuffer rx = readBlock(channel, 32);
int voltage = rx.getInt();
short length = rx.getShort();//(short) (rx[6] + 256 * rx[7]);
boolean phoneFlag = rx.get(19) != 0;//(rx[19] != 0);
double timeDiv;
switch (length) {
case 5:
case 10:
timeDiv = 2e7;
break;
case 15:
case 20:
timeDiv = 1e7;
break;
case 50:
timeDiv = 5e6;
break;
case 100:
timeDiv = 2.5e6;
break;
case 200:
timeDiv = 1.25e6;
break;
default:
throw new IOException("Unknown time divider in input data");
}
if (phoneFlag) {
timeDiv /= 20.0;
length *= 20;
}
List<NumassEvent> events = new ArrayList<>();
int lab = readBlock(channel, 1).get();
while (lab == 0xBF) {
ByteBuffer buffer = readBlock(channel, 5);
lab = buffer.get(4);
}
do {
events.add(readEvent(channel, lab, timeDiv));
lab = readBlock(channel, 1).get();
} while (lab != 0xAF);
//point end
ByteBuffer ending = readBlock(channel, 64);
int hours = ending.get(37);
int minutes = ending.get(38);
LocalDateTime start = LocalDateTime.from(getStartTime());
LocalDateTime absoluteTime = start.withHour(hours).withMinute(minutes);
//проверяем, не проскочили ли мы полночь
if (absoluteTime.isBefore(start)) {
absoluteTime = absoluteTime.plusDays(1);
}
int uRead = ending.getInt(39);
double uSet;
if (!this.hasUset()) {
uSet = uRead / 10d / getHVdev();
} else {
uSet = voltage / 10d;
}
NumassBlock block = new SimpleBlock(absoluteTime.toInstant(ZoneOffset.UTC), Duration.ofSeconds(length), events);
Meta pointMeta = new MetaBuilder("point")
.setValue(HV_KEY, uSet)
.setValue("uRead", uRead / 10 / getHVdev())
.setValue("source", "legacy");
return new SimpleNumassPoint(pointMeta, Collections.singletonList(block));
}
@Override
public Stream<NumassPoint> getPoints() {
try (SeekableByteChannel channel = Files.newByteChannel(path, READ)) {
//int lab = readBlock(channel,1).get();
int lab;
List<NumassPoint> points = new ArrayList<>();
do {
//TODO check point start
points.add(readPoint(channel));
lab = readBlock(channel, 1).get();
} while (lab != 0xff);
return points.stream();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
private LocalDateTime readDate(String head) throws IOException {
// Должны считать 14 символов
Scanner sc = new Scanner(head);
sc.nextLine();
String dateStr = sc.nextLine().trim();
//DD.MM.YY HH:MM
//12:35:16 19-11-2013
DateTimeFormatter format = DateTimeFormatter.ofPattern("HH:mm:ss dd-MM-yyyy");
return LocalDateTime.parse(dateStr, format);
}
private NumassEvent readEvent(SeekableByteChannel channel, int b, double timeDiv) throws IOException {
short chanel;
long time;
int hb = (b & 0x0f);
int lab = (b & 0xf0);
switch (lab) {
case 0x10:
chanel = readChanel(channel, hb);
time = readTime(channel);
break;
case 0x20:
chanel = 0;
time = readTime(channel);
break;
case 0x40:
time = 0;
chanel = readChanel(channel, hb);
break;
case 0x80:
time = 0;
chanel = 0;
break;
default:
throw new IOException("Event head expected");
}
return new NumassEvent(chanel, (long) (time / timeDiv));
}
private short readChanel(SeekableByteChannel channel, int hb) throws IOException {
assert hb < 127;
ByteBuffer buffer = readBlock(channel, 1);
return (short) (buffer.get() + 256 * hb);
}
private long readTime(SeekableByteChannel channel) throws IOException {
ByteBuffer rx = readBlock(channel, 4);
return rx.getLong();//rx[0] + 256 * rx[1] + 65536 * rx[2] + 256 * 65536 * rx[3];
}
// private void skip(int length) throws IOException {
// long n = stream.skip(length);
// if (n != length) {
// stream.skip(length - n);
// }
// }
}

View File

@ -1,45 +0,0 @@
package inr.numass.data.legacy;
import hep.dataforge.io.envelopes.EnvelopeTag;
import hep.dataforge.storage.filestorage.FileEnvelope;
import inr.numass.NumassEnvelopeType;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import static java.nio.file.StandardOpenOption.READ;
public class NumassFileEnvelope extends FileEnvelope {
public static byte[] LEGACY_START_SEQUENCE = {'#','!'};
public static byte[] LEGACY_END_SEQUENCE = {'!','#','\r','\n'};
public static FileEnvelope open(Path path, boolean readOnly) {
// if (!Files.exists(path)) {
// throw new RuntimeException("File envelope does not exist");
// }
try (FileChannel channel = FileChannel.open(path,READ)) {
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, 2);
if (buffer.compareTo(ByteBuffer.wrap(LEGACY_START_SEQUENCE)) == 0) {
return new NumassFileEnvelope(path, readOnly);
} else {
return FileEnvelope.Companion.open(path, readOnly);
}
} catch (IOException e) {
throw new RuntimeException("Failed to open file envelope", e);
}
}
private NumassFileEnvelope(Path path, boolean readOnly) {
super(path, readOnly);
}
@Override
protected EnvelopeTag buildTag() {
return new NumassEnvelopeType.LegacyTag();
}
}

View File

@ -0,0 +1,102 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder
import hep.dataforge.tables.Adapters.*
import hep.dataforge.tables.BasicAdapter
import hep.dataforge.tables.ValueMap
import hep.dataforge.tables.ValuesAdapter
import hep.dataforge.values.Value
import hep.dataforge.values.Values
import java.util.*
import java.util.stream.Stream
/**
* @author Darksnake
*/
class SpectrumAdapter : BasicAdapter {
constructor(meta: Meta) : super(meta) {}
constructor(xName: String, yName: String, yErrName: String, measurementTime: String) : super(MetaBuilder(ValuesAdapter.ADAPTER_KEY)
.setValue(X_VALUE_KEY, xName)
.setValue(Y_VALUE_KEY, yName)
.setValue(Y_ERROR_KEY, yErrName)
.setValue(POINT_LENGTH_NAME, measurementTime)
.build()
) {
}
constructor(xName: String, yName: String, measurementTime: String) : super(MetaBuilder(ValuesAdapter.ADAPTER_KEY)
.setValue(X_VALUE_KEY, xName)
.setValue(Y_VALUE_KEY, yName)
.setValue(POINT_LENGTH_NAME, measurementTime)
.build()
) {
}
fun getTime(point: Values): Double {
return this.optComponent(point, POINT_LENGTH_NAME).map<Double> { it.doubleValue() }.orElse(1.0)
}
fun buildSpectrumDataPoint(x: Double, count: Long, t: Double): Values {
return ValueMap.of(arrayOf(getComponentName(X_VALUE_KEY), getComponentName(Y_VALUE_KEY), getComponentName(POINT_LENGTH_NAME)),
x, count, t)
}
fun buildSpectrumDataPoint(x: Double, count: Long, countErr: Double, t: Double): Values {
return ValueMap.of(arrayOf(getComponentName(X_VALUE_KEY), getComponentName(Y_VALUE_KEY), getComponentName(Y_ERROR_KEY), getComponentName(POINT_LENGTH_NAME)),
x, count, countErr, t)
}
override fun optComponent(values: Values, component: String): Optional<Value> {
when (component) {
"count" -> return super.optComponent(values, Y_VALUE_KEY)
Y_VALUE_KEY -> return super.optComponent(values, Y_VALUE_KEY)
.map { it -> it.doubleValue() / getTime(values) }
.map { Value.of(it) }
Y_ERROR_KEY -> {
val err = super.optComponent(values, Y_ERROR_KEY)
return if (err.isPresent) {
Optional.of(Value.of(err.get().doubleValue() / getTime(values)))
} else {
val y = getComponent(values, Y_VALUE_KEY).doubleValue()
if (y < 0) {
Optional.empty()
} else if (y == 0.0) {
//avoid infinite weights
Optional.of(Value.of(1.0 / getTime(values)))
} else {
Optional.of(Value.of(Math.sqrt(y) / getTime(values)))
}
}
}
else -> return super.optComponent(values, component)
}
}
override fun listComponents(): Stream<String> {
return Stream.concat(super.listComponents(), Stream.of(X_VALUE_KEY, Y_VALUE_KEY, POINT_LENGTH_NAME)).distinct()
}
companion object {
private const val POINT_LENGTH_NAME = "time"
}
}

View File

@ -24,7 +24,7 @@ import hep.dataforge.tables.TableFormat
import hep.dataforge.tables.TableFormatBuilder import hep.dataforge.tables.TableFormatBuilder
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.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.lang.IllegalArgumentException
@ -48,7 +48,7 @@ abstract class AbstractAnalyzer @JvmOverloads constructor(private val processor:
val loChannel = meta.getInt("window.lo", 0) val loChannel = meta.getInt("window.lo", 0)
val upChannel = meta.getInt("window.up", Integer.MAX_VALUE) val upChannel = meta.getInt("window.up", Integer.MAX_VALUE)
var res = getAllEvents(block).filter { event -> var res = getAllEvents(block).filter { event ->
event.chanel.toInt() in loChannel..(upChannel - 1) event.amp.toInt() in loChannel..(upChannel - 1)
} }
if (meta.getBoolean("sort", false)) { if (meta.getBoolean("sort", false)) {
res = res.sorted(Comparator.comparing<NumassEvent, Long> { it.timeOffset }) res = res.sorted(Comparator.comparing<NumassEvent, Long> { it.timeOffset })

View File

@ -24,7 +24,7 @@ import hep.dataforge.values.Values
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 import inr.numass.data.api.NumassPoint
import inr.numass.data.api.NumassPoint.HV_KEY import inr.numass.data.api.NumassPoint.Companion.HV_KEY
import inr.numass.data.api.NumassSet import inr.numass.data.api.NumassSet
import java.util.* import java.util.*
import java.util.concurrent.atomic.AtomicLong import java.util.concurrent.atomic.AtomicLong
@ -56,7 +56,7 @@ interface NumassAnalyzer {
*/ */
fun analyzePoint(point: NumassPoint, config: Meta = Meta.empty()): Values { fun analyzePoint(point: NumassPoint, config: Meta = Meta.empty()): Values {
val map = HashMap(analyze(point, config).asMap()) val map = HashMap(analyze(point, config).asMap())
map.put(HV_KEY, Value.of(point.voltage)) map[HV_KEY] = Value.of(point.voltage)
return ValueMap(map) return ValueMap(map)
} }
@ -161,7 +161,7 @@ fun getAmplitudeSpectrum(events: Sequence<NumassEvent>, length: Double, config:
//optimized for fastest computation //optimized for fastest computation
val spectrum: MutableMap<Int, AtomicLong> = HashMap() val spectrum: MutableMap<Int, AtomicLong> = HashMap()
events.forEach { event -> events.forEach { event ->
val channel = event.chanel.toInt() val channel = event.amp.toInt()
spectrum.getOrPut(channel) { spectrum.getOrPut(channel) {
AtomicLong(0) AtomicLong(0)
}.incrementAndGet() }.incrementAndGet()

View File

@ -29,7 +29,7 @@ import hep.dataforge.values.Values
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 import inr.numass.data.api.NumassPoint
import inr.numass.data.api.NumassPoint.HV_KEY import inr.numass.data.api.NumassPoint.Companion.HV_KEY
import inr.numass.data.api.SignalProcessor import inr.numass.data.api.SignalProcessor
import java.util.* import java.util.*
import java.util.concurrent.atomic.AtomicLong import java.util.concurrent.atomic.AtomicLong

View File

@ -0,0 +1,38 @@
package inr.numass.data.api
import java.time.Duration
import java.time.Instant
import java.util.*
import java.util.stream.Stream
/**
* A block constructed from a set of other blocks. Internal blocks are not necessary subsequent. Blocks are automatically sorted.
* Created by darksnake on 16.07.2017.
*/
class MetaBlock : NumassBlock {
private val blocks = TreeSet(Comparator.comparing<NumassBlock, Instant>{ it.startTime })
override val startTime: Instant
get() = blocks.first().startTime
override val length: Duration
get() = Duration.ofNanos(blocks.stream().mapToLong { block -> block.length.toNanos() }.sum())
override val events: Stream<NumassEvent>
get() = blocks.stream()
.sorted(Comparator.comparing<NumassBlock, Instant>{ it.startTime })
.flatMap{ it.events }
override val frames: Stream<NumassFrame>
get() = blocks.stream()
.sorted(Comparator.comparing<NumassBlock, Instant>{ it.startTime })
.flatMap{ it.frames }
constructor(vararg blocks: NumassBlock) {
this.blocks.addAll(Arrays.asList(*blocks))
}
constructor(blocks: Collection<NumassBlock>) {
this.blocks.addAll(blocks)
}
}

View File

@ -0,0 +1,49 @@
package inr.numass.data.api
import java.time.Duration
import java.time.Instant
import java.util.stream.Stream
typealias NumassChannel = Int
/**
* A single continuous measurement block. The block can contain both isolated events and signal frames
*
*
* Created by darksnake on 06-Jul-17.
*/
interface NumassBlock {
/**
* A channel
*/
val channel: NumassChannel
get() = DEFAULT_CHANNEL
/**
* The absolute start time of the block
*/
val startTime: Instant
/**
* The length of the block
*/
val length: Duration
/**
* Stream of isolated events. Could be empty
*/
val events: Stream<NumassEvent>
/**
* Stream of frames. Could be empty
*/
val frames: Stream<NumassFrame>
companion object {
val DEFAULT_CHANNEL: NumassChannel = -1
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data.api
import java.io.Serializable
import java.time.Instant
/**
* A single numass event with given amplitude and time.
*
* @author Darksnake
* @property amp the amplitude of the event
* @property blockTime
* @property timeOffset time in nanoseconds relative to block start
*
*/
class NumassEvent(val amp: Short, val timeOffset: Long, val block: NumassBlock? = null) : Serializable {
val channel: NumassChannel?
get() = block?.channel
val time: Instant
get() = (block?.startTime ?: Instant.EPOCH).plusNanos(timeOffset)
}

View File

@ -0,0 +1,27 @@
package inr.numass.data.api
import java.nio.ShortBuffer
import java.time.Duration
import java.time.Instant
/**
* The continuous frame of digital detector data
* Created by darksnake on 06-Jul-17.
*/
class NumassFrame(
/**
* The absolute start time of the frame
*/
val time: Instant,
/**
* The time interval per tick
*/
val tickSize: Duration,
/**
* The buffered signal shape in ticks
*/
val signal: ShortBuffer) {
val length: Duration
get() = tickSize.multipliedBy(signal.capacity().toLong())
}

View File

@ -0,0 +1,85 @@
package inr.numass.data.api
import hep.dataforge.meta.Metoid
import java.time.Duration
import java.time.Instant
import java.util.stream.Stream
/**
* Created by darksnake on 06-Jul-17.
*/
interface NumassPoint : Metoid, NumassBlock {
val blocks: Stream<NumassBlock>
/**
* Get the voltage setting for the point
*
* @return
*/
val voltage: Double
get() = meta.getDouble(HV_KEY, 0.0)
/**
* Get the index for this point in the set
* @return
*/
val index: Int
get() = meta.getInt(INDEX_KEY, -1)
/**
* Get the first block if it exists. Throw runtime exception otherwise.
*
* @return
*/
val firstBlock: NumassBlock
get() = blocks.findFirst().orElseThrow { RuntimeException("The point is empty") }
/**
* Get the starting time from meta or from first block
*
* @return
*/
override val startTime: Instant
get() = meta.optValue(START_TIME_KEY).map<Instant>{ it.timeValue() }.orElseGet { firstBlock.startTime }
/**
* Get the length key of meta or calculate length as a sum of block lengths. The latter could be a bit slow
*
* @return
*/
override val length: Duration
get() = Duration.ofNanos(
meta.optValue(LENGTH_KEY).map<Long>{ it.longValue() }
.orElseGet { blocks.mapToLong { it -> it.length.toNanos() }.sum() }
)
/**
* Get all events it all blocks as a single sequence
*
*
* Some performance analysis of different stream concatenation approaches is given here: https://www.techempower.com/blog/2016/10/19/efficient-multiple-stream-concatenation-in-java/
*
*
* @return
*/
override val events: Stream<NumassEvent>
get() = blocks.flatMap{ it.events }
/**
* Get all frames in all blocks as a single sequence
*
* @return
*/
override val frames: Stream<NumassFrame>
get() = blocks.flatMap{ it.frames }
companion object {
const val START_TIME_KEY = "start"
const val LENGTH_KEY = "length"
const val HV_KEY = "voltage"
const val INDEX_KEY = "index"
}
}

View File

@ -0,0 +1,93 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.data.api
import hep.dataforge.kodex.toList
import hep.dataforge.meta.Metoid
import hep.dataforge.names.Named
import hep.dataforge.providers.Provider
import hep.dataforge.providers.Provides
import hep.dataforge.providers.ProvidesNames
import hep.dataforge.tables.Table
import java.time.Instant
import java.util.*
import java.util.stream.Stream
/**
* A single set of numass points previously called file.
*
* @author [Alexander Nozik](mailto:altavir@gmail.com)
*/
interface NumassSet : Named, Metoid, Iterable<NumassPoint>, Provider {
val points: Stream<NumassPoint>
/**
* Get the first point if it exists. Throw runtime exception otherwise.
*
* @return
*/
val firstPoint: NumassPoint
get() = points.findFirst().orElseThrow { RuntimeException("The set is empty") }
/**
* Get the starting time from meta or from first point
*
* @return
*/
val startTime: Instant
get() = meta.optValue(NumassPoint.START_TIME_KEY).map<Instant>{ it.timeValue() }.orElseGet { firstPoint.startTime }
val hvData: Optional<Table>
get() = Optional.empty()
// default String getDescription() {
// return getMeta().getString(DESCRIPTION_KEY, "");
// }
override fun iterator(): Iterator<NumassPoint> {
return points.iterator()
}
/**
* Find first point with given voltage
*
* @param voltage
* @return
*/
fun optPoint(voltage: Double): Optional<NumassPoint> {
return points.filter { it -> it.voltage == voltage }.findFirst()
}
/**
* List all points with given voltage
*
* @param voltage
* @return
*/
fun getPoints(voltage: Double): List<NumassPoint> {
return points.filter { it -> it.voltage == voltage }.toList()
}
@Provides(NUMASS_POINT_PROVIDER_KEY)
fun optPoint(voltage: String): Optional<NumassPoint> {
return optPoint(java.lang.Double.parseDouble(voltage))
}
override fun defaultTarget(): String {
return NUMASS_POINT_PROVIDER_KEY
}
@ProvidesNames(NUMASS_POINT_PROVIDER_KEY)
fun listPoints(): Stream<String> {
return points.map { it -> java.lang.Double.toString(it.voltage) }
}
companion object {
const val DESCRIPTION_KEY = "info"
const val NUMASS_POINT_PROVIDER_KEY = "point"
}
}

View File

@ -0,0 +1,11 @@
package inr.numass.data.api
import java.util.stream.Stream
/**
* An ancestor to numass frame analyzers
* Created by darksnake on 07.07.2017.
*/
interface SignalProcessor {
fun analyze(frame: NumassFrame): Stream<NumassEvent>
}

View File

@ -0,0 +1,19 @@
package inr.numass.data.api
import java.io.Serializable
import java.time.Duration
import java.time.Instant
import java.util.stream.Stream
/**
* A simple in-memory implementation of block of events. No frames are allowed
* Created by darksnake on 08.07.2017.
*/
class SimpleBlock(override val startTime: Instant, override val length: Duration, private val eventList: List<NumassEvent>) : NumassBlock, Serializable {
override val frames: Stream<NumassFrame> = Stream.empty()
override val events: Stream<NumassEvent>
get() = eventList.stream()
}

View File

@ -0,0 +1,31 @@
package inr.numass.data.api
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.MetaHolder
import java.util.stream.Stream
/**
* A simple static implementation of NumassPoint
* Created by darksnake on 08.07.2017.
*/
class SimpleNumassPoint : MetaHolder, NumassPoint {
private val blockList: List<NumassBlock>
/**
* Input blocks must be sorted
* @param voltage
* @param blocks
*/
constructor(voltage: Double, blocks: Collection<NumassBlock>) : super(MetaBuilder("point").setValue(NumassPoint.HV_KEY, voltage)) {
this.blockList = blocks.sortedBy { it.startTime }
}
constructor(meta: Meta, blocks: Collection<NumassBlock>) : super(meta) {
this.blockList = blocks.sortedBy { it.startTime }
}
override val blocks: Stream<NumassBlock>
get() = blockList.stream()
}

View File

@ -0,0 +1,244 @@
package inr.numass.data.legacy
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder
import inr.numass.data.api.*
import inr.numass.data.api.NumassPoint.Companion.HV_KEY
import org.apache.commons.io.FilenameUtils
import java.io.IOException
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.channels.SeekableByteChannel
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.StandardOpenOption.READ
import java.time.Duration
import java.time.LocalDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.util.*
import java.util.stream.Stream
/**
* Created by darksnake on 08.07.2017.
*/
class NumassDatFile @Throws(IOException::class)
constructor(private val name: String, private val path: Path, meta: Meta) : NumassSet {
private val meta: Meta
private val hVdev: Double
get() = getMeta().getDouble("dat.hvDev", 2.468555393226049)
override//int lab = readBlock(channel,1).get();
//TODO check point start
val points: Stream<NumassPoint>
get() = try {
Files.newByteChannel(path, READ).use { channel ->
var lab: Int
val points = ArrayList<NumassPoint>()
do {
points.add(readPoint(channel))
lab = readBlock(channel, 1).get().toInt()
} while (lab != 0xff)
return points.stream()
}
} catch (ex: IOException) {
throw RuntimeException(ex)
}
@Throws(IOException::class)
constructor(path: Path, meta: Meta) : this(FilenameUtils.getBaseName(path.fileName.toString()), path, meta) {
}
init {
val head = readHead(path)//2048
this.meta = MetaBuilder(meta)
.setValue("info", head)
.setValue(NumassPoint.START_TIME_KEY, readDate(head))
.build()
}
override fun getMeta(): Meta {
return meta
}
override fun getName(): String {
return name
}
private fun hasUset(): Boolean {
return getMeta().getBoolean("dat.uSet", true)
}
@Throws(IOException::class)
private fun readHead(path: Path): String {
Files.newByteChannel(path, READ).use { channel ->
channel.position(0)
val buffer = ByteBuffer.allocate(2048)
channel.read(buffer)
return String(buffer.array()).replace("\u0000".toRegex(), "")
}
}
/**
* Read the block at current position
*
* @param channel
* @param length
* @return
* @throws IOException
*/
@Throws(IOException::class)
private fun readBlock(channel: SeekableByteChannel, length: Int): ByteBuffer {
val res = ByteBuffer.allocate(length)
channel.read(res)
res.order(ByteOrder.LITTLE_ENDIAN)
res.flip()
return res
}
/**
* Read the point at current position
*
* @param channel
* @return
* @throws IOException
*/
@Synchronized
@Throws(IOException::class)
private fun readPoint(channel: SeekableByteChannel): NumassPoint {
val rx = readBlock(channel, 32)
val voltage = rx.int
var length = rx.short//(short) (rx[6] + 256 * rx[7]);
val phoneFlag = rx.get(19).toInt() != 0//(rx[19] != 0);
var timeDiv: Double = when (length.toInt()) {
5, 10 -> 2e7
15, 20 -> 1e7
50 -> 5e6
100 -> 2.5e6
200 -> 1.25e6
else -> throw IOException("Unknown time divider in input data")
}
if (phoneFlag) {
timeDiv /= 20.0
length = (length*20).toShort()
}
val events = ArrayList<NumassEvent>()
var lab = readBlock(channel, 1).get().toInt()
while (lab == 0xBF) {
val buffer = readBlock(channel, 5)
lab = buffer.get(4).toInt()
}
do {
events.add(readEvent(channel, lab, timeDiv))
lab = readBlock(channel, 1).get().toInt()
} while (lab != 0xAF)
//point end
val ending = readBlock(channel, 64)
val hours = ending.get(37).toInt()
val minutes = ending.get(38).toInt()
val start = LocalDateTime.from(startTime)
var absoluteTime = start.withHour(hours).withMinute(minutes)
//проверяем, не проскочили ли мы полночь
if (absoluteTime.isBefore(start)) {
absoluteTime = absoluteTime.plusDays(1)
}
val uRead = ending.getInt(39)
val uSet: Double
if (!this.hasUset()) {
uSet = uRead.toDouble() / 10.0 / hVdev
} else {
uSet = voltage / 10.0
}
val block = SimpleBlock(absoluteTime.toInstant(ZoneOffset.UTC), Duration.ofSeconds(length.toLong()), events)
val pointMeta = MetaBuilder("point")
.setValue(HV_KEY, uSet)
.setValue("uRead", uRead.toDouble() / 10.0 / hVdev)
.setValue("source", "legacy")
return SimpleNumassPoint(pointMeta, listOf<NumassBlock>(block))
}
@Throws(IOException::class)
private fun readDate(head: String): LocalDateTime {
// Должны считать 14 символов
val sc = Scanner(head)
sc.nextLine()
val dateStr = sc.nextLine().trim { it <= ' ' }
//DD.MM.YY HH:MM
//12:35:16 19-11-2013
val format = DateTimeFormatter.ofPattern("HH:mm:ss dd-MM-yyyy")
return LocalDateTime.parse(dateStr, format)
}
@Throws(IOException::class)
private fun readEvent(channel: SeekableByteChannel, b: Int, timeDiv: Double): NumassEvent {
val chanel: Short
val time: Long
val hb = b and 0x0f
val lab = b and 0xf0
when (lab) {
0x10 -> {
chanel = readChanel(channel, hb)
time = readTime(channel)
}
0x20 -> {
chanel = 0
time = readTime(channel)
}
0x40 -> {
time = 0
chanel = readChanel(channel, hb)
}
0x80 -> {
time = 0
chanel = 0
}
else -> throw IOException("Event head expected")
}
return NumassEvent(chanel, (time / timeDiv).toLong())
}
@Throws(IOException::class)
private fun readChanel(channel: SeekableByteChannel, hb: Int): Short {
assert(hb < 127)
val buffer = readBlock(channel, 1)
return (buffer.get() + 256 * hb).toShort()
}
@Throws(IOException::class)
private fun readTime(channel: SeekableByteChannel): Long {
val rx = readBlock(channel, 4)
return rx.long//rx[0] + 256 * rx[1] + 65536 * rx[2] + 256 * 65536 * rx[3];
}
// private void skip(int length) throws IOException {
// long n = stream.skip(length);
// if (n != length) {
// stream.skip(length - n);
// }
// }
}

View File

@ -0,0 +1,43 @@
package inr.numass.data.legacy
import hep.dataforge.io.envelopes.EnvelopeTag
import hep.dataforge.storage.filestorage.FileEnvelope
import inr.numass.NumassEnvelopeType
import java.io.IOException
import java.nio.ByteBuffer
import java.nio.channels.FileChannel
import java.nio.file.Path
import java.nio.file.StandardOpenOption.READ
class NumassFileEnvelope private constructor(path: Path, readOnly: Boolean) : FileEnvelope(path, readOnly) {
override fun buildTag(): EnvelopeTag {
return NumassEnvelopeType.LegacyTag()
}
companion object {
val LEGACY_START_SEQUENCE = byteArrayOf('#'.toByte(), '!'.toByte())
val LEGACY_END_SEQUENCE = byteArrayOf('!'.toByte(), '#'.toByte(), '\r'.toByte(), '\n'.toByte())
fun open(path: Path, readOnly: Boolean): FileEnvelope {
// if (!Files.exists(path)) {
// throw new RuntimeException("File envelope does not exist");
// }
try {
FileChannel.open(path, READ).use { channel ->
val buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, 2)
return if (buffer.compareTo(ByteBuffer.wrap(LEGACY_START_SEQUENCE)) == 0) {
NumassFileEnvelope(path, readOnly)
} else {
FileEnvelope.open(path, readOnly)
}
}
} catch (e: IOException) {
throw RuntimeException("Failed to open file envelope", e)
}
}
}
}

View File

@ -112,7 +112,7 @@ class NumassDataLoader(
} }
override fun getStartTime(): Instant { override fun getStartTime(): Instant {
return meta.optValue("start_time").map<Instant> { it.timeValue() }.orElseGet { super.getStartTime() } return meta.optValue("start_time").map<Instant> { it.timeValue() }.orElseGet { super.startTime }
} }
override val isOpen: Boolean override val isOpen: Boolean

View File

@ -1,5 +1,7 @@
package inr.numass.data.storage package inr.numass.data.storage
import hep.dataforge.context.Context
import hep.dataforge.context.Global
import hep.dataforge.io.envelopes.Envelope import hep.dataforge.io.envelopes.Envelope
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import inr.numass.data.NumassProto import inr.numass.data.NumassProto
@ -30,14 +32,14 @@ class ProtoNumassPoint(private val envelope: Envelope) : NumassPoint {
throw RuntimeException("Failed to read point via protobuf") throw RuntimeException("Failed to read point via protobuf")
} }
override fun getBlocks(): Stream<NumassBlock> { override val blocks: Stream<NumassBlock>
return point.channelsList.stream() get() = point.channelsList.stream()
.flatMap { channel -> .flatMap { channel ->
channel.blocksList.stream() channel.blocksList.stream()
.map { block -> ProtoBlock(channel.num.toInt(), block, meta) } .map { block -> ProtoBlock(channel.num.toInt(), block, meta) }
.sorted(Comparator.comparing<ProtoBlock, Instant> { it.startTime }) .sorted(Comparator.comparing<ProtoBlock, Instant> { it.startTime })
} }
}
override fun getMeta(): Meta { override fun getMeta(): Meta {
return envelope.meta return envelope.meta
@ -48,6 +50,10 @@ class ProtoNumassPoint(private val envelope: Envelope) : NumassPoint {
return ProtoNumassPoint(NumassFileEnvelope.open(path, true)) return ProtoNumassPoint(NumassFileEnvelope.open(path, true))
} }
fun readFile(path: String, context: Context = Global): ProtoNumassPoint {
return readFile(context.io.getFile(path).absolutePath)
}
fun ofEpochNanos(nanos: Long): Instant { fun ofEpochNanos(nanos: Long): Instant {
val seconds = Math.floorDiv(nanos, 1e9.toInt().toLong()) val seconds = Math.floorDiv(nanos, 1e9.toInt().toLong())
val reminder = (nanos % 1e9).toInt() val reminder = (nanos % 1e9).toInt()
@ -56,27 +62,26 @@ class ProtoNumassPoint(private val envelope: Envelope) : NumassPoint {
} }
} }
class ProtoBlock(val channel: Int, private val block: NumassProto.Point.Channel.Block, private val meta: Meta) : NumassBlock { class ProtoBlock(override val channel: Int, private val block: NumassProto.Point.Channel.Block, private val meta: Meta) : NumassBlock {
override fun getStartTime(): Instant { override val startTime: Instant
return ProtoNumassPoint.ofEpochNanos(block.time) get() = ProtoNumassPoint.ofEpochNanos(block.time)
}
override fun getLength(): Duration { override val length: Duration
return Duration.ofNanos((meta.getDouble("params.b_size") / meta.getDouble("params.sample_freq") * 1e9).toLong()) get() = Duration.ofNanos((meta.getDouble("params.b_size") / meta.getDouble("params.sample_freq") * 1e9).toLong())
}
override fun getEvents(): Stream<NumassEvent> {
val blockTime = startTime override val events: Stream<NumassEvent>
if (block.hasEvents()) { get() = if (block.hasEvents()) {
val events = block.events val events = block.events
return IntStream.range(0, events.timesCount).mapToObj { i -> NumassEvent(events.getAmplitudes(i).toShort(), blockTime, events.getTimes(i)) } IntStream.range(0, events.timesCount).mapToObj { i -> NumassEvent(events.getAmplitudes(i).toShort(), events.getTimes(i), this) }
} else { } else {
return Stream.empty() Stream.empty()
}
} }
override fun getFrames(): Stream<NumassFrame> {
override val frames: Stream<NumassFrame>
get() {
val tickSize = Duration.ofNanos((1e9 / meta.getInt("params.sample_freq")).toLong()) val tickSize = Duration.ofNanos((1e9 / meta.getInt("params.sample_freq")).toLong())
return block.framesList.stream().map { frame -> return block.framesList.stream().map { frame ->
val time = startTime.plusNanos(frame.time) val time = startTime.plusNanos(frame.time)

View File

@ -28,7 +28,7 @@ new GrindShell(ctx).eval {
def table = new SimpleHistogram([0d, 0d] as Double[], [2d, 100d] as Double[]) def table = new SimpleHistogram([0d, 0d] as Double[], [2d, 100d] as Double[])
.fill(new TimeAnalyzer().getEventsWithDelay(point, Meta.empty()).map { .fill(new TimeAnalyzer().getEventsWithDelay(point, Meta.empty()).map {
[it.value / 1000, it.key.chanel] as Double[] [it.value / 1000, it.key.amp] as Double[]
}).asTable() }).asTable()
ColumnedDataWriter.writeTable(System.out, table, "hist") ColumnedDataWriter.writeTable(System.out, table, "hist")

View File

@ -200,7 +200,7 @@ public class MonitorCorrectAction extends OneToOneAction<Table, Table> {
} }
private boolean isMonitorPoint(double monitor, Values point) { private boolean isMonitorPoint(double monitor, Values point) {
return point.getValue(NumassPoint.HV_KEY).doubleValue() == monitor; return point.getValue(NumassPoint.Companion.getHV_KEY()).doubleValue() == monitor;
} }
private Instant getTime(Values point) { private Instant getTime(Values point) {

View File

@ -67,8 +67,8 @@ public class NMEventGenerator {
// public void loadSpectrum(RawNMPoint point, int minChanel, int maxChanel) { // public void loadSpectrum(RawNMPoint point, int minChanel, int maxChanel) {
// List<Short> shorts = new ArrayList<>(); // List<Short> shorts = new ArrayList<>();
// point.getEvents().stream() // point.getEvents().stream()
// .filter((event) -> ((event.getChanel() > minChanel) && (event.getChanel() < maxChanel))) // .filter((event) -> ((event.getAmp() > minChanel) && (event.getAmp() < maxChanel)))
// .forEach((event) -> shorts.add(event.getChanel())); // .forEach((event) -> shorts.add(event.getAmp()));
// double[] doubles = new double[shorts.size()]; // double[] doubles = new double[shorts.size()];
// //
// for (int i = 0; i < shorts.size(); i++) { // for (int i = 0; i < shorts.size(); i++) {

View File

@ -120,7 +120,7 @@ public class PileUpSimulator {
//not counting double pileups //not counting double pileups
if (generated.size() > 1) { if (generated.size() > 1) {
double delay = (next.getTimeOffset() - lastRegisteredTime) / us; //time between events in microseconds double delay = (next.getTimeOffset() - lastRegisteredTime) / us; //time between events in microseconds
if (nextEventRegistered(next.getChanel(), delay)) { if (nextEventRegistered(next.getAmp(), delay)) {
//just register new event //just register new event
registered.add(next); registered.add(next);
lastRegisteredTime = next.getTimeOffset(); lastRegisteredTime = next.getTimeOffset();
@ -131,7 +131,7 @@ public class PileUpSimulator {
doublePileup.incrementAndGet(); doublePileup.incrementAndGet();
} else { } else {
//pileup event //pileup event
short newChannel = pileupChannel(delay, next.getChanel(), next.getChanel()); short newChannel = pileupChannel(delay, next.getAmp(), next.getAmp());
NumassEvent newEvent = new NumassEvent(newChannel, next.getBlockTime(), next.getTimeOffset()); NumassEvent newEvent = new NumassEvent(newChannel, next.getBlockTime(), next.getTimeOffset());
//replace already registered event by event with new channel //replace already registered event by event with new channel
registered.remove(registered.size() - 1); registered.remove(registered.size() - 1);

View File

@ -32,7 +32,7 @@ private fun correlation(sequence: Stream<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 {
amplitudes.add(it.chanel.toDouble()) amplitudes.add(it.amp.toDouble())
times.add(it.timeOffset.toDouble()) times.add(it.timeOffset.toDouble())
} }

View File

@ -0,0 +1,34 @@
package inr.numass.scripts.tristan
import hep.dataforge.meta.Meta
import hep.dataforge.tables.Table
import hep.dataforge.values.Values
import inr.numass.data.analyzers.NumassAnalyzer
import inr.numass.data.api.NumassBlock
import inr.numass.data.api.NumassEvent
import inr.numass.data.api.NumassSet
import inr.numass.data.storage.ProtoNumassPoint
import java.util.stream.Stream
fun main(args: Array<String>) {
val analyzer = object : NumassAnalyzer{
override fun analyze(block: NumassBlock, config: Meta): Values {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun getEvents(block: NumassBlock, meta: Meta): Stream<NumassEvent> {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun analyzeSet(set: NumassSet, config: Meta): Table {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
val file = ProtoNumassPoint.readFile("D:\\Work\\Numass\\data\\TRISTAN_11_2017\\df\\gun_16_19.df ")
val events = Sequence { file.events.iterator() }.sortedBy { it.time }
}