From 700707a7a92c329c246a49a694d944871567c0e3 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 28 Mar 2018 16:59:40 +0300 Subject: [PATCH] Numass control update --- .../java/inr/numass/client/NumassClient.java | 6 +- .../control/cryotemp/PKT8VirtualPort.kt | 7 +- .../inr/numass/control/msp/MspDevice.kt | 328 ++++++++---------- .../numass/control/NumassStorageConnection.kt | 54 +++ .../inr/numass/control/StorageHelper.kt | 1 + .../control/readvac/VacDeviceFactory.kt | 2 +- .../inr/numass/control/readvac/VacDisplay.kt | 33 +- .../numass/data/storage/NumassDataLoader.kt | 3 +- .../inr/numass/data/storage/NumassStorage.kt | 11 +- .../main/kotlin/inr/numass/NumassPlugin.kt | 43 ++- .../numass/tasks/NumassFitScanSummaryTask.kt | 11 +- .../kotlin/inr/numass/tasks/NumassTasks.kt | 9 - .../src/test/java/inr/numass/NumassTest.java | 4 - .../java/inr/numass/server/NumassRun.java | 5 +- .../java/inr/numass/server/NumassServer.java | 7 + .../kotlin/inr/numass/viewer/StorageView.kt | 12 +- 16 files changed, 280 insertions(+), 256 deletions(-) create mode 100644 numass-control/src/main/kotlin/inr/numass/control/NumassStorageConnection.kt diff --git a/numass-client/src/main/java/inr/numass/client/NumassClient.java b/numass-client/src/main/java/inr/numass/client/NumassClient.java index 1786a00c..f163b3b1 100644 --- a/numass-client/src/main/java/inr/numass/client/NumassClient.java +++ b/numass-client/src/main/java/inr/numass/client/NumassClient.java @@ -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)); diff --git a/numass-control/cryotemp/src/main/kotlin/inr/numass/control/cryotemp/PKT8VirtualPort.kt b/numass-control/cryotemp/src/main/kotlin/inr/numass/control/cryotemp/PKT8VirtualPort.kt index 27041cd3..9777d510 100644 --- a/numass-control/cryotemp/src/main/kotlin/inr/numass/control/cryotemp/PKT8VirtualPort.kt +++ b/numass-control/cryotemp/src/main/kotlin/inr/numass/control/cryotemp/PKT8VirtualPort.kt @@ -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) { diff --git a/numass-control/msp/src/main/kotlin/inr/numass/control/msp/MspDevice.kt b/numass-control/msp/src/main/kotlin/inr/numass/control/msp/MspDevice.kt index 7bb2f073..744047b3 100644 --- a/numass-control/msp/src/main/kotlin/inr/numass/control/msp/MspDevice.kt +++ b/numass-control/msp/src/main/kotlin/inr/numass/control/msp/MspDevice.kt @@ -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? = null +// private var measurementDelegate: Consumer? = 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,54 +133,47 @@ 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() - var response = commandAndWait("Sensors") - if (response.isOK) { - sensorName = response[2, 1] - } else { - notifyError(response.errorDescription, null) - return false - } - //PENDING определеить в конфиге номер прибора - - 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") - if (response.isOK) { - // controlled = true; - // invalidateState("controlled"); - updateLogicalState("controlled", true) - } else { - notifyError(response.errorDescription, null) - return false - } - // connected = true; - updateLogicalState(PortSensor.CONNECTED_STATE, true) - return true + if (on) { + //ensure device is connected + connected = true + var response = commandAndWait("Sensors") + if (response.isOK) { + sensorName = response[2, 1] } else { - connection.close() - return !commandAndWait("Release").isOK + notifyError(response.errorDescription, null) + return false + } + //PENDING определеить в конфиге номер прибора + + response = commandAndWait("Select", sensorName) + if (response.isOK) { + updateLogicalState("selected", true) + } else { + notifyError(response.errorDescription, null) + return false } + response = commandAndWait("Control", "inr.numass.msp", "1.1") + if (response.isOK) { + + updateLogicalState("controlled", true) + } else { + notifyError(response.errorDescription, null) + return false + } + // connected = true; + updateLogicalState(PortSensor.CONNECTED_STATE, true) + return true } else { - return false + return !commandAndWait("Release").isOK } + } /** @@ -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(), Consumer { - - private val collector = RegularPointCollector(averagingDuration, Consumer { this.result(it) }) - private val helper = StorageHelper(this@MspDevice) { connection: StorageConnection -> this.makeLoader(connection) } - private var peakMap: MutableMap = 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 start() { - try { - val measurementName = "peakJump" - val filterMode = meta.getString("filterMode", "PeakAverage") - val accuracy = meta.getInt("accuracy", 5)!! - //PENDING вставить остальные параметры? - sendAndWait("MeasurementRemoveAll") - if (commandAndWait("AddPeakJump", measurementName, filterMode, accuracy, 0, 0, 0).isOK) { - peakMap.clear() - for (peak in meta.getMetaList("peak")) { - peakMap.put(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") - } - } - } 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) - } - - if (!commandAndWait("ScanStart", 2).isOK) { - this.error("Failed to start scan", null) - } - } catch (ex: ControlException) { - error(ex) + override fun setMeasurement(oldMeta: Meta?, newMeta: Meta) { + if(oldMeta!= null){ + stopMeasurement() + } + if (newMeta.getString("type", "peakJump") == "peakJump") { + execute { + startPeakJump(newMeta) } - - afterStart() + } else { + throw MeasurementException("Unknown measurement type") } + } - @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) + private fun startPeakJump(meta: Meta) { + notifyMeasurementState(MeasurementState.IN_PROGRESS) + val measurementName = "peakJump" + val filterMode = meta.getString("filterMode", "PeakAverage") + val accuracy = meta.getInt("accuracy", 5) + //PENDING вставить остальные параметры? + sendAndWait("MeasurementRemoveAll") + +// val peakMap: MutableMap = LinkedHashMap() + + val builder = TableFormatBuilder().addTime("timestamp") + + if (commandAndWait("AddPeakJump", measurementName, filterMode, accuracy, 0, 0, 0).isOK) { +// peakMap.clear() + for (peak in meta.getMetaList("peak")) { +// 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") } - @Synchronized - override fun result(result: Values, time: Instant) { - super.result(result, time) - helper.push(result) - } + storageHelper = NumassStorageConnection("msp"){builder.build()} + connect(storageHelper) - 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 { diff --git a/numass-control/src/main/kotlin/inr/numass/control/NumassStorageConnection.kt b/numass-control/src/main/kotlin/inr/numass/control/NumassStorageConnection.kt new file mode 100644 index 00000000..0997fa16 --- /dev/null +++ b/numass-control/src/main/kotlin/inr/numass/control/NumassStorageConnection.kt @@ -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() + + + @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() + } +} \ No newline at end of file diff --git a/numass-control/src/main/kotlin/inr/numass/control/StorageHelper.kt b/numass-control/src/main/kotlin/inr/numass/control/StorageHelper.kt index f9d8e0df..80cdc9dc 100644 --- a/numass-control/src/main/kotlin/inr/numass/control/StorageHelper.kt +++ b/numass-control/src/main/kotlin/inr/numass/control/StorageHelper.kt @@ -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() diff --git a/numass-control/vac/src/main/kotlin/inr/numass/control/readvac/VacDeviceFactory.kt b/numass-control/vac/src/main/kotlin/inr/numass/control/readvac/VacDeviceFactory.kt index a104a718..ecabf0b7 100644 --- a/numass-control/vac/src/main/kotlin/inr/numass/control/readvac/VacDeviceFactory.kt +++ b/numass-control/vac/src/main/kotlin/inr/numass/control/readvac/VacDeviceFactory.kt @@ -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") } } diff --git a/numass-control/vac/src/main/kotlin/inr/numass/control/readvac/VacDisplay.kt b/numass-control/vac/src/main/kotlin/inr/numass/control/readvac/VacDisplay.kt index ac7e3f63..e18d0006 100644 --- a/numass-control/vac/src/main/kotlin/inr/numass/control/readvac/VacDisplay.kt +++ b/numass-control/vac/src/main/kotlin/inr/numass/control/readvac/VacDisplay.kt @@ -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(), MeasurementListener { +open class VacDisplay : DeviceDisplay() { val statusProperty = SimpleStringProperty("") var status: String by statusProperty @@ -49,7 +51,7 @@ open class VacDisplay : DeviceDisplay(), 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(), 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(), 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(), MeasurementListener { top { borderpane { center { - label(device.name){ + label(device.name) { style { fontSize = 18.pt fontWeight = FontWeight.BOLD diff --git a/numass-core/src/main/kotlin/inr/numass/data/storage/NumassDataLoader.kt b/numass-core/src/main/kotlin/inr/numass/data/storage/NumassDataLoader.kt index f5dc9125..c258a14b 100644 --- a/numass-core/src/main/kotlin/inr/numass/data/storage/NumassDataLoader.kt +++ b/numass-core/src/main/kotlin/inr/numass/data/storage/NumassDataLoader.kt @@ -108,7 +108,8 @@ class NumassDataLoader( throw TODO("Not supported yet.") } - override val startTime: Instant = meta.optValue("start_time").map { it.timeValue() }.orElseGet { super.startTime } + override val startTime: Instant + get() = meta.optValue("start_time").map { it.timeValue() }.orElseGet { super.startTime } override val isOpen: Boolean diff --git a/numass-core/src/main/kotlin/inr/numass/data/storage/NumassStorage.kt b/numass-core/src/main/kotlin/inr/numass/data/storage/NumassStorage.kt index 10959d7d..8264c182 100644 --- a/numass-core/src/main/kotlin/inr/numass/data/storage/NumassStorage.kt +++ b/numass-core/src/main/kotlin/inr/numass/data/storage/NumassStorage.kt @@ -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" } } diff --git a/numass-main/src/main/kotlin/inr/numass/NumassPlugin.kt b/numass-main/src/main/kotlin/inr/numass/NumassPlugin.kt index 58678074..1efec731 100644 --- a/numass-main/src/main/kotlin/inr/numass/NumassPlugin.kt +++ b/numass-main/src/main/kotlin/inr/numass/NumassPlugin.kt @@ -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 { + return tasks.map { it.name } } private fun loadMath(math: FunctionLibrary) { diff --git a/numass-main/src/main/kotlin/inr/numass/tasks/NumassFitScanSummaryTask.kt b/numass-main/src/main/kotlin/inr/numass/tasks/NumassFitScanSummaryTask.kt index 9494c76a..1c9125dc 100644 --- a/numass-main/src/main/kotlin/inr/numass/tasks/NumassFitScanSummaryTask.kt +++ b/numass-main/src/main/kotlin/inr/numass/tasks/NumassFitScanSummaryTask.kt @@ -24,7 +24,7 @@ import inr.numass.NumassUtils /** * @author Alexander Nozik */ -class NumassFitScanSummaryTask : AbstractTask() { +object NumassFitScanSummaryTask : AbstractTask
() { override fun run(model: TaskModel, data: DataNode<*>): DataNode
{ val builder = DataSet.edit(Table::class) @@ -44,7 +44,7 @@ class NumassFitScanSummaryTask : AbstractTask
() { override val name = "scansum" @TypedActionDef(name = "sterileSummary", inputType = FitResult::class, outputType = Table::class) - private inner class FitSummaryAction : ManyToOneAction() { + private class FitSummaryAction : ManyToOneAction() { override fun execute(context: Context, nodeName: String, input: Map, meta: Laminate): Table { val builder = ListTable.Builder("m", "U2", "U2err", "U2limit", "E0", "trap") @@ -53,11 +53,10 @@ class NumassFitScanSummaryTask : AbstractTask
() { 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( diff --git a/numass-main/src/main/kotlin/inr/numass/tasks/NumassTasks.kt b/numass-main/src/main/kotlin/inr/numass/tasks/NumassTasks.kt index 3a5538bc..28b7fc64 100644 --- a/numass-main/src/main/kotlin/inr/numass/tasks/NumassTasks.kt +++ b/numass-main/src/main/kotlin/inr/numass/tasks/NumassTasks.kt @@ -117,15 +117,6 @@ val mergeTask = task("merge") { action(MergeDataAction()) } -//val newMergeTask = task("merge") { -// model { meta -> -// dependsOn(analyzeTask, meta) -// } -// join { -// byValue(MERGE_NAME) -// } -//} - val mergeEmptyTask = task("empty") { model { meta -> if (!meta.hasMeta("empty")) { diff --git a/numass-main/src/test/java/inr/numass/NumassTest.java b/numass-main/src/test/java/inr/numass/NumassTest.java index e0118778..6c89d9ce 100644 --- a/numass-main/src/test/java/inr/numass/NumassTest.java +++ b/numass-main/src/test/java/inr/numass/NumassTest.java @@ -14,10 +14,6 @@ import org.junit.Test; * @author Alexander Nozik */ public class NumassTest { - - public NumassTest() { - } - /** * Test of buildContext method, of class Numass. */ diff --git a/numass-server/src/main/java/inr/numass/server/NumassRun.java b/numass-server/src/main/java/inr/numass/server/NumassRun.java index bcbcaf75..45e485f4 100644 --- a/numass-server/src/main/java/inr/numass/server/NumassRun.java +++ b/numass-server/src/main/java/inr/numass/server/NumassRun.java @@ -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(); } diff --git a/numass-server/src/main/java/inr/numass/server/NumassServer.java b/numass-server/src/main/java/inr/numass/server/NumassServer.java index e2a07769..b4a660d5 100644 --- a/numass-server/src/main/java/inr/numass/server/NumassServer.java +++ b/numass-server/src/main/java/inr/numass/server/NumassServer.java @@ -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()); + } } diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt index f7fa559e..d3b7ff5d 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt @@ -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() } }