Numass control update

This commit is contained in:
Alexander Nozik 2018-03-28 16:59:40 +03:00
parent a24e7c6963
commit 700707a7a9
16 changed files with 280 additions and 256 deletions

View File

@ -113,19 +113,19 @@ public class NumassClient implements AutoCloseable, Responder {
ByteBuffer buffer; ByteBuffer buffer;
String zipName = null; String zipName = null;
if (file.isDirectory()) { if (file.isDirectory()) {
File tmpFile = File.createTempFile(file.getName(), NumassStorage.Companion.getNUMASS_ZIP_EXTENSION()); File tmpFile = File.createTempFile(file.getName(), NumassStorage.NUMASS_ZIP_EXTENSION);
tmpFile.deleteOnExit(); tmpFile.deleteOnExit();
ZipUtil.pack(file, tmpFile); ZipUtil.pack(file, tmpFile);
zipName = file.getName(); zipName = file.getName();
file = tmpFile; file = tmpFile;
} }
if (file.toString().endsWith(NumassStorage.Companion.getNUMASS_ZIP_EXTENSION())) { if (file.toString().endsWith(NumassStorage.NUMASS_ZIP_EXTENSION)) {
FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ); FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ);
buffer = ByteBuffer.allocate((int) channel.size()); buffer = ByteBuffer.allocate((int) channel.size());
channel.read(buffer); channel.read(buffer);
if (zipName == null) { if (zipName == null) {
zipName = file.getName().replace(NumassStorage.Companion.getNUMASS_ZIP_EXTENSION(), ""); zipName = file.getName().replace(NumassStorage.NUMASS_ZIP_EXTENSION, "");
} }
} else { } else {
return getErrorMeta(new FileNotFoundException(fileName)); return getErrorMeta(new FileNotFoundException(fileName));

View File

@ -22,12 +22,7 @@ class PKT8VirtualPort(private val portName: String, meta: Meta) : VirtualPort(me
private val generator = Random() private val generator = Random()
// init { override val name: String = 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) {

View File

@ -21,9 +21,9 @@ import hep.dataforge.connections.RoleDefs
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.control.collectors.RegularPointCollector import hep.dataforge.control.collectors.RegularPointCollector
import hep.dataforge.control.connections.Roles import hep.dataforge.control.connections.Roles
import hep.dataforge.control.devices.Device
import hep.dataforge.control.devices.PortSensor import hep.dataforge.control.devices.PortSensor
import hep.dataforge.control.measurements.AbstractMeasurement import hep.dataforge.control.devices.booleanState
import hep.dataforge.control.devices.doubleState
import hep.dataforge.control.ports.GenericPortController import hep.dataforge.control.ports.GenericPortController
import hep.dataforge.control.ports.Port import hep.dataforge.control.ports.Port
import hep.dataforge.control.ports.PortFactory import hep.dataforge.control.ports.PortFactory
@ -34,19 +34,15 @@ import hep.dataforge.exceptions.PortException
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.states.StateDef import hep.dataforge.states.StateDef
import hep.dataforge.states.StateDefs import hep.dataforge.states.StateDefs
import hep.dataforge.storage.api.TableLoader
import hep.dataforge.storage.commons.LoaderFactory
import hep.dataforge.storage.commons.StorageConnection import hep.dataforge.storage.commons.StorageConnection
import hep.dataforge.tables.TableFormatBuilder import hep.dataforge.tables.TableFormatBuilder
import hep.dataforge.utils.DateTimeUtils import hep.dataforge.tables.ValuesListener
import hep.dataforge.values.Value import hep.dataforge.values.Value
import hep.dataforge.values.Values import hep.dataforge.values.ValueType
import inr.numass.control.DeviceView import inr.numass.control.DeviceView
import inr.numass.control.StorageHelper import inr.numass.control.NumassStorageConnection
import java.time.Duration import java.time.Duration
import java.time.Instant
import java.util.* import java.util.*
import java.util.function.Consumer
/** /**
* @author Alexander Nozik * @author Alexander Nozik
@ -56,47 +52,34 @@ import java.util.function.Consumer
RoleDef(name = Roles.VIEW_ROLE) RoleDef(name = Roles.VIEW_ROLE)
) )
@StateDefs( @StateDefs(
StateDef(value = ValueDef(name = PortSensor.CONNECTED_STATE, info = "Connection with the device itself"), writable = true), StateDef(value = ValueDef(name = "controlled", info = "Connection with the device itself"), writable = true),
StateDef(value = ValueDef(name = "storing", info = "Define if this device is currently writes to storage"), writable = true), StateDef(value = ValueDef(name = "storing", info = "Define if this device is currently writes to storage"), writable = true),
StateDef(value = ValueDef(name = "filament", info = "The number of filament in use"), writable = true), StateDef(value = ValueDef(name = "filament", info = "The number of filament in use"), writable = true),
StateDef(value = ValueDef(name = "filamentOn", info = "Mass-spectrometer filament on"), writable = true), StateDef(value = ValueDef(name = "filamentOn", info = "Mass-spectrometer filament on"), writable = true),
StateDef(ValueDef(name = "filamentStatus", info = "Filament status")) StateDef(ValueDef(name = "filamentStatus", info = "Filament status")),
StateDef(ValueDef(name = "peakJump.zero", type = [ValueType.NUMBER], info = "Peak jump zero reading"))
) )
@DeviceView(MspDisplay::class) @DeviceView(MspDisplay::class)
class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) { class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
private var measurementDelegate: Consumer<MspResponse>? = null // private var measurementDelegate: Consumer<MspResponse>? = null
val isSelected: Boolean val selected: Boolean by booleanState()
get() = getState("selected").booleanValue()
val isControlled: Boolean var controlled: Boolean by booleanState()
get() = getState("controlled").booleanValue()
val isFilamentOn: Boolean var filamentOn: Boolean by booleanState()
get() = getState("filamentOn").booleanValue()
val peakJumpZero: Double by doubleState("peakJump.zero")
private val averagingDuration: Duration = Duration.parse(meta.getString("averagingDuration", "PT30S")) private val averagingDuration: Duration = Duration.parse(meta.getString("averagingDuration", "PT30S"))
private var storageHelper: NumassStorageConnection? = null
@Throws(ControlException::class) private val collector = RegularPointCollector(averagingDuration) { res ->
override fun init() { notifyResult(produceResult(res))
super.init() forEachConnection(ValuesListener::class.java) {
connection.weakOnError(this::notifyError) it.accept(res)
onResponse("FilamentStatus") {
val status = it[0, 2]
updateLogicalState("filamentOn", status == "ON")
updateLogicalState("filamentStatus", status)
}
logger.info("Connected to MKS mass-spectrometer on {}", connection.port);
}
/**
* Add reaction on specific response
*/
private fun onResponse(command: String, action: (MspResponse) -> Unit) {
connection.weakOnPhrase({ it.startsWith(command) }) {
action(MspResponse(it))
} }
} }
@ -104,7 +87,15 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
val portName = meta.getString("name") val portName = meta.getString("name")
logger.info("Connecting to port {}", portName) logger.info("Connecting to port {}", portName)
val port: Port = PortFactory.build(meta) val port: Port = PortFactory.build(meta)
return GenericPortController(context, port, "\r\r") return GenericPortController(context, port, "\r\r").also {
it.weakOnPhrase({ it.startsWith("FilamentStatus") }, this) {
val response = MspResponse(it)
val status = response[0, 2]
updateLogicalState("filamentOn", status == "ON")
updateLogicalState("filamentStatus", status)
}
logger.info("Connected to MKS mass-spectrometer on {}", it.port)
}
} }
@ -113,35 +104,17 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
super.stopMeasurement() super.stopMeasurement()
if (connected) { if (connected) {
setFilamentOn(false) setFilamentOn(false)
setConnected(false) connect(false)
} }
super.shutdown() super.shutdown()
} }
@Throws(MeasurementException::class) //TODO make actual request
override fun createMeasurement(): PeakJumpMeasurement {
val measurementMeta = meta.getMeta("peakJump")
val s = measurementMeta.getString("type", "peakJump")
if (s == "peakJump") {
val measurement = PeakJumpMeasurement(measurementMeta)
this.measurementDelegate = measurement
return measurement
} else {
throw MeasurementException("Unknown measurement type")
}
}
override fun setMeasurement(oldMeta: Meta?, newMeta: Meta) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@Throws(ControlException::class)
override fun computeState(stateName: String): Any = when (stateName) { override fun computeState(stateName: String): Any = when (stateName) {
"connected" -> false "controlled" -> false
"filament" -> 1 "filament" -> 1
"filamentOn" -> false//Always return false on first request "filamentOn" -> false//Always return false on first request
"filamentStatus" -> "UNKNOWN" "filamentStatus" -> "UNKNOWN"
"storing" -> false
else -> super.computeState(stateName) else -> super.computeState(stateName)
} }
@ -150,7 +123,7 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
@Throws(ControlException::class) @Throws(ControlException::class)
override fun requestStateChange(stateName: String, value: Value) { override fun requestStateChange(stateName: String, value: Value) {
when (stateName) { when (stateName) {
PortSensor.CONNECTED_STATE -> setConnected(value.booleanValue()) "controlled" -> control(value.booleanValue())
"filament" -> selectFilament(value.intValue()) "filament" -> selectFilament(value.intValue())
"filamentOn" -> setFilamentOn(value.booleanValue()) "filamentOn" -> setFilamentOn(value.booleanValue())
else -> super.requestStateChange(stateName, value) else -> super.requestStateChange(stateName, value)
@ -160,16 +133,15 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
/** /**
* Startup MSP: get available sensors, select sensor and control. * Startup MSP: get available sensors, select sensor and control.
* *
* @param connected * @param on
* @return * @return
* @throws hep.dataforge.exceptions.ControlException * @throws hep.dataforge.exceptions.ControlException
*/ */
@Throws(ControlException::class) private fun control(on: Boolean): Boolean {
private fun setConnected(connected: Boolean): Boolean {
val sensorName: String val sensorName: String
if (this.connected != connected) { if (on) {
if (connected) { //ensure device is connected
connection.open() connected = true
var response = commandAndWait("Sensors") var response = commandAndWait("Sensors")
if (response.isOK) { if (response.isOK) {
sensorName = response[2, 1] sensorName = response[2, 1]
@ -182,16 +154,14 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
response = commandAndWait("Select", sensorName) response = commandAndWait("Select", sensorName)
if (response.isOK) { if (response.isOK) {
updateLogicalState("selected", true) updateLogicalState("selected", true)
// selected = true;
} else { } else {
notifyError(response.errorDescription, null) notifyError(response.errorDescription, null)
return false return false
} }
response = commandAndWait("Control", "inr.numass.msp", "1.0") response = commandAndWait("Control", "inr.numass.msp", "1.1")
if (response.isOK) { if (response.isOK) {
// controlled = true;
// invalidateState("controlled");
updateLogicalState("controlled", true) updateLogicalState("controlled", true)
} else { } else {
notifyError(response.errorDescription, null) notifyError(response.errorDescription, null)
@ -201,13 +171,9 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
updateLogicalState(PortSensor.CONNECTED_STATE, true) updateLogicalState(PortSensor.CONNECTED_STATE, true)
return true return true
} else { } else {
connection.close()
return !commandAndWait("Release").isOK return !commandAndWait("Release").isOK
} }
} else {
return false
}
} }
/** /**
@ -279,15 +245,6 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
commandAndWait("FilamentControl", "Off").isOK commandAndWait("FilamentControl", "Off").isOK
} }
} }
//
// /**
// * Evaluate general async messages
// *
// * @param response
// */
// private fun evaluateResponse(response: MspResponse) {
//
// }
/** /**
* The MKS response as two-dimensional array of strings * The MKS response as two-dimensional array of strings
@ -337,95 +294,69 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
operator fun get(lineNo: Int, columnNo: Int): String = data[lineNo][columnNo] operator fun get(lineNo: Int, columnNo: Int): String = data[lineNo][columnNo]
} }
inner class PeakJumpMeasurement(private val meta: Meta) : AbstractMeasurement<Values>(), Consumer<MspResponse> { // @Throws(MeasurementException::class)
// override fun createMeasurement(): PeakJumpMeasurement {
private val collector = RegularPointCollector(averagingDuration, Consumer { this.result(it) }) // val measurementMeta = meta.getMeta("peakJump")
private val helper = StorageHelper(this@MspDevice) { connection: StorageConnection -> this.makeLoader(connection) } // val s = measurementMeta.getString("type", "peakJump")
private var peakMap: MutableMap<Int, String> = LinkedHashMap() // if (s == "peakJump") {
private var zero = 0.0 // val measurement = PeakJumpMeasurement(measurementMeta)
// this.measurementDelegate = measurement
private fun makeLoader(connection: StorageConnection): TableLoader { // return measurement
val storage = connection.storage // } else {
// throw MeasurementException("Unknown measurement type")
val builder = TableFormatBuilder().addTime("timestamp") // }
this.peakMap.values.forEach { builder.addNumber(it) } // }
val format = builder.build()
val suffix = DateTimeUtils.fileSuffix()
return LoaderFactory
.buildPointLoader(storage, "msp_" + suffix, "", "timestamp", format)
override fun stopMeasurement() {
super.stopMeasurement()
execute {
stopPeakJump()
}
} }
override fun getDevice(): Device = this@MspDevice override fun setMeasurement(oldMeta: Meta?, newMeta: Meta) {
if(oldMeta!= null){
stopMeasurement()
}
if (newMeta.getString("type", "peakJump") == "peakJump") {
execute {
startPeakJump(newMeta)
}
} else {
throw MeasurementException("Unknown measurement type")
}
}
override fun start() { private fun startPeakJump(meta: Meta) {
try { notifyMeasurementState(MeasurementState.IN_PROGRESS)
val measurementName = "peakJump" val measurementName = "peakJump"
val filterMode = meta.getString("filterMode", "PeakAverage") val filterMode = meta.getString("filterMode", "PeakAverage")
val accuracy = meta.getInt("accuracy", 5)!! val accuracy = meta.getInt("accuracy", 5)
//PENDING вставить остальные параметры? //PENDING вставить остальные параметры?
sendAndWait("MeasurementRemoveAll") sendAndWait("MeasurementRemoveAll")
// val peakMap: MutableMap<Int, String> = LinkedHashMap()
val builder = TableFormatBuilder().addTime("timestamp")
if (commandAndWait("AddPeakJump", measurementName, filterMode, accuracy, 0, 0, 0).isOK) { if (commandAndWait("AddPeakJump", measurementName, filterMode, accuracy, 0, 0, 0).isOK) {
peakMap.clear() // peakMap.clear()
for (peak in meta.getMetaList("peak")) { for (peak in meta.getMetaList("peak")) {
peakMap.put(peak.getInt("mass"), peak.getString("name", peak.getString("mass"))) // peakMap[peak.getInt("mass")] = peak.getString("name", peak.getString("mass"))
if (!commandAndWait("MeasurementAddMass", peak.getString("mass")).isOK) { if (!commandAndWait("MeasurementAddMass", peak.getString("mass")).isOK) {
throw ControlException("Can't add mass to measurement measurement for msp") throw ControlException("Can't add mass to measurement measurement for msp")
} }
builder.addNumber(peak.getString("name", peak.getString("mass")))
} }
} else { } else {
throw ControlException("Can't create measurement for msp") throw ControlException("Can't create measurement for msp")
} }
if (!isFilamentOn) { storageHelper = NumassStorageConnection("msp"){builder.build()}
this.error("Can't start measurement. Filament is not turned on.", null) connect(storageHelper)
}
if (!commandAndWait("ScanAdd", measurementName).isOK) {
this.error("Failed to add scan", null)
}
if (!commandAndWait("ScanStart", 2).isOK) { connection.onAnyPhrase(this) {
this.error("Failed to start scan", null) val response = MspResponse(it)
}
} catch (ex: ControlException) {
error(ex)
}
afterStart()
}
@Throws(MeasurementException::class)
override fun stop(force: Boolean): Boolean {
try {
collector.stop()
val stop = commandAndWait("ScanStop").isOK
afterStop()
helper.close()
return stop
} catch (ex: PortException) {
throw MeasurementException(ex)
}
}
@Synchronized
override fun result(result: Values, time: Instant) {
super.result(result, time)
helper.push(result)
}
private fun error(errorMessage: String?, error: Throwable?) {
if (error == null) {
error(MeasurementException(errorMessage))
} else {
error(error)
}
}
override fun accept(response: MspResponse) {
//Evaluating measurement information
when (response.commandName) { when (response.commandName) {
"MassReading" -> { "MassReading" -> {
val mass = java.lang.Double.parseDouble(response[0, 1]) val mass = java.lang.Double.parseDouble(response[0, 1])
@ -434,7 +365,9 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
collector.put(massName, value) collector.put(massName, value)
forEachConnection(Roles.VIEW_ROLE, NamedValueListener::class.java) { listener -> listener.pushValue(massName, value) } forEachConnection(Roles.VIEW_ROLE, NamedValueListener::class.java) { listener -> listener.pushValue(massName, value) }
} }
"ZeroReading" -> zero = java.lang.Double.parseDouble(response[0, 2]) / 100.0 "ZeroReading" -> {
updateLogicalState("peakJump.zero", java.lang.Double.parseDouble(response[0, 2]) / 100.0)
}
"StartingScan" -> { "StartingScan" -> {
val numScans = Integer.parseInt(response[0, 3]) val numScans = Integer.parseInt(response[0, 3])
@ -443,13 +376,32 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
command("ScanResume", 10) command("ScanResume", 10)
//FIXME обработать ошибку связи //FIXME обработать ошибку связи
} catch (ex: PortException) { } catch (ex: PortException) {
error(null, ex) notifyError("Failed to resume scan", ex)
} }
} }
} }
} }
} }
if (!filamentOn) {
notifyError("Can't start measurement. Filament is not turned on.")
}
if (!commandAndWait("ScanAdd", measurementName).isOK) {
notifyError("Failed to add scan")
}
if (!commandAndWait("ScanStart", 2).isOK) {
notifyError("Failed to start scan")
}
}
private fun stopPeakJump() {
collector.stop()
val stop = commandAndWait("ScanStop").isOK
//Reset loaders in connections
storageHelper?.let { disconnect(it)}
notifyMeasurementState(MeasurementState.STOPPED)
} }
companion object { companion object {

View File

@ -0,0 +1,54 @@
package inr.numass.control
import hep.dataforge.control.connections.DeviceConnection
import hep.dataforge.control.connections.Roles
import hep.dataforge.control.devices.Device
import hep.dataforge.kodex.nullable
import hep.dataforge.storage.api.Storage
import hep.dataforge.storage.api.TableLoader
import hep.dataforge.storage.commons.LoaderFactory
import hep.dataforge.storage.commons.StorageConnection
import hep.dataforge.tables.TableFormat
import hep.dataforge.tables.ValuesListener
import hep.dataforge.utils.DateTimeUtils
import hep.dataforge.values.Values
import java.util.*
class NumassStorageConnection(private val loaderName: String? = null, private val formatBuilder: (Device) -> TableFormat) : DeviceConnection(), ValuesListener {
private val loaderMap = HashMap<Storage, TableLoader>()
@Synchronized
override fun accept(point: Values) {
if (device.optBooleanState("storing").nullable == true) {
val format = formatBuilder(device)
val suffix = DateTimeUtils.fileSuffix()
val loaderName = "${loaderName ?: device.name}_$suffix"
device.forEachConnection(Roles.STORAGE_ROLE, StorageConnection::class.java) { connection ->
try {
//create a loader instance for each connected storage
val pl = loaderMap.computeIfAbsent(connection.storage){storage ->
LoaderFactory.buildPointLoader(storage, loaderName, "", "timestamp", format)
}
pl.push(point)
} catch (ex: Exception) {
device.logger.error("Push to loader failed", ex)
}
}
}
}
fun reset() = close()
@Synchronized
override fun close() {
loaderMap.values.forEach { it ->
try {
it.close()
} catch (ex: Exception) {
device.logger.error("Failed to close Loader", ex)
}
}
loaderMap.clear()
}
}

View File

@ -11,6 +11,7 @@ import java.util.*
* A helper to store points in multiple loaders * A helper to store points in multiple loaders
* Created by darksnake on 16-May-17. * Created by darksnake on 16-May-17.
*/ */
@Deprecated("To be replaced by connection")
class StorageHelper(private val device: AbstractDevice, private val loaderFactory: (StorageConnection) -> TableLoader) : AutoCloseable { class StorageHelper(private val device: AbstractDevice, private val loaderFactory: (StorageConnection) -> TableLoader) : AutoCloseable {
private val loaderMap = HashMap<StorageConnection, TableLoader>() private val loaderMap = HashMap<StorageConnection, TableLoader>()

View File

@ -21,7 +21,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)
VirtualDevice.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")
} }
} }

View File

@ -6,9 +6,11 @@
package inr.numass.control.readvac package inr.numass.control.readvac
import hep.dataforge.control.devices.Device import hep.dataforge.control.devices.Device
import hep.dataforge.control.devices.PortSensor.Companion.CONNECTED_STATE
import hep.dataforge.control.devices.Sensor import hep.dataforge.control.devices.Sensor
import hep.dataforge.control.measurements.Measurement import hep.dataforge.kodex.timeValue
import hep.dataforge.control.measurements.MeasurementListener import hep.dataforge.kodex.value
import hep.dataforge.meta.Meta
import inr.numass.control.DeviceDisplay import inr.numass.control.DeviceDisplay
import inr.numass.control.switch import inr.numass.control.switch
import javafx.application.Platform import javafx.application.Platform
@ -30,7 +32,7 @@ import java.time.format.DateTimeFormatter
/** /**
* @author [Alexander Nozik](mailto:altavir@gmail.com) * @author [Alexander Nozik](mailto:altavir@gmail.com)
*/ */
open class VacDisplay : DeviceDisplay<Sensor>(), MeasurementListener { open class VacDisplay : DeviceDisplay<Sensor>() {
val statusProperty = SimpleStringProperty("") val statusProperty = SimpleStringProperty("")
var status: String by statusProperty var status: String by statusProperty
@ -49,7 +51,7 @@ open class VacDisplay : DeviceDisplay<Sensor>(), MeasurementListener {
override fun evaluateDeviceException(device: Device, message: String, exception: Throwable) { override fun evaluateDeviceException(device: Device, message: String, exception: Throwable) {
if (!message.isEmpty()) { if (!message.isEmpty()) {
Platform.runLater { Platform.runLater {
status = "ERROR: " + message status = "ERROR: $message"
} }
} }
} }
@ -60,13 +62,13 @@ open class VacDisplay : DeviceDisplay<Sensor>(), MeasurementListener {
} }
} }
override fun onMeasurementProgress(measurement: Measurement<*>, message: String) { fun message(message: String) {
Platform.runLater { Platform.runLater {
status = message status = message
} }
} }
override fun onMeasurementResult(measurement: Measurement<*>, res: Any, time: Instant) { fun onResult(res: Any, time: Instant) {
val result = Number::class.java.cast(res).toDouble() val result = Number::class.java.cast(res).toDouble()
val resString = FORMAT.format(result) val resString = FORMAT.format(result)
Platform.runLater { Platform.runLater {
@ -76,6 +78,21 @@ open class VacDisplay : DeviceDisplay<Sensor>(), MeasurementListener {
} }
} }
override fun notifyDeviceStateChanged(device: Device, name: String, state: Meta) {
super.notifyDeviceStateChanged(device, name, state)
when (name) {
Sensor.MEASUREMENT_RESULT_STATE -> {
val res by state.value(Sensor.RESULT_VALUE)
val time by state.timeValue(Sensor.RESULT_TIMESTAMP)
onResult(res, time)
}
Sensor.MEASUREMENT_ERROR_STATE -> {
}
}
}
fun getTitle(): String { fun getTitle(): String {
return device.meta.getString("title", device.name); return device.meta.getString("title", device.name);
} }

View File

@ -108,7 +108,8 @@ class NumassDataLoader(
throw TODO("Not supported yet.") throw TODO("Not supported yet.")
} }
override val startTime: Instant = meta.optValue("start_time").map<Instant> { it.timeValue() }.orElseGet { super.startTime } override val startTime: Instant
get() = meta.optValue("start_time").map<Instant> { it.timeValue() }.orElseGet { super.startTime }
override val isOpen: Boolean override val isOpen: Boolean

View File

@ -50,15 +50,16 @@ class NumassStorage : FileStorage {
get() = meta.getString("description", "") get() = meta.getString("description", "")
private constructor(parent: FileStorage, config: Meta, shelf: String) : super(parent, config, shelf) { private constructor(parent: FileStorage, config: Meta, shelf: String) : super(parent, config, shelf) {
super.refresh() refresh()
} }
constructor(context: Context, config: Meta, path: Path) : super(context, config, path) { constructor(context: Context, config: Meta, path: Path) : super(context, config, path) {
super.refresh() refresh()
} }
override fun updateDirectoryLoaders() { override fun refresh() {
try { try {
this.shelves.clear()
this.loaders.clear() this.loaders.clear()
Files.list(dataDir).forEach { file -> Files.list(dataDir).forEach { file ->
try { try {
@ -194,8 +195,8 @@ class NumassStorage : FileStorage {
companion object { companion object {
val NUMASS_ZIP_EXTENSION = ".nm.zip" const val NUMASS_ZIP_EXTENSION = ".nm.zip"
val NUMASS_DATA_LOADER_TYPE = "numassData" const val NUMASS_DATA_LOADER_TYPE = "numassData"
} }
} }

View File

@ -15,18 +15,19 @@
*/ */
package inr.numass package inr.numass
import hep.dataforge.actions.ActionManager
import hep.dataforge.context.* import hep.dataforge.context.*
import hep.dataforge.fx.FXPlugin import hep.dataforge.fx.FXPlugin
import hep.dataforge.fx.plots.PlotContainer import hep.dataforge.fx.plots.PlotContainer
import hep.dataforge.maths.functions.FunctionLibrary import hep.dataforge.maths.functions.FunctionLibrary
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.plots.jfreechart.JFreeChartFrame import hep.dataforge.plots.jfreechart.JFreeChartFrame
import hep.dataforge.providers.Provides
import hep.dataforge.stat.models.ModelManager import hep.dataforge.stat.models.ModelManager
import hep.dataforge.stat.models.WeightedXYModel import hep.dataforge.stat.models.WeightedXYModel
import hep.dataforge.stat.models.XYModel import hep.dataforge.stat.models.XYModel
import hep.dataforge.tables.Adapters import hep.dataforge.tables.Adapters
import hep.dataforge.tables.ValuesAdapter import hep.dataforge.tables.ValuesAdapter
import hep.dataforge.workspace.tasks.Task
import inr.numass.data.analyzers.NumassAnalyzer import inr.numass.data.analyzers.NumassAnalyzer
import inr.numass.data.api.NumassPoint import inr.numass.data.api.NumassPoint
import inr.numass.models.* import inr.numass.models.*
@ -50,25 +51,35 @@ class NumassPlugin : BasicPlugin() {
override fun attach(context: Context) { override fun attach(context: Context) {
// StorageManager.buildFrom(context); // StorageManager.buildFrom(context);
super.attach(context) super.attach(context)
//TODO Replace by local providers
loadModels(context[ModelManager::class.java]) loadModels(context[ModelManager::class.java])
loadMath(FunctionLibrary.buildFrom(context)) loadMath(FunctionLibrary.buildFrom(context))
context.get(ActionManager::class.java).apply {
putTask(NumassFitScanTask::class.java)
putTask(NumassFitScanSummaryTask::class.java)
putTask(NumassFitSummaryTask::class.java)
put(selectTask)
put(analyzeTask)
put(mergeTask)
put(mergeEmptyTask)
put(monitorTableTask)
put(subtractEmptyTask)
put(transformTask)
put(filterTask)
put(fitTask)
put(plotFitTask)
} }
private val tasks = listOf(
NumassFitScanTask,
NumassFitScanSummaryTask,
NumassFitSummaryTask,
selectTask,
analyzeTask,
mergeTask,
mergeEmptyTask,
monitorTableTask,
subtractEmptyTask,
transformTask,
filterTask,
fitTask,
plotFitTask
)
@Provides(Task.TASK_TARGET)
fun getTask(name: String): Task<*>? {
return tasks.find { it.name == name }
}
@Provides(Task.TASK_TARGET)
fun taskList(): List<String> {
return tasks.map { it.name }
} }
private fun loadMath(math: FunctionLibrary) { private fun loadMath(math: FunctionLibrary) {

View File

@ -24,7 +24,7 @@ import inr.numass.NumassUtils
/** /**
* @author Alexander Nozik * @author Alexander Nozik
*/ */
class NumassFitScanSummaryTask : AbstractTask<Table>() { object NumassFitScanSummaryTask : AbstractTask<Table>() {
override fun run(model: TaskModel, data: DataNode<*>): DataNode<Table> { override fun run(model: TaskModel, data: DataNode<*>): DataNode<Table> {
val builder = DataSet.edit(Table::class) val builder = DataSet.edit(Table::class)
@ -44,7 +44,7 @@ class NumassFitScanSummaryTask : AbstractTask<Table>() {
override val name = "scansum" override val name = "scansum"
@TypedActionDef(name = "sterileSummary", inputType = FitResult::class, outputType = Table::class) @TypedActionDef(name = "sterileSummary", inputType = FitResult::class, outputType = Table::class)
private inner class FitSummaryAction : ManyToOneAction<FitResult, Table>() { private class FitSummaryAction : ManyToOneAction<FitResult, Table>() {
override fun execute(context: Context, nodeName: String, input: Map<String, FitResult>, meta: Laminate): Table { override fun execute(context: Context, nodeName: String, input: Map<String, FitResult>, meta: Laminate): Table {
val builder = ListTable.Builder("m", "U2", "U2err", "U2limit", "E0", "trap") val builder = ListTable.Builder("m", "U2", "U2err", "U2limit", "E0", "trap")
@ -53,11 +53,10 @@ class NumassFitScanSummaryTask : AbstractTask<Table>() {
val u2Val = pars.getDouble("U2") / pars.getError("U2") val u2Val = pars.getDouble("U2") / pars.getError("U2")
val limit: Double val limit: Double = if (Math.abs(u2Val) < 3) {
if (Math.abs(u2Val) < 3) { UpperLimitGenerator.getConfidenceLimit(u2Val) * pars.getError("U2")
limit = UpperLimitGenerator.getConfidenceLimit(u2Val) * pars.getError("U2")
} else { } else {
limit = java.lang.Double.NaN java.lang.Double.NaN
} }
builder.row( builder.row(

View File

@ -117,15 +117,6 @@ val mergeTask = task("merge") {
action<Table, Table>(MergeDataAction()) action<Table, Table>(MergeDataAction())
} }
//val newMergeTask = task("merge") {
// model { meta ->
// dependsOn(analyzeTask, meta)
// }
// join<Table, Table> {
// byValue(MERGE_NAME)
// }
//}
val mergeEmptyTask = task("empty") { val mergeEmptyTask = task("empty") {
model { meta -> model { meta ->
if (!meta.hasMeta("empty")) { if (!meta.hasMeta("empty")) {

View File

@ -14,10 +14,6 @@ import org.junit.Test;
* @author Alexander Nozik * @author Alexander Nozik
*/ */
public class NumassTest { public class NumassTest {
public NumassTest() {
}
/** /**
* Test of buildContext method, of class Numass. * Test of buildContext method, of class Numass.
*/ */

View File

@ -31,7 +31,6 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.time.Instant; import java.time.Instant;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -167,7 +166,7 @@ public class NumassRun implements Metoid, Responder {
try { try {
String filePath = message.getMeta().getString("path", ""); String filePath = message.getMeta().getString("path", "");
String fileName = message.getMeta().getString("name") String fileName = message.getMeta().getString("name")
.replace(NumassStorage.Companion.getNUMASS_ZIP_EXTENSION(), "");// removing .nm.zip if it is present .replace(NumassStorage.NUMASS_ZIP_EXTENSION, "");// removing .nm.zip if it is present
if (storage instanceof NumassStorage) { if (storage instanceof NumassStorage) {
((NumassStorage) storage).pushNumassData(filePath, fileName, message.getData().getBuffer()); ((NumassStorage) storage).pushNumassData(filePath, fileName, message.getData().getBuffer());
} else { } else {
@ -175,7 +174,7 @@ public class NumassRun implements Metoid, Responder {
} }
//TODO add checksum here //TODO add checksum here
return okResponseBase("numass.data.push.response", false, false).build(); return okResponseBase("numass.data.push.response", false, false).build();
} catch (StorageException | IOException ex) { } catch (StorageException ex) {
logger.error("Failed to push point", ex); logger.error("Failed to push point", ex);
return errorResponseBase("numass.data.push.response", ex).build(); return errorResponseBase("numass.data.push.response", ex).build();
} }

View File

@ -28,6 +28,7 @@ import hep.dataforge.storage.commons.LoaderFactory;
import hep.dataforge.storage.commons.StorageManager; import hep.dataforge.storage.commons.StorageManager;
import hep.dataforge.storage.commons.StorageUtils; import hep.dataforge.storage.commons.StorageUtils;
import inr.numass.data.storage.NumassStorage; import inr.numass.data.storage.NumassStorage;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ratpack.server.RatpackServer; import ratpack.server.RatpackServer;
@ -242,4 +243,10 @@ public class NumassServer extends AbstractNetworkListener implements ContextAwar
public NumassRun getRun() { public NumassRun getRun() {
return run; return run;
} }
@NotNull
@Override
public Logger getLogger() {
return LoggerFactory.getLogger(getClass());
}
} }

View File

@ -2,11 +2,8 @@ package inr.numass.viewer
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.fx.bindWindow import hep.dataforge.fx.*
import hep.dataforge.fx.dfIcon
import hep.dataforge.fx.fragments.LogFragment import hep.dataforge.fx.fragments.LogFragment
import hep.dataforge.fx.runGoal
import hep.dataforge.fx.ui
import hep.dataforge.meta.Metoid import hep.dataforge.meta.Metoid
import hep.dataforge.storage.api.Loader import hep.dataforge.storage.api.Loader
import hep.dataforge.storage.api.Storage import hep.dataforge.storage.api.Storage
@ -16,12 +13,12 @@ import inr.numass.NumassProperties
import inr.numass.data.api.NumassPoint import inr.numass.data.api.NumassPoint
import inr.numass.data.api.NumassSet import inr.numass.data.api.NumassSet
import inr.numass.data.storage.NumassDataLoader import inr.numass.data.storage.NumassDataLoader
import inr.numass.data.storage.NumassStorage
import inr.numass.data.storage.NumassStorageFactory import inr.numass.data.storage.NumassStorageFactory
import javafx.beans.property.SimpleBooleanProperty import javafx.beans.property.SimpleBooleanProperty
import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleObjectProperty
import javafx.beans.property.SimpleStringProperty import javafx.beans.property.SimpleStringProperty
import javafx.geometry.Insets import javafx.geometry.Insets
import javafx.scene.control.Alert
import javafx.scene.control.ContextMenu import javafx.scene.control.ContextMenu
import javafx.scene.control.TreeItem import javafx.scene.control.TreeItem
import javafx.scene.image.ImageView import javafx.scene.image.ImageView
@ -280,12 +277,15 @@ class StorageView(private val context: Context = Global) : View(title = "Numass
runGoal("loadDirectory[$path]") { runGoal("loadDirectory[$path]") {
title = "Load storage ($path)" title = "Load storage ($path)"
message = "Building numass storage tree..." message = "Building numass storage tree..."
(StorageManager.buildStorage(context, NumassStorageFactory.buildStorageMeta(path, true, false)) as NumassStorage) StorageManager.buildStorage(context, NumassStorageFactory.buildStorageMeta(path, true, false))
} ui { } ui {
storage = it storage = it
storageName = "Storage: $path" storageName = "Storage: $path"
statusBar.text = "OK" statusBar.text = "OK"
} except {
alert(type = Alert.AlertType.ERROR, header = "Error during storage loading", content = it.toString()).show()
it.printStackTrace()
} }
} }