Numass control update
This commit is contained in:
parent
a24e7c6963
commit
700707a7a9
@ -113,19 +113,19 @@ public class NumassClient implements AutoCloseable, Responder {
|
||||
ByteBuffer buffer;
|
||||
String zipName = null;
|
||||
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();
|
||||
ZipUtil.pack(file, tmpFile);
|
||||
zipName = file.getName();
|
||||
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);
|
||||
buffer = ByteBuffer.allocate((int) channel.size());
|
||||
channel.read(buffer);
|
||||
if (zipName == null) {
|
||||
zipName = file.getName().replace(NumassStorage.Companion.getNUMASS_ZIP_EXTENSION(), "");
|
||||
zipName = file.getName().replace(NumassStorage.NUMASS_ZIP_EXTENSION, "");
|
||||
}
|
||||
} else {
|
||||
return getErrorMeta(new FileNotFoundException(fileName));
|
||||
|
@ -22,12 +22,7 @@ class PKT8VirtualPort(private val portName: String, meta: Meta) : VirtualPort(me
|
||||
|
||||
private val generator = Random()
|
||||
|
||||
// init {
|
||||
// super.configureValue("id", portName)
|
||||
// }
|
||||
|
||||
override fun getName(): String = portName
|
||||
|
||||
override val name: String = portName
|
||||
|
||||
@Synchronized override fun evaluateRequest(request: String) {
|
||||
when (request) {
|
||||
|
@ -21,9 +21,9 @@ import hep.dataforge.connections.RoleDefs
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.control.collectors.RegularPointCollector
|
||||
import hep.dataforge.control.connections.Roles
|
||||
import hep.dataforge.control.devices.Device
|
||||
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.Port
|
||||
import hep.dataforge.control.ports.PortFactory
|
||||
@ -34,19 +34,15 @@ import hep.dataforge.exceptions.PortException
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.states.StateDef
|
||||
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.tables.TableFormatBuilder
|
||||
import hep.dataforge.utils.DateTimeUtils
|
||||
import hep.dataforge.tables.ValuesListener
|
||||
import hep.dataforge.values.Value
|
||||
import hep.dataforge.values.Values
|
||||
import hep.dataforge.values.ValueType
|
||||
import inr.numass.control.DeviceView
|
||||
import inr.numass.control.StorageHelper
|
||||
import inr.numass.control.NumassStorageConnection
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
import java.util.function.Consumer
|
||||
|
||||
/**
|
||||
* @author Alexander Nozik
|
||||
@ -56,47 +52,34 @@ import java.util.function.Consumer
|
||||
RoleDef(name = Roles.VIEW_ROLE)
|
||||
)
|
||||
@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 = "filament", info = "The number of filament in use"), 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)
|
||||
class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
|
||||
|
||||
private var measurementDelegate: Consumer<MspResponse>? = null
|
||||
// private var measurementDelegate: Consumer<MspResponse>? = null
|
||||
|
||||
val isSelected: Boolean
|
||||
get() = getState("selected").booleanValue()
|
||||
val selected: Boolean by booleanState()
|
||||
|
||||
val isControlled: Boolean
|
||||
get() = getState("controlled").booleanValue()
|
||||
var controlled: Boolean by booleanState()
|
||||
|
||||
val isFilamentOn: Boolean
|
||||
get() = getState("filamentOn").booleanValue()
|
||||
var filamentOn: Boolean by booleanState()
|
||||
|
||||
val peakJumpZero: Double by doubleState("peakJump.zero")
|
||||
|
||||
private val averagingDuration: Duration = Duration.parse(meta.getString("averagingDuration", "PT30S"))
|
||||
|
||||
private var storageHelper: NumassStorageConnection? = null
|
||||
|
||||
@Throws(ControlException::class)
|
||||
override fun init() {
|
||||
super.init()
|
||||
connection.weakOnError(this::notifyError)
|
||||
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))
|
||||
private val collector = RegularPointCollector(averagingDuration) { res ->
|
||||
notifyResult(produceResult(res))
|
||||
forEachConnection(ValuesListener::class.java) {
|
||||
it.accept(res)
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +87,15 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
|
||||
val portName = meta.getString("name")
|
||||
logger.info("Connecting to port {}", portName)
|
||||
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()
|
||||
if (connected) {
|
||||
setFilamentOn(false)
|
||||
setConnected(false)
|
||||
connect(false)
|
||||
}
|
||||
super.shutdown()
|
||||
}
|
||||
|
||||
@Throws(MeasurementException::class)
|
||||
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)
|
||||
//TODO make actual request
|
||||
override fun computeState(stateName: String): Any = when (stateName) {
|
||||
"connected" -> false
|
||||
"controlled" -> false
|
||||
"filament" -> 1
|
||||
"filamentOn" -> false//Always return false on first request
|
||||
"filamentStatus" -> "UNKNOWN"
|
||||
"storing" -> false
|
||||
else -> super.computeState(stateName)
|
||||
}
|
||||
|
||||
@ -150,7 +123,7 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
|
||||
@Throws(ControlException::class)
|
||||
override fun requestStateChange(stateName: String, value: Value) {
|
||||
when (stateName) {
|
||||
PortSensor.CONNECTED_STATE -> setConnected(value.booleanValue())
|
||||
"controlled" -> control(value.booleanValue())
|
||||
"filament" -> selectFilament(value.intValue())
|
||||
"filamentOn" -> setFilamentOn(value.booleanValue())
|
||||
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.
|
||||
*
|
||||
* @param connected
|
||||
* @param on
|
||||
* @return
|
||||
* @throws hep.dataforge.exceptions.ControlException
|
||||
*/
|
||||
@Throws(ControlException::class)
|
||||
private fun setConnected(connected: Boolean): Boolean {
|
||||
private fun control(on: Boolean): Boolean {
|
||||
val sensorName: String
|
||||
if (this.connected != connected) {
|
||||
if (connected) {
|
||||
connection.open()
|
||||
if (on) {
|
||||
//ensure device is connected
|
||||
connected = true
|
||||
var response = commandAndWait("Sensors")
|
||||
if (response.isOK) {
|
||||
sensorName = response[2, 1]
|
||||
@ -182,16 +154,14 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
|
||||
response = commandAndWait("Select", sensorName)
|
||||
if (response.isOK) {
|
||||
updateLogicalState("selected", true)
|
||||
// selected = true;
|
||||
} else {
|
||||
notifyError(response.errorDescription, null)
|
||||
return false
|
||||
}
|
||||
|
||||
response = commandAndWait("Control", "inr.numass.msp", "1.0")
|
||||
response = commandAndWait("Control", "inr.numass.msp", "1.1")
|
||||
if (response.isOK) {
|
||||
// controlled = true;
|
||||
// invalidateState("controlled");
|
||||
|
||||
updateLogicalState("controlled", true)
|
||||
} else {
|
||||
notifyError(response.errorDescription, null)
|
||||
@ -201,13 +171,9 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
|
||||
updateLogicalState(PortSensor.CONNECTED_STATE, true)
|
||||
return true
|
||||
} else {
|
||||
connection.close()
|
||||
return !commandAndWait("Release").isOK
|
||||
}
|
||||
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -279,15 +245,6 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
|
||||
commandAndWait("FilamentControl", "Off").isOK
|
||||
}
|
||||
}
|
||||
//
|
||||
// /**
|
||||
// * Evaluate general async messages
|
||||
// *
|
||||
// * @param response
|
||||
// */
|
||||
// private fun evaluateResponse(response: MspResponse) {
|
||||
//
|
||||
// }
|
||||
|
||||
/**
|
||||
* 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]
|
||||
}
|
||||
|
||||
inner class PeakJumpMeasurement(private val meta: Meta) : AbstractMeasurement<Values>(), Consumer<MspResponse> {
|
||||
|
||||
private val collector = RegularPointCollector(averagingDuration, Consumer { this.result(it) })
|
||||
private val helper = StorageHelper(this@MspDevice) { connection: StorageConnection -> this.makeLoader(connection) }
|
||||
private var peakMap: MutableMap<Int, String> = LinkedHashMap()
|
||||
private var zero = 0.0
|
||||
|
||||
private fun makeLoader(connection: StorageConnection): TableLoader {
|
||||
val storage = connection.storage
|
||||
|
||||
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)
|
||||
// @Throws(MeasurementException::class)
|
||||
// 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 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() {
|
||||
try {
|
||||
private fun startPeakJump(meta: Meta) {
|
||||
notifyMeasurementState(MeasurementState.IN_PROGRESS)
|
||||
val measurementName = "peakJump"
|
||||
val filterMode = meta.getString("filterMode", "PeakAverage")
|
||||
val accuracy = meta.getInt("accuracy", 5)!!
|
||||
val accuracy = meta.getInt("accuracy", 5)
|
||||
//PENDING вставить остальные параметры?
|
||||
sendAndWait("MeasurementRemoveAll")
|
||||
|
||||
// val peakMap: MutableMap<Int, String> = LinkedHashMap()
|
||||
|
||||
val builder = TableFormatBuilder().addTime("timestamp")
|
||||
|
||||
if (commandAndWait("AddPeakJump", measurementName, filterMode, accuracy, 0, 0, 0).isOK) {
|
||||
peakMap.clear()
|
||||
// peakMap.clear()
|
||||
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) {
|
||||
throw ControlException("Can't add mass to measurement measurement for msp")
|
||||
}
|
||||
builder.addNumber(peak.getString("name", peak.getString("mass")))
|
||||
}
|
||||
} else {
|
||||
throw ControlException("Can't create measurement for msp")
|
||||
}
|
||||
|
||||
if (!isFilamentOn) {
|
||||
this.error("Can't start measurement. Filament is not turned on.", null)
|
||||
}
|
||||
if (!commandAndWait("ScanAdd", measurementName).isOK) {
|
||||
this.error("Failed to add scan", null)
|
||||
}
|
||||
storageHelper = NumassStorageConnection("msp"){builder.build()}
|
||||
connect(storageHelper)
|
||||
|
||||
if (!commandAndWait("ScanStart", 2).isOK) {
|
||||
this.error("Failed to start scan", null)
|
||||
}
|
||||
} 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
|
||||
connection.onAnyPhrase(this) {
|
||||
val response = MspResponse(it)
|
||||
when (response.commandName) {
|
||||
"MassReading" -> {
|
||||
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)
|
||||
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" -> {
|
||||
val numScans = Integer.parseInt(response[0, 3])
|
||||
|
||||
@ -443,13 +376,32 @@ class MspDevice(context: Context, meta: Meta) : PortSensor(context, meta) {
|
||||
command("ScanResume", 10)
|
||||
//FIXME обработать ошибку связи
|
||||
} 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 {
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import java.util.*
|
||||
* A helper to store points in multiple loaders
|
||||
* 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 {
|
||||
private val loaderMap = HashMap<StorageConnection, TableLoader>()
|
||||
|
||||
|
@ -21,7 +21,7 @@ class VacDeviceFactory : DeviceFactory {
|
||||
"CM32" -> CM32Device(context, sensorConfig)
|
||||
"meradat" -> MeradatVacDevice(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")
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,11 @@
|
||||
package inr.numass.control.readvac
|
||||
|
||||
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.measurements.Measurement
|
||||
import hep.dataforge.control.measurements.MeasurementListener
|
||||
import hep.dataforge.kodex.timeValue
|
||||
import hep.dataforge.kodex.value
|
||||
import hep.dataforge.meta.Meta
|
||||
import inr.numass.control.DeviceDisplay
|
||||
import inr.numass.control.switch
|
||||
import javafx.application.Platform
|
||||
@ -30,7 +32,7 @@ import java.time.format.DateTimeFormatter
|
||||
/**
|
||||
* @author [Alexander Nozik](mailto:altavir@gmail.com)
|
||||
*/
|
||||
open class VacDisplay : DeviceDisplay<Sensor>(), MeasurementListener {
|
||||
open class VacDisplay : DeviceDisplay<Sensor>() {
|
||||
|
||||
val statusProperty = SimpleStringProperty("")
|
||||
var status: String by statusProperty
|
||||
@ -49,7 +51,7 @@ open class VacDisplay : DeviceDisplay<Sensor>(), MeasurementListener {
|
||||
override fun evaluateDeviceException(device: Device, message: String, exception: Throwable) {
|
||||
if (!message.isEmpty()) {
|
||||
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 {
|
||||
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 resString = FORMAT.format(result)
|
||||
Platform.runLater {
|
||||
@ -76,7 +78,22 @@ open class VacDisplay : DeviceDisplay<Sensor>(), MeasurementListener {
|
||||
}
|
||||
}
|
||||
|
||||
fun getTitle(): String{
|
||||
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 {
|
||||
return device.meta.getString("title", device.name);
|
||||
}
|
||||
|
||||
@ -90,7 +107,7 @@ open class VacDisplay : DeviceDisplay<Sensor>(), MeasurementListener {
|
||||
top {
|
||||
borderpane {
|
||||
center {
|
||||
label(device.name){
|
||||
label(device.name) {
|
||||
style {
|
||||
fontSize = 18.pt
|
||||
fontWeight = FontWeight.BOLD
|
||||
|
@ -108,7 +108,8 @@ class NumassDataLoader(
|
||||
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
|
||||
|
@ -50,15 +50,16 @@ class NumassStorage : FileStorage {
|
||||
get() = meta.getString("description", "")
|
||||
|
||||
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) {
|
||||
super.refresh()
|
||||
refresh()
|
||||
}
|
||||
|
||||
override fun updateDirectoryLoaders() {
|
||||
override fun refresh() {
|
||||
try {
|
||||
this.shelves.clear()
|
||||
this.loaders.clear()
|
||||
Files.list(dataDir).forEach { file ->
|
||||
try {
|
||||
@ -194,8 +195,8 @@ class NumassStorage : FileStorage {
|
||||
|
||||
companion object {
|
||||
|
||||
val NUMASS_ZIP_EXTENSION = ".nm.zip"
|
||||
val NUMASS_DATA_LOADER_TYPE = "numassData"
|
||||
const val NUMASS_ZIP_EXTENSION = ".nm.zip"
|
||||
const val NUMASS_DATA_LOADER_TYPE = "numassData"
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,18 +15,19 @@
|
||||
*/
|
||||
package inr.numass
|
||||
|
||||
import hep.dataforge.actions.ActionManager
|
||||
import hep.dataforge.context.*
|
||||
import hep.dataforge.fx.FXPlugin
|
||||
import hep.dataforge.fx.plots.PlotContainer
|
||||
import hep.dataforge.maths.functions.FunctionLibrary
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
||||
import hep.dataforge.providers.Provides
|
||||
import hep.dataforge.stat.models.ModelManager
|
||||
import hep.dataforge.stat.models.WeightedXYModel
|
||||
import hep.dataforge.stat.models.XYModel
|
||||
import hep.dataforge.tables.Adapters
|
||||
import hep.dataforge.tables.ValuesAdapter
|
||||
import hep.dataforge.workspace.tasks.Task
|
||||
import inr.numass.data.analyzers.NumassAnalyzer
|
||||
import inr.numass.data.api.NumassPoint
|
||||
import inr.numass.models.*
|
||||
@ -50,25 +51,35 @@ class NumassPlugin : BasicPlugin() {
|
||||
override fun attach(context: Context) {
|
||||
// StorageManager.buildFrom(context);
|
||||
super.attach(context)
|
||||
//TODO Replace by local providers
|
||||
loadModels(context[ModelManager::class.java])
|
||||
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) {
|
||||
|
@ -24,7 +24,7 @@ import inr.numass.NumassUtils
|
||||
/**
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
class NumassFitScanSummaryTask : AbstractTask<Table>() {
|
||||
object NumassFitScanSummaryTask : AbstractTask<Table>() {
|
||||
|
||||
override fun run(model: TaskModel, data: DataNode<*>): DataNode<Table> {
|
||||
val builder = DataSet.edit(Table::class)
|
||||
@ -44,7 +44,7 @@ class NumassFitScanSummaryTask : AbstractTask<Table>() {
|
||||
override val name = "scansum"
|
||||
|
||||
@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 {
|
||||
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 limit: Double
|
||||
if (Math.abs(u2Val) < 3) {
|
||||
limit = UpperLimitGenerator.getConfidenceLimit(u2Val) * pars.getError("U2")
|
||||
val limit: Double = if (Math.abs(u2Val) < 3) {
|
||||
UpperLimitGenerator.getConfidenceLimit(u2Val) * pars.getError("U2")
|
||||
} else {
|
||||
limit = java.lang.Double.NaN
|
||||
java.lang.Double.NaN
|
||||
}
|
||||
|
||||
builder.row(
|
||||
|
@ -117,15 +117,6 @@ val mergeTask = task("merge") {
|
||||
action<Table, Table>(MergeDataAction())
|
||||
}
|
||||
|
||||
//val newMergeTask = task("merge") {
|
||||
// model { meta ->
|
||||
// dependsOn(analyzeTask, meta)
|
||||
// }
|
||||
// join<Table, Table> {
|
||||
// byValue(MERGE_NAME)
|
||||
// }
|
||||
//}
|
||||
|
||||
val mergeEmptyTask = task("empty") {
|
||||
model { meta ->
|
||||
if (!meta.hasMeta("empty")) {
|
||||
|
@ -14,10 +14,6 @@ import org.junit.Test;
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
public class NumassTest {
|
||||
|
||||
public NumassTest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of buildContext method, of class Numass.
|
||||
*/
|
||||
|
@ -31,7 +31,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Stream;
|
||||
@ -167,7 +166,7 @@ public class NumassRun implements Metoid, Responder {
|
||||
try {
|
||||
String filePath = message.getMeta().getString("path", "");
|
||||
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) {
|
||||
((NumassStorage) storage).pushNumassData(filePath, fileName, message.getData().getBuffer());
|
||||
} else {
|
||||
@ -175,7 +174,7 @@ public class NumassRun implements Metoid, Responder {
|
||||
}
|
||||
//TODO add checksum here
|
||||
return okResponseBase("numass.data.push.response", false, false).build();
|
||||
} catch (StorageException | IOException ex) {
|
||||
} catch (StorageException ex) {
|
||||
logger.error("Failed to push point", ex);
|
||||
return errorResponseBase("numass.data.push.response", ex).build();
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import hep.dataforge.storage.commons.LoaderFactory;
|
||||
import hep.dataforge.storage.commons.StorageManager;
|
||||
import hep.dataforge.storage.commons.StorageUtils;
|
||||
import inr.numass.data.storage.NumassStorage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ratpack.server.RatpackServer;
|
||||
@ -242,4 +243,10 @@ public class NumassServer extends AbstractNetworkListener implements ContextAwar
|
||||
public NumassRun getRun() {
|
||||
return run;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return LoggerFactory.getLogger(getClass());
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,8 @@ package inr.numass.viewer
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.fx.bindWindow
|
||||
import hep.dataforge.fx.dfIcon
|
||||
import hep.dataforge.fx.*
|
||||
import hep.dataforge.fx.fragments.LogFragment
|
||||
import hep.dataforge.fx.runGoal
|
||||
import hep.dataforge.fx.ui
|
||||
import hep.dataforge.meta.Metoid
|
||||
import hep.dataforge.storage.api.Loader
|
||||
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.NumassSet
|
||||
import inr.numass.data.storage.NumassDataLoader
|
||||
import inr.numass.data.storage.NumassStorage
|
||||
import inr.numass.data.storage.NumassStorageFactory
|
||||
import javafx.beans.property.SimpleBooleanProperty
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import javafx.geometry.Insets
|
||||
import javafx.scene.control.Alert
|
||||
import javafx.scene.control.ContextMenu
|
||||
import javafx.scene.control.TreeItem
|
||||
import javafx.scene.image.ImageView
|
||||
@ -280,12 +277,15 @@ class StorageView(private val context: Context = Global) : View(title = "Numass
|
||||
runGoal("loadDirectory[$path]") {
|
||||
title = "Load storage ($path)"
|
||||
message = "Building numass storage tree..."
|
||||
(StorageManager.buildStorage(context, NumassStorageFactory.buildStorageMeta(path, true, false)) as NumassStorage)
|
||||
StorageManager.buildStorage(context, NumassStorageFactory.buildStorageMeta(path, true, false))
|
||||
} ui {
|
||||
storage = it
|
||||
storageName = "Storage: $path"
|
||||
|
||||
statusBar.text = "OK"
|
||||
} except {
|
||||
alert(type = Alert.AlertType.ERROR, header = "Error during storage loading", content = it.toString()).show()
|
||||
it.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user