From c83d38991a6707b2566b257a3b2b92d40b790051 Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Thu, 4 Jul 2024 15:59:27 +0100 Subject: [PATCH 01/25] Created PressureJumpCell device and the main PVs for setting pressure and pressure jumps. --- src/dodal/beamlines/p38.py | 15 +++ src/dodal/devices/pressure_jump_cell.py | 141 ++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 src/dodal/devices/pressure_jump_cell.py diff --git a/src/dodal/beamlines/p38.py b/src/dodal/beamlines/p38.py index 11da31b0da..f743dbf388 100644 --- a/src/dodal/beamlines/p38.py +++ b/src/dodal/beamlines/p38.py @@ -15,6 +15,7 @@ from dodal.devices.i22.dcm import CrystalMetadata, DoubleCrystalMonochromator from dodal.devices.i22.fswitch import FSwitch from dodal.devices.linkam3 import Linkam3 +from dodal.devices.pressure_jump_cell import PressureJumpCell from dodal.devices.slits import Slits from dodal.devices.tetramm import TetrammDetector from dodal.devices.undulator import Undulator @@ -318,3 +319,17 @@ def linkam( wait_for_connection, fake_with_ophyd_sim, ) + + +def high_pressure_xray_cell( + wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False +) -> PressureJumpCell: + return device_instantiation( + PressureJumpCell, + "high_pressure_xray_cell", + "-EA-HPXC-01:", + wait_for_connection, + fake_with_ophyd_sim, + adc1_prefix=f"{BeamlinePrefix(BL).beamline_prefix}-EA-ADC-01:", + adc2_prefix=f"{BeamlinePrefix(BL).beamline_prefix}-EA-ADC-02:", + ) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py new file mode 100644 index 0000000000..4554340abb --- /dev/null +++ b/src/dodal/devices/pressure_jump_cell.py @@ -0,0 +1,141 @@ +from ophyd_async.core import ConfigSignal, StandardReadable +from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw + + +class PressureJumpCellPumpMode: + MANUAL = "Manual" + AUTO_PRESSURE = "Auto Pressure" + AUTO_POSITION = "Auto Position" + + +class PressureJumpCellBusyStatus: + IDLE = "Idle" + BUSY = "Busy" + + +class PressureJumpCellTimerState: + TIMEOUT = "TIMEOUT" + COUNTDOWN = "COUNTDOWN" + + +class PressureJumpCellStopValue: + CONTINUE = "CONTINUE" + STOP = "STOP" + + +class PressureJumpCell(StandardReadable): + """ + High pressure X-ray cell, used to apply pressure or pressure jupmps to a sample. + """ + + def __init__( + self, + prefix: str = "", + adc1_prefix: str = "", + adc2_prefix: str = "", + name: str = "", + ) -> None: + with self.add_children_as_readables(): + ## Valves ## + self.valve1_state = epics_signal_r(float, prefix + "V1:STA") + # V2 - valve manual control + self.valve3_state = epics_signal_r(float, prefix + "V3:STA") + # V4 - valve manual control + self.valve5_state = epics_signal_r(float, prefix + "V5:STA") + self.valve6_state = epics_signal_r(float, prefix + "V6:STA") + # V7 - valve manual control + # V8 - valve manual control + + ## Cell ## + self.cell_temperature = epics_signal_r(float, prefix + "TEMP") + + ## Pump ## + self.pump_position = epics_signal_r(float, prefix + "POS") + self.pump_forward_limit = epics_signal_r(float, prefix + "D74IN1") + self.pump_backward_limit = epics_signal_r(float, prefix + "D74IN0") + + ## Pressure Transducer 1 ## + self.pressuretransducer1_omron_pressure = epics_signal_r( + float, prefix + "PP1:PRES" + ) + self.pressuretransducer1_omron_voltage = epics_signal_r( + float, prefix + "PP1:RAW" + ) + self.pressuretransducer1_beckhoff_pressure = epics_signal_r( + float, prefix + "STATP1:MeanValue_RBV" + ) + self.pressuretransducer1_beckhoff_voltage = epics_signal_r( + float, adc2_prefix + "CH1" + ) + + ## Pressure Transducer 2 ## + self.pressuretransducer2_omron_pressure = epics_signal_r( + float, prefix + "PP2:PRES" + ) + self.pressuretransducer2_omron_voltage = epics_signal_r( + float, prefix + "PP2:RAW" + ) + self.pressuretransducer2_beckhoff_pressure = epics_signal_r( + float, prefix + "STATP2:MeanValue_RBV" + ) + self.pressuretransducer2_beckhoff_voltage = epics_signal_r( + float, adc1_prefix + "CH2" + ) + + ## Pressure Transducer 3 ## + self.pressuretransducer3_omron_pressure = epics_signal_r( + float, prefix + "PP3:PRES" + ) + self.pressuretransducer3_omron_voltage = epics_signal_r( + float, prefix + "PP3:RAW" + ) + self.pressuretransducer3_beckhoff_pressure = epics_signal_r( + float, prefix + "STATP3:MeanValue_RBV" + ) + self.pressuretransducer3_beckhoff_voltage = epics_signal_r( + float, adc1_prefix + "CH1" + ) + + ##Control Common## + self.control_gotobusy = epics_signal_r( + PressureJumpCellBusyStatus, prefix + "CTRL:GOTOBUSY" + ) + + ## Control Pressure ## + self.control_timer = epics_signal_r( + PressureJumpCellTimerState, prefix + "CTRL:TIMER" + ) + self.control_counter = epics_signal_r(float, prefix + "CTRL:COUNTER") + self.control_script_status = epics_signal_r(str, prefix + "CTRL:RESULT") + self.control_routine = epics_signal_r(str, prefix + "CTRL:METHOD") + self.control_state = epics_signal_r(str, prefix + "CTRL:STATE") + self.control_iteration = epics_signal_r(int, prefix + "CTRL:ITER") + + with self.add_children_as_readables(ConfigSignal): + ## Pump ## + self.pump_mode = epics_signal_rw( + PressureJumpCellPumpMode, prefix + "SP:AUTO" + ) + + ##Control Common## + self.control_stop = epics_signal_rw( + PressureJumpCellStopValue, prefix + "CTRL:STOP" + ) + + ## Control Pressure ## + self.control_target_pressure = epics_signal_rw( + float, prefix + "CTRL:TARGET" + ) + self.control_timeout = epics_signal_rw(float, prefix + "CTRL:TIMER.HIGH") + self.control_go = epics_signal_rw(bool, prefix + "CTRL:GO") + + ## Control Jump ## + self.control_jump_from_pressure = epics_signal_rw( + float, prefix + "CTRL:JUMPF" + ) + self.control_jump_to_pressure = epics_signal_rw( + float, prefix + "CTRL:JUMPT" + ) + self.control_jump_set = epics_signal_rw(bool, prefix + "CTRL:SETJUMP") + + super().__init__(name) From d7715c48503cf75e06696b4d3cbbb7383d18a76a Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Fri, 5 Jul 2024 09:14:40 +0100 Subject: [PATCH 02/25] Added pump motor and valve manual control PVs and corrected some typos and formatting. --- src/dodal/devices/pressure_jump_cell.py | 67 +++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 4554340abb..ec7ac52eb8 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -23,9 +23,39 @@ class PressureJumpCellStopValue: STOP = "STOP" +class PressureJumpCellValveControlRequest: + OPEN = "Open" + CLOSE = "Close" + RESET = "Reset" + ARM = "Arm" + DISARM = "Disarm" + # TODO the nones may not be required but FVST and SXST set + NONE1 = "" + NONE2 = "" + + +class PressureJumpCellPumpMotorControlRequest: + ENABLE = "Enable" + DISABLE = "Disable" + RESET = "Reset" + FORWARD = "Forward" + REVERSE = "Reverse" + + +class PressureJumpCellPumpMotorDirection: + ZERO = "0" + FORWARD = "Forward" + REVERSE = "Reverse" + THREE = "3" + FOUR = "4" + FIVE = "5" + SIX = "6" + SEVEN = "7" + + class PressureJumpCell(StandardReadable): """ - High pressure X-ray cell, used to apply pressure or pressure jupmps to a sample. + High pressure X-ray cell, used to apply pressure or pressure jumps to a sample. """ def __init__( @@ -53,6 +83,10 @@ def __init__( self.pump_position = epics_signal_r(float, prefix + "POS") self.pump_forward_limit = epics_signal_r(float, prefix + "D74IN1") self.pump_backward_limit = epics_signal_r(float, prefix + "D74IN0") + self.pump_position = epics_signal_r( + PressureJumpCellPumpMotorDirection, prefix + "MTRDIR" + ) + self.pump_speed_rbv = epics_signal_r(int, prefix + "MSPEED_RBV") ## Pressure Transducer 1 ## self.pressuretransducer1_omron_pressure = epics_signal_r( @@ -96,7 +130,7 @@ def __init__( float, adc1_prefix + "CH1" ) - ##Control Common## + ## Control Common ## self.control_gotobusy = epics_signal_r( PressureJumpCellBusyStatus, prefix + "CTRL:GOTOBUSY" ) @@ -112,12 +146,39 @@ def __init__( self.control_iteration = epics_signal_r(int, prefix + "CTRL:ITER") with self.add_children_as_readables(ConfigSignal): + ## Valves ## + self.valve1_open = epics_signal_rw(bool, prefix + "V1:OPENSEQ") + self.valve1_control = epics_signal_rw( + PressureJumpCellValveControlRequest, prefix + "V1:CON" + ) + + self.valve3_open = epics_signal_rw(bool, prefix + "V3:OPENSEQ") + self.valve3_control = epics_signal_rw( + PressureJumpCellValveControlRequest, prefix + "V3:CON" + ) + + self.valve5_open = epics_signal_rw(bool, prefix + "V5:OPENSEQ") + self.valve5_control = epics_signal_rw( + PressureJumpCellValveControlRequest, prefix + "V5:CON" + ) + + self.valve6_open = epics_signal_rw(bool, prefix + "V6:OPENSEQ") + self.valve6_control = epics_signal_rw( + PressureJumpCellValveControlRequest, prefix + "V6CON" + ) + ## Pump ## self.pump_mode = epics_signal_rw( PressureJumpCellPumpMode, prefix + "SP:AUTO" ) + self.pump_speed = epics_signal_rw(float, prefix + "MSPEED") + self.pump_move_forward = epics_signal_rw(bool, prefix + "M1:FORW") + self.pump_move_backward = epics_signal_rw(bool, prefix + "M1:BACKW") + self.pump_move_backward = epics_signal_rw( + PressureJumpCellPumpMotorControlRequest, prefix + "M1:CON" + ) - ##Control Common## + ## Control Common ## self.control_stop = epics_signal_rw( PressureJumpCellStopValue, prefix + "CTRL:STOP" ) From 4294d753f8c7b073152385f92af8b88566c1ac40 Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Sun, 14 Jul 2024 16:11:45 +0100 Subject: [PATCH 03/25] Pressure jump cell: Added enums for valve and limit switch states and added unit test for readback values. --- src/dodal/devices/pressure_jump_cell.py | 36 ++- .../unit_tests/test_pressure_jump_cell.py | 208 ++++++++++++++++++ 2 files changed, 237 insertions(+), 7 deletions(-) create mode 100644 tests/devices/unit_tests/test_pressure_jump_cell.py diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index ec7ac52eb8..50558e96db 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -53,6 +53,28 @@ class PressureJumpCellPumpMotorDirection: SEVEN = "7" +class PressureJumpCellValveState: + FAULT = "Fault" + OPEN = "Open" + OPENING = "Opening" + CLOSED = "Closed" + CLOSING = "Closing" + NONE5 = "" + NONE6 = "" + +class PressureJumpCellFastValveState: + FAULT = "Fault" + OPEN = "Open" + OPEN_ARMED = "Open Armed" + CLOSED = "Closed" + CLOSED_ARMED = "Closed Armed" + NONE5 = "Unused" + NONE6 = "" + +class PressureJumpCellLimitSwitch: + OFF = "Off" + ON = "On" + class PressureJumpCell(StandardReadable): """ High pressure X-ray cell, used to apply pressure or pressure jumps to a sample. @@ -67,12 +89,12 @@ def __init__( ) -> None: with self.add_children_as_readables(): ## Valves ## - self.valve1_state = epics_signal_r(float, prefix + "V1:STA") + self.valve1_state = epics_signal_r(PressureJumpCellValveState, prefix + "V1:STA") # V2 - valve manual control - self.valve3_state = epics_signal_r(float, prefix + "V3:STA") + self.valve3_state = epics_signal_r(PressureJumpCellValveState, prefix + "V3:STA") # V4 - valve manual control - self.valve5_state = epics_signal_r(float, prefix + "V5:STA") - self.valve6_state = epics_signal_r(float, prefix + "V6:STA") + self.valve5_state = epics_signal_r(PressureJumpCellFastValveState, prefix + "V5:STA") + self.valve6_state = epics_signal_r(PressureJumpCellFastValveState, prefix + "V6:STA") # V7 - valve manual control # V8 - valve manual control @@ -81,9 +103,9 @@ def __init__( ## Pump ## self.pump_position = epics_signal_r(float, prefix + "POS") - self.pump_forward_limit = epics_signal_r(float, prefix + "D74IN1") - self.pump_backward_limit = epics_signal_r(float, prefix + "D74IN0") - self.pump_position = epics_signal_r( + self.pump_forward_limit = epics_signal_r(PressureJumpCellLimitSwitch, prefix + "D74IN1") + self.pump_backward_limit = epics_signal_r(PressureJumpCellLimitSwitch, prefix + "D74IN0") + self.pump_motor_direction = epics_signal_r( PressureJumpCellPumpMotorDirection, prefix + "MTRDIR" ) self.pump_speed_rbv = epics_signal_r(int, prefix + "MSPEED_RBV") diff --git a/tests/devices/unit_tests/test_pressure_jump_cell.py b/tests/devices/unit_tests/test_pressure_jump_cell.py new file mode 100644 index 0000000000..208bb0391b --- /dev/null +++ b/tests/devices/unit_tests/test_pressure_jump_cell.py @@ -0,0 +1,208 @@ +from unittest.mock import ANY + +import pytest +from ophyd_async.core import DeviceCollector, assert_reading, set_mock_value + +from dodal.devices.pressure_jump_cell import ( + PressureJumpCell, + PressureJumpCellBusyStatus, + PressureJumpCellPumpMotorDirection, + PressureJumpCellTimerState, + PressureJumpCellValveState, + PressureJumpCellFastValveState, + PressureJumpCellLimitSwitch +) + +@pytest.fixture +async def pressurejumpcell() -> PressureJumpCell: + async with DeviceCollector(mock=True): + pjump = PressureJumpCell("DEMO-PJUMPCELL-01:") + + return pjump + + +async def test_reading_pjumpcell_includes_read_fields( + pressurejumpcell: PressureJumpCell, +): + set_mock_value(pressurejumpcell.valve1_state, PressureJumpCellValveState.CLOSED) + set_mock_value(pressurejumpcell.valve3_state, PressureJumpCellValveState.OPEN) + set_mock_value(pressurejumpcell.valve5_state, PressureJumpCellFastValveState.CLOSED_ARMED) + set_mock_value(pressurejumpcell.valve6_state, PressureJumpCellFastValveState.OPEN_ARMED) + set_mock_value(pressurejumpcell.cell_temperature, 12.3) + set_mock_value(pressurejumpcell.pump_position, 100) + set_mock_value(pressurejumpcell.pump_forward_limit, PressureJumpCellLimitSwitch.OFF) + set_mock_value(pressurejumpcell.pump_backward_limit, PressureJumpCellLimitSwitch.ON) + set_mock_value(pressurejumpcell.pump_motor_direction, PressureJumpCellPumpMotorDirection.FORWARD) + set_mock_value(pressurejumpcell.pump_speed_rbv, 100) + set_mock_value(pressurejumpcell.pressuretransducer1_omron_pressure, 1001) + set_mock_value(pressurejumpcell.pressuretransducer1_omron_voltage, 2.51) + set_mock_value(pressurejumpcell.pressuretransducer1_beckhoff_pressure, 1001.1) + set_mock_value(pressurejumpcell.pressuretransducer1_beckhoff_voltage, 2.51) + set_mock_value(pressurejumpcell.pressuretransducer2_omron_pressure, 1002) + set_mock_value(pressurejumpcell.pressuretransducer2_omron_voltage, 2.52) + set_mock_value(pressurejumpcell.pressuretransducer2_beckhoff_pressure, 1002.2) + set_mock_value(pressurejumpcell.pressuretransducer2_beckhoff_voltage, 2.52) + set_mock_value(pressurejumpcell.pressuretransducer3_omron_pressure, 1003) + set_mock_value(pressurejumpcell.pressuretransducer3_omron_voltage, 2.53) + set_mock_value(pressurejumpcell.pressuretransducer3_beckhoff_pressure, 1003.3) + set_mock_value(pressurejumpcell.pressuretransducer3_beckhoff_voltage, 2.53) + set_mock_value(pressurejumpcell.control_gotobusy, PressureJumpCellBusyStatus.IDLE) + set_mock_value(pressurejumpcell.control_timer, PressureJumpCellTimerState.COUNTDOWN) + set_mock_value(pressurejumpcell.control_counter, 123) + set_mock_value(pressurejumpcell.control_script_status, "ABC") + set_mock_value(pressurejumpcell.control_routine, "CDE") + set_mock_value(pressurejumpcell.control_state, "EFG") + set_mock_value(pressurejumpcell.control_iteration, 456) + + + await assert_reading( + pressurejumpcell, + { + "pjump-valve1_state": { + "value": PressureJumpCellValveState.CLOSED, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-valve3_state": { + "value": PressureJumpCellValveState.OPEN, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-valve5_state": { + "value": PressureJumpCellFastValveState.CLOSED_ARMED, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-valve6_state": { + "value": PressureJumpCellFastValveState.OPEN_ARMED, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-cell_temperature": { + "value": 12.3, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pump_position": { + "value": 100, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pump_forward_limit": { + "value": PressureJumpCellLimitSwitch.OFF, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pump_backward_limit": { + "value": PressureJumpCellLimitSwitch.ON, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pump_motor_direction": { + "value": PressureJumpCellPumpMotorDirection.FORWARD, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pump_speed_rbv": { + "value": 100, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer1_omron_pressure": { + "value": 1001, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer1_omron_voltage": { + "value": 2.51, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer1_beckhoff_pressure": { + "value": 1001.1, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer1_beckhoff_voltage": { + "value": 2.51, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer2_omron_pressure": { + "value": 1002, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer2_omron_voltage": { + "value": 2.52, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer2_beckhoff_pressure": { + "value": 1002.2, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer2_beckhoff_voltage": { + "value": 2.52, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer3_omron_pressure": { + "value": 1003, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer3_omron_voltage": { + "value": 2.53, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer3_beckhoff_pressure": { + "value": 1003.3, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-pressuretransducer3_beckhoff_voltage": { + "value": 2.53, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-control_gotobusy": { + "value": PressureJumpCellBusyStatus.IDLE, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-control_timer": { + "value": PressureJumpCellTimerState.COUNTDOWN, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-control_counter": { + "value": 123, + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-control_script_status": { + "value": "ABC", + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-control_routine": { + "value": "CDE", + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-control_state": { + "value": "EFG", + "timestamp": ANY, + "alarm_severity": 0, + }, + "pjump-control_iteration": { + "value": 456, + "timestamp": ANY, + "alarm_severity": 0, + }, + }, + ) + From 90684235a19c9ab9dfd2a8b3d9fbdd695667fef3 Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Mon, 15 Jul 2024 09:49:46 +0100 Subject: [PATCH 04/25] Linting and formatting fixes. --- src/dodal/devices/pressure_jump_cell.py | 55 ++++++++++++------- .../unit_tests/test_pressure_jump_cell.py | 26 +++++---- 2 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 50558e96db..4fcee8fce3 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -54,27 +54,30 @@ class PressureJumpCellPumpMotorDirection: class PressureJumpCellValveState: - FAULT = "Fault" - OPEN = "Open" - OPENING = "Opening" - CLOSED = "Closed" - CLOSING = "Closing" - NONE5 = "" - NONE6 = "" + FAULT = "Fault" + OPEN = "Open" + OPENING = "Opening" + CLOSED = "Closed" + CLOSING = "Closing" + NONE5 = "" + NONE6 = "" + class PressureJumpCellFastValveState: - FAULT = "Fault" - OPEN = "Open" - OPEN_ARMED = "Open Armed" - CLOSED = "Closed" - CLOSED_ARMED = "Closed Armed" - NONE5 = "Unused" - NONE6 = "" + FAULT = "Fault" + OPEN = "Open" + OPEN_ARMED = "Open Armed" + CLOSED = "Closed" + CLOSED_ARMED = "Closed Armed" + NONE5 = "Unused" + NONE6 = "" + class PressureJumpCellLimitSwitch: OFF = "Off" ON = "On" + class PressureJumpCell(StandardReadable): """ High pressure X-ray cell, used to apply pressure or pressure jumps to a sample. @@ -89,12 +92,20 @@ def __init__( ) -> None: with self.add_children_as_readables(): ## Valves ## - self.valve1_state = epics_signal_r(PressureJumpCellValveState, prefix + "V1:STA") + self.valve1_state = epics_signal_r( + PressureJumpCellValveState, prefix + "V1:STA" + ) # V2 - valve manual control - self.valve3_state = epics_signal_r(PressureJumpCellValveState, prefix + "V3:STA") + self.valve3_state = epics_signal_r( + PressureJumpCellValveState, prefix + "V3:STA" + ) # V4 - valve manual control - self.valve5_state = epics_signal_r(PressureJumpCellFastValveState, prefix + "V5:STA") - self.valve6_state = epics_signal_r(PressureJumpCellFastValveState, prefix + "V6:STA") + self.valve5_state = epics_signal_r( + PressureJumpCellFastValveState, prefix + "V5:STA" + ) + self.valve6_state = epics_signal_r( + PressureJumpCellFastValveState, prefix + "V6:STA" + ) # V7 - valve manual control # V8 - valve manual control @@ -103,8 +114,12 @@ def __init__( ## Pump ## self.pump_position = epics_signal_r(float, prefix + "POS") - self.pump_forward_limit = epics_signal_r(PressureJumpCellLimitSwitch, prefix + "D74IN1") - self.pump_backward_limit = epics_signal_r(PressureJumpCellLimitSwitch, prefix + "D74IN0") + self.pump_forward_limit = epics_signal_r( + PressureJumpCellLimitSwitch, prefix + "D74IN1" + ) + self.pump_backward_limit = epics_signal_r( + PressureJumpCellLimitSwitch, prefix + "D74IN0" + ) self.pump_motor_direction = epics_signal_r( PressureJumpCellPumpMotorDirection, prefix + "MTRDIR" ) diff --git a/tests/devices/unit_tests/test_pressure_jump_cell.py b/tests/devices/unit_tests/test_pressure_jump_cell.py index 208bb0391b..b71149397c 100644 --- a/tests/devices/unit_tests/test_pressure_jump_cell.py +++ b/tests/devices/unit_tests/test_pressure_jump_cell.py @@ -6,13 +6,14 @@ from dodal.devices.pressure_jump_cell import ( PressureJumpCell, PressureJumpCellBusyStatus, + PressureJumpCellFastValveState, + PressureJumpCellLimitSwitch, PressureJumpCellPumpMotorDirection, PressureJumpCellTimerState, PressureJumpCellValveState, - PressureJumpCellFastValveState, - PressureJumpCellLimitSwitch ) + @pytest.fixture async def pressurejumpcell() -> PressureJumpCell: async with DeviceCollector(mock=True): @@ -26,18 +27,25 @@ async def test_reading_pjumpcell_includes_read_fields( ): set_mock_value(pressurejumpcell.valve1_state, PressureJumpCellValveState.CLOSED) set_mock_value(pressurejumpcell.valve3_state, PressureJumpCellValveState.OPEN) - set_mock_value(pressurejumpcell.valve5_state, PressureJumpCellFastValveState.CLOSED_ARMED) - set_mock_value(pressurejumpcell.valve6_state, PressureJumpCellFastValveState.OPEN_ARMED) + set_mock_value( + pressurejumpcell.valve5_state, PressureJumpCellFastValveState.CLOSED_ARMED + ) + set_mock_value( + pressurejumpcell.valve6_state, PressureJumpCellFastValveState.OPEN_ARMED + ) set_mock_value(pressurejumpcell.cell_temperature, 12.3) - set_mock_value(pressurejumpcell.pump_position, 100) + set_mock_value(pressurejumpcell.pump_position, 100) set_mock_value(pressurejumpcell.pump_forward_limit, PressureJumpCellLimitSwitch.OFF) set_mock_value(pressurejumpcell.pump_backward_limit, PressureJumpCellLimitSwitch.ON) - set_mock_value(pressurejumpcell.pump_motor_direction, PressureJumpCellPumpMotorDirection.FORWARD) + set_mock_value( + pressurejumpcell.pump_motor_direction, + PressureJumpCellPumpMotorDirection.FORWARD, + ) set_mock_value(pressurejumpcell.pump_speed_rbv, 100) set_mock_value(pressurejumpcell.pressuretransducer1_omron_pressure, 1001) set_mock_value(pressurejumpcell.pressuretransducer1_omron_voltage, 2.51) set_mock_value(pressurejumpcell.pressuretransducer1_beckhoff_pressure, 1001.1) - set_mock_value(pressurejumpcell.pressuretransducer1_beckhoff_voltage, 2.51) + set_mock_value(pressurejumpcell.pressuretransducer1_beckhoff_voltage, 2.51) set_mock_value(pressurejumpcell.pressuretransducer2_omron_pressure, 1002) set_mock_value(pressurejumpcell.pressuretransducer2_omron_voltage, 2.52) set_mock_value(pressurejumpcell.pressuretransducer2_beckhoff_pressure, 1002.2) @@ -50,11 +58,10 @@ async def test_reading_pjumpcell_includes_read_fields( set_mock_value(pressurejumpcell.control_timer, PressureJumpCellTimerState.COUNTDOWN) set_mock_value(pressurejumpcell.control_counter, 123) set_mock_value(pressurejumpcell.control_script_status, "ABC") - set_mock_value(pressurejumpcell.control_routine, "CDE") + set_mock_value(pressurejumpcell.control_routine, "CDE") set_mock_value(pressurejumpcell.control_state, "EFG") set_mock_value(pressurejumpcell.control_iteration, 456) - await assert_reading( pressurejumpcell, { @@ -205,4 +212,3 @@ async def test_reading_pjumpcell_includes_read_fields( }, }, ) - From 4dee191bb83c611187b5ee29ac790bcec7e7cc43 Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Thu, 25 Jul 2024 14:24:54 +0100 Subject: [PATCH 05/25] Restructured pressure jump cell device to be by component. --- src/dodal/devices/pressure_jump_cell.py | 129 ++++++----- .../unit_tests/test_pressure_jump_cell.py | 205 ++++++++++++------ 2 files changed, 218 insertions(+), 116 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 4fcee8fce3..c1448d0a96 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -78,20 +78,9 @@ class PressureJumpCellLimitSwitch: ON = "On" -class PressureJumpCell(StandardReadable): - """ - High pressure X-ray cell, used to apply pressure or pressure jumps to a sample. - """ - - def __init__( - self, - prefix: str = "", - adc1_prefix: str = "", - adc2_prefix: str = "", - name: str = "", - ) -> None: +class PressureJumpCellControlValves(StandardReadable): + def __init__(self, prefix: str, name: str = "") -> None: with self.add_children_as_readables(): - ## Valves ## self.valve1_state = epics_signal_r( PressureJumpCellValveState, prefix + "V1:STA" ) @@ -109,10 +98,33 @@ def __init__( # V7 - valve manual control # V8 - valve manual control - ## Cell ## - self.cell_temperature = epics_signal_r(float, prefix + "TEMP") + with self.add_children_as_readables(ConfigSignal): + self.valve1_open = epics_signal_rw(bool, prefix + "V1:OPENSEQ") + self.valve1_control = epics_signal_rw( + PressureJumpCellValveControlRequest, prefix + "V1:CON" + ) + + self.valve3_open = epics_signal_rw(bool, prefix + "V3:OPENSEQ") + self.valve3_control = epics_signal_rw( + PressureJumpCellValveControlRequest, prefix + "V3:CON" + ) + + self.valve5_open = epics_signal_rw(bool, prefix + "V5:OPENSEQ") + self.valve5_control = epics_signal_rw( + PressureJumpCellValveControlRequest, prefix + "V5:CON" + ) + + self.valve6_open = epics_signal_rw(bool, prefix + "V6:OPENSEQ") + self.valve6_control = epics_signal_rw( + PressureJumpCellValveControlRequest, prefix + "V6CON" + ) + + super().__init__(name) + - ## Pump ## +class PressureJumpCellPump(StandardReadable): + def __init__(self, prefix: str, name: str = "") -> None: + with self.add_children_as_readables(): self.pump_position = epics_signal_r(float, prefix + "POS") self.pump_forward_limit = epics_signal_r( PressureJumpCellLimitSwitch, prefix + "D74IN1" @@ -125,6 +137,25 @@ def __init__( ) self.pump_speed_rbv = epics_signal_r(int, prefix + "MSPEED_RBV") + with self.add_children_as_readables(ConfigSignal): + self.pump_mode = epics_signal_rw( + PressureJumpCellPumpMode, prefix + "SP:AUTO" + ) + self.pump_speed = epics_signal_rw(float, prefix + "MSPEED") + self.pump_move_forward = epics_signal_rw(bool, prefix + "M1:FORW") + self.pump_move_backward = epics_signal_rw(bool, prefix + "M1:BACKW") + self.pump_move_backward = epics_signal_rw( + PressureJumpCellPumpMotorControlRequest, prefix + "M1:CON" + ) + + super().__init__(name) + + +class PressureJumpCellPressureTransducers(StandardReadable): + def __init__( + self, prefix: str, name: str = "", adc1_prefix: str = "", adc2_prefix: str = "" + ) -> None: + with self.add_children_as_readables(): ## Pressure Transducer 1 ## self.pressuretransducer1_omron_pressure = epics_signal_r( float, prefix + "PP1:PRES" @@ -167,7 +198,12 @@ def __init__( float, adc1_prefix + "CH1" ) - ## Control Common ## + super().__init__(name) + + +class PressureJumpCellController(StandardReadable): + def __init__(self, prefix: str, name: str = "") -> None: + with self.add_children_as_readables(): self.control_gotobusy = epics_signal_r( PressureJumpCellBusyStatus, prefix + "CTRL:GOTOBUSY" ) @@ -183,44 +219,10 @@ def __init__( self.control_iteration = epics_signal_r(int, prefix + "CTRL:ITER") with self.add_children_as_readables(ConfigSignal): - ## Valves ## - self.valve1_open = epics_signal_rw(bool, prefix + "V1:OPENSEQ") - self.valve1_control = epics_signal_rw( - PressureJumpCellValveControlRequest, prefix + "V1:CON" - ) - - self.valve3_open = epics_signal_rw(bool, prefix + "V3:OPENSEQ") - self.valve3_control = epics_signal_rw( - PressureJumpCellValveControlRequest, prefix + "V3:CON" - ) - - self.valve5_open = epics_signal_rw(bool, prefix + "V5:OPENSEQ") - self.valve5_control = epics_signal_rw( - PressureJumpCellValveControlRequest, prefix + "V5:CON" - ) - - self.valve6_open = epics_signal_rw(bool, prefix + "V6:OPENSEQ") - self.valve6_control = epics_signal_rw( - PressureJumpCellValveControlRequest, prefix + "V6CON" - ) - - ## Pump ## - self.pump_mode = epics_signal_rw( - PressureJumpCellPumpMode, prefix + "SP:AUTO" - ) - self.pump_speed = epics_signal_rw(float, prefix + "MSPEED") - self.pump_move_forward = epics_signal_rw(bool, prefix + "M1:FORW") - self.pump_move_backward = epics_signal_rw(bool, prefix + "M1:BACKW") - self.pump_move_backward = epics_signal_rw( - PressureJumpCellPumpMotorControlRequest, prefix + "M1:CON" - ) - - ## Control Common ## self.control_stop = epics_signal_rw( PressureJumpCellStopValue, prefix + "CTRL:STOP" ) - ## Control Pressure ## self.control_target_pressure = epics_signal_rw( float, prefix + "CTRL:TARGET" ) @@ -237,3 +239,28 @@ def __init__( self.control_jump_set = epics_signal_rw(bool, prefix + "CTRL:SETJUMP") super().__init__(name) + + +class PressureJumpCell(StandardReadable): + """ + High pressure X-ray cell, used to apply pressure or pressure jumps to a sample. + """ + + def __init__( + self, + prefix: str = "", + adc1_prefix: str = "", + adc2_prefix: str = "", + name: str = "", + ): + self.valves = PressureJumpCellControlValves(prefix, name) + self.pump = PressureJumpCellPump(prefix, name) + self.transducers = PressureJumpCellPressureTransducers( + prefix, name, adc1_prefix, adc2_prefix + ) + self.controller = PressureJumpCellController(prefix, name) + + with self.add_children_as_readables(): + self.cell_temperature = epics_signal_r(float, prefix + "TEMP") + + super().__init__(name) diff --git a/tests/devices/unit_tests/test_pressure_jump_cell.py b/tests/devices/unit_tests/test_pressure_jump_cell.py index b71149397c..f16a389797 100644 --- a/tests/devices/unit_tests/test_pressure_jump_cell.py +++ b/tests/devices/unit_tests/test_pressure_jump_cell.py @@ -22,193 +22,268 @@ async def pressurejumpcell() -> PressureJumpCell: return pjump -async def test_reading_pjumpcell_includes_read_fields( +async def test_reading_pjumpcell_includes_read_fields_valves( pressurejumpcell: PressureJumpCell, ): - set_mock_value(pressurejumpcell.valve1_state, PressureJumpCellValveState.CLOSED) - set_mock_value(pressurejumpcell.valve3_state, PressureJumpCellValveState.OPEN) set_mock_value( - pressurejumpcell.valve5_state, PressureJumpCellFastValveState.CLOSED_ARMED + pressurejumpcell.valves.valve1_state, PressureJumpCellValveState.CLOSED ) set_mock_value( - pressurejumpcell.valve6_state, PressureJumpCellFastValveState.OPEN_ARMED + pressurejumpcell.valves.valve3_state, PressureJumpCellValveState.OPEN ) - set_mock_value(pressurejumpcell.cell_temperature, 12.3) - set_mock_value(pressurejumpcell.pump_position, 100) - set_mock_value(pressurejumpcell.pump_forward_limit, PressureJumpCellLimitSwitch.OFF) - set_mock_value(pressurejumpcell.pump_backward_limit, PressureJumpCellLimitSwitch.ON) set_mock_value( - pressurejumpcell.pump_motor_direction, - PressureJumpCellPumpMotorDirection.FORWARD, + pressurejumpcell.valves.valve5_state, + PressureJumpCellFastValveState.CLOSED_ARMED, + ) + set_mock_value( + pressurejumpcell.valves.valve6_state, PressureJumpCellFastValveState.OPEN_ARMED ) - set_mock_value(pressurejumpcell.pump_speed_rbv, 100) - set_mock_value(pressurejumpcell.pressuretransducer1_omron_pressure, 1001) - set_mock_value(pressurejumpcell.pressuretransducer1_omron_voltage, 2.51) - set_mock_value(pressurejumpcell.pressuretransducer1_beckhoff_pressure, 1001.1) - set_mock_value(pressurejumpcell.pressuretransducer1_beckhoff_voltage, 2.51) - set_mock_value(pressurejumpcell.pressuretransducer2_omron_pressure, 1002) - set_mock_value(pressurejumpcell.pressuretransducer2_omron_voltage, 2.52) - set_mock_value(pressurejumpcell.pressuretransducer2_beckhoff_pressure, 1002.2) - set_mock_value(pressurejumpcell.pressuretransducer2_beckhoff_voltage, 2.52) - set_mock_value(pressurejumpcell.pressuretransducer3_omron_pressure, 1003) - set_mock_value(pressurejumpcell.pressuretransducer3_omron_voltage, 2.53) - set_mock_value(pressurejumpcell.pressuretransducer3_beckhoff_pressure, 1003.3) - set_mock_value(pressurejumpcell.pressuretransducer3_beckhoff_voltage, 2.53) - set_mock_value(pressurejumpcell.control_gotobusy, PressureJumpCellBusyStatus.IDLE) - set_mock_value(pressurejumpcell.control_timer, PressureJumpCellTimerState.COUNTDOWN) - set_mock_value(pressurejumpcell.control_counter, 123) - set_mock_value(pressurejumpcell.control_script_status, "ABC") - set_mock_value(pressurejumpcell.control_routine, "CDE") - set_mock_value(pressurejumpcell.control_state, "EFG") - set_mock_value(pressurejumpcell.control_iteration, 456) await assert_reading( - pressurejumpcell, + pressurejumpcell.valves, { - "pjump-valve1_state": { + "pjump-valves-valve1_state": { "value": PressureJumpCellValveState.CLOSED, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-valve3_state": { + "pjump-valves-valve3_state": { "value": PressureJumpCellValveState.OPEN, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-valve5_state": { + "pjump-valves-valve5_state": { "value": PressureJumpCellFastValveState.CLOSED_ARMED, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-valve6_state": { + "pjump-valves-valve6_state": { "value": PressureJumpCellFastValveState.OPEN_ARMED, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-cell_temperature": { - "value": 12.3, - "timestamp": ANY, - "alarm_severity": 0, - }, - "pjump-pump_position": { + }, + ) + + +async def test_reading_pjumpcell_includes_read_fields_pump( + pressurejumpcell: PressureJumpCell, +): + set_mock_value(pressurejumpcell.pump.pump_position, 100) + set_mock_value( + pressurejumpcell.pump.pump_forward_limit, PressureJumpCellLimitSwitch.OFF + ) + set_mock_value( + pressurejumpcell.pump.pump_backward_limit, PressureJumpCellLimitSwitch.ON + ) + set_mock_value( + pressurejumpcell.pump.pump_motor_direction, + PressureJumpCellPumpMotorDirection.FORWARD, + ) + set_mock_value(pressurejumpcell.pump.pump_speed_rbv, 100) + + await assert_reading( + pressurejumpcell.pump, + { + "pjump-pump-pump_position": { "value": 100, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pump_forward_limit": { + "pjump-pump-pump_forward_limit": { "value": PressureJumpCellLimitSwitch.OFF, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pump_backward_limit": { + "pjump-pump-pump_backward_limit": { "value": PressureJumpCellLimitSwitch.ON, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pump_motor_direction": { + "pjump-pump-pump_motor_direction": { "value": PressureJumpCellPumpMotorDirection.FORWARD, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pump_speed_rbv": { + "pjump-pump-pump_speed_rbv": { "value": 100, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer1_omron_pressure": { + }, + ) + + +async def test_reading_pjumpcell_includes_read_fields_transducers( + pressurejumpcell: PressureJumpCell, +): + set_mock_value( + pressurejumpcell.transducers.pressuretransducer1_omron_pressure, 1001 + ) + set_mock_value(pressurejumpcell.transducers.pressuretransducer1_omron_voltage, 2.51) + set_mock_value( + pressurejumpcell.transducers.pressuretransducer1_beckhoff_pressure, 1001.1 + ) + set_mock_value( + pressurejumpcell.transducers.pressuretransducer1_beckhoff_voltage, 2.51 + ) + set_mock_value( + pressurejumpcell.transducers.pressuretransducer2_omron_pressure, 1002 + ) + set_mock_value(pressurejumpcell.transducers.pressuretransducer2_omron_voltage, 2.52) + set_mock_value( + pressurejumpcell.transducers.pressuretransducer2_beckhoff_pressure, 1002.2 + ) + set_mock_value( + pressurejumpcell.transducers.pressuretransducer2_beckhoff_voltage, 2.52 + ) + set_mock_value( + pressurejumpcell.transducers.pressuretransducer3_omron_pressure, 1003 + ) + set_mock_value(pressurejumpcell.transducers.pressuretransducer3_omron_voltage, 2.53) + set_mock_value( + pressurejumpcell.transducers.pressuretransducer3_beckhoff_pressure, 1003.3 + ) + set_mock_value( + pressurejumpcell.transducers.pressuretransducer3_beckhoff_voltage, 2.53 + ) + + await assert_reading( + pressurejumpcell.transducers, + { + "pjump-transducers-pressuretransducer1_omron_pressure": { "value": 1001, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer1_omron_voltage": { + "pjump-transducers-pressuretransducer1_omron_voltage": { "value": 2.51, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer1_beckhoff_pressure": { + "pjump-transducers-pressuretransducer1_beckhoff_pressure": { "value": 1001.1, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer1_beckhoff_voltage": { + "pjump-transducers-pressuretransducer1_beckhoff_voltage": { "value": 2.51, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer2_omron_pressure": { + "pjump-transducers-pressuretransducer2_omron_pressure": { "value": 1002, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer2_omron_voltage": { + "pjump-transducers-pressuretransducer2_omron_voltage": { "value": 2.52, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer2_beckhoff_pressure": { + "pjump-transducers-pressuretransducer2_beckhoff_pressure": { "value": 1002.2, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer2_beckhoff_voltage": { + "pjump-transducers-pressuretransducer2_beckhoff_voltage": { "value": 2.52, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer3_omron_pressure": { + "pjump-transducers-pressuretransducer3_omron_pressure": { "value": 1003, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer3_omron_voltage": { + "pjump-transducers-pressuretransducer3_omron_voltage": { "value": 2.53, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer3_beckhoff_pressure": { + "pjump-transducers-pressuretransducer3_beckhoff_pressure": { "value": 1003.3, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressuretransducer3_beckhoff_voltage": { + "pjump-transducers-pressuretransducer3_beckhoff_voltage": { "value": 2.53, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-control_gotobusy": { + }, + ) + + +async def test_reading_pjumpcell_includes_read_fields_controller( + pressurejumpcell: PressureJumpCell, +): + set_mock_value( + pressurejumpcell.controller.control_gotobusy, PressureJumpCellBusyStatus.IDLE + ) + set_mock_value( + pressurejumpcell.controller.control_timer, PressureJumpCellTimerState.COUNTDOWN + ) + set_mock_value(pressurejumpcell.controller.control_counter, 123) + set_mock_value(pressurejumpcell.controller.control_script_status, "ABC") + set_mock_value(pressurejumpcell.controller.control_routine, "CDE") + set_mock_value(pressurejumpcell.controller.control_state, "EFG") + set_mock_value(pressurejumpcell.controller.control_iteration, 456) + + await assert_reading( + pressurejumpcell.controller, + { + "pjump-controller-control_gotobusy": { "value": PressureJumpCellBusyStatus.IDLE, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-control_timer": { + "pjump-controller-control_timer": { "value": PressureJumpCellTimerState.COUNTDOWN, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-control_counter": { + "pjump-controller-control_counter": { "value": 123, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-control_script_status": { + "pjump-controller-control_script_status": { "value": "ABC", "timestamp": ANY, "alarm_severity": 0, }, - "pjump-control_routine": { + "pjump-controller-control_routine": { "value": "CDE", "timestamp": ANY, "alarm_severity": 0, }, - "pjump-control_state": { + "pjump-controller-control_state": { "value": "EFG", "timestamp": ANY, "alarm_severity": 0, }, - "pjump-control_iteration": { + "pjump-controller-control_iteration": { "value": 456, "timestamp": ANY, "alarm_severity": 0, }, }, ) + + +async def test_reading_pjumpcell_includes_read_fields( + pressurejumpcell: PressureJumpCell, +): + set_mock_value(pressurejumpcell.cell_temperature, 12.3) + + await assert_reading( + pressurejumpcell, + { + "pjump-cell_temperature": { + "value": 12.3, + "timestamp": ANY, + "alarm_severity": 0, + }, + }, + ) From e6e38f655823d36c5b819be67273809c9fea6a0f Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Thu, 25 Jul 2024 16:16:51 +0100 Subject: [PATCH 06/25] Define pressure jump adc numbering in constructor. --- src/dodal/beamlines/p38.py | 6 +++--- src/dodal/devices/pressure_jump_cell.py | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/dodal/beamlines/p38.py b/src/dodal/beamlines/p38.py index f743dbf388..416abd974b 100644 --- a/src/dodal/beamlines/p38.py +++ b/src/dodal/beamlines/p38.py @@ -327,9 +327,9 @@ def high_pressure_xray_cell( return device_instantiation( PressureJumpCell, "high_pressure_xray_cell", - "-EA-HPXC-01:", + "-EA", wait_for_connection, fake_with_ophyd_sim, - adc1_prefix=f"{BeamlinePrefix(BL).beamline_prefix}-EA-ADC-01:", - adc2_prefix=f"{BeamlinePrefix(BL).beamline_prefix}-EA-ADC-02:", + cell_prefix="-HPXC-01:", + adc_prefix="-ADC", ) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index c1448d0a96..40b3196b4d 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -249,18 +249,23 @@ class PressureJumpCell(StandardReadable): def __init__( self, prefix: str = "", - adc1_prefix: str = "", - adc2_prefix: str = "", + cell_prefix: str = "", + adc_prefix: str = "", name: str = "", ): - self.valves = PressureJumpCellControlValves(prefix, name) - self.pump = PressureJumpCellPump(prefix, name) + cellFullPrefix = prefix + cell_prefix + adcFullPrefix = prefix + adc_prefix + + self.valves = PressureJumpCellControlValves(cellFullPrefix, name) + self.pump = PressureJumpCellPump(cellFullPrefix, name) self.transducers = PressureJumpCellPressureTransducers( - prefix, name, adc1_prefix, adc2_prefix + cellFullPrefix, name, + adc1_prefix= adcFullPrefix + "-01:", + adc2_prefix= adcFullPrefix + "-02:", ) - self.controller = PressureJumpCellController(prefix, name) + self.controller = PressureJumpCellController(cellFullPrefix, name) with self.add_children_as_readables(): - self.cell_temperature = epics_signal_r(float, prefix + "TEMP") + self.cell_temperature = epics_signal_r(float, cellFullPrefix + "TEMP") super().__init__(name) From 49eae382427dcdbb148a42a6179fb17dfc6ebcce Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Mon, 29 Jul 2024 14:32:09 +0100 Subject: [PATCH 07/25] Minor formatting fixes. --- src/dodal/devices/pressure_jump_cell.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 40b3196b4d..6c4a1c1755 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -253,15 +253,16 @@ def __init__( adc_prefix: str = "", name: str = "", ): - cellFullPrefix = prefix + cell_prefix + cellFullPrefix = prefix + cell_prefix adcFullPrefix = prefix + adc_prefix self.valves = PressureJumpCellControlValves(cellFullPrefix, name) self.pump = PressureJumpCellPump(cellFullPrefix, name) self.transducers = PressureJumpCellPressureTransducers( - cellFullPrefix, name, - adc1_prefix= adcFullPrefix + "-01:", - adc2_prefix= adcFullPrefix + "-02:", + cellFullPrefix, + name, + adc1_prefix=adcFullPrefix + "-01:", + adc2_prefix=adcFullPrefix + "-02:", ) self.controller = PressureJumpCellController(cellFullPrefix, name) From 8b2707df10b6d1d90f82a75ff433a8792231f50c Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Mon, 29 Jul 2024 14:52:40 +0100 Subject: [PATCH 08/25] Pressure jump cell corrected enums extend str and Enum --- src/dodal/devices/pressure_jump_cell.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 6c4a1c1755..66bbea79c1 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -1,29 +1,30 @@ +from enum import Enum from ophyd_async.core import ConfigSignal, StandardReadable from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw -class PressureJumpCellPumpMode: +class PressureJumpCellPumpMode(str, Enum): MANUAL = "Manual" AUTO_PRESSURE = "Auto Pressure" AUTO_POSITION = "Auto Position" -class PressureJumpCellBusyStatus: +class PressureJumpCellBusyStatus(str, Enum): IDLE = "Idle" BUSY = "Busy" -class PressureJumpCellTimerState: +class PressureJumpCellTimerState(str, Enum): TIMEOUT = "TIMEOUT" COUNTDOWN = "COUNTDOWN" -class PressureJumpCellStopValue: +class PressureJumpCellStopValue(str, Enum): CONTINUE = "CONTINUE" STOP = "STOP" -class PressureJumpCellValveControlRequest: +class PressureJumpCellValveControlRequest(str, Enum): OPEN = "Open" CLOSE = "Close" RESET = "Reset" @@ -34,7 +35,7 @@ class PressureJumpCellValveControlRequest: NONE2 = "" -class PressureJumpCellPumpMotorControlRequest: +class PressureJumpCellPumpMotorControlRequest(str, Enum): ENABLE = "Enable" DISABLE = "Disable" RESET = "Reset" @@ -42,7 +43,7 @@ class PressureJumpCellPumpMotorControlRequest: REVERSE = "Reverse" -class PressureJumpCellPumpMotorDirection: +class PressureJumpCellPumpMotorDirection(str, Enum): ZERO = "0" FORWARD = "Forward" REVERSE = "Reverse" @@ -53,7 +54,7 @@ class PressureJumpCellPumpMotorDirection: SEVEN = "7" -class PressureJumpCellValveState: +class PressureJumpCellValveState(str, Enum): FAULT = "Fault" OPEN = "Open" OPENING = "Opening" @@ -63,7 +64,7 @@ class PressureJumpCellValveState: NONE6 = "" -class PressureJumpCellFastValveState: +class PressureJumpCellFastValveState(str, Enum): FAULT = "Fault" OPEN = "Open" OPEN_ARMED = "Open Armed" @@ -73,7 +74,7 @@ class PressureJumpCellFastValveState: NONE6 = "" -class PressureJumpCellLimitSwitch: +class PressureJumpCellLimitSwitch(str, Enum): OFF = "Off" ON = "On" From 8ff69a776d5b3bbcadb78e93d491d5370f374a20 Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Mon, 29 Jul 2024 15:05:05 +0100 Subject: [PATCH 09/25] Pressure jump cell removed empty enum values. --- src/dodal/devices/pressure_jump_cell.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 66bbea79c1..5779cce344 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -1,4 +1,5 @@ from enum import Enum + from ophyd_async.core import ConfigSignal, StandardReadable from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw @@ -30,9 +31,6 @@ class PressureJumpCellValveControlRequest(str, Enum): RESET = "Reset" ARM = "Arm" DISARM = "Disarm" - # TODO the nones may not be required but FVST and SXST set - NONE1 = "" - NONE2 = "" class PressureJumpCellPumpMotorControlRequest(str, Enum): @@ -60,8 +58,6 @@ class PressureJumpCellValveState(str, Enum): OPENING = "Opening" CLOSED = "Closed" CLOSING = "Closing" - NONE5 = "" - NONE6 = "" class PressureJumpCellFastValveState(str, Enum): @@ -71,7 +67,6 @@ class PressureJumpCellFastValveState(str, Enum): CLOSED = "Closed" CLOSED_ARMED = "Closed Armed" NONE5 = "Unused" - NONE6 = "" class PressureJumpCellLimitSwitch(str, Enum): From fc209874db1978847670d7fd9c3fc96985c5af37 Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Tue, 30 Jul 2024 12:53:45 +0100 Subject: [PATCH 10/25] use devicevector --- src/dodal/devices/pressure_jump_cell.py | 132 +++++++++++------------- 1 file changed, 63 insertions(+), 69 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 5779cce344..f39db9cb7e 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -1,6 +1,11 @@ from enum import Enum -from ophyd_async.core import ConfigSignal, StandardReadable +from ophyd_async.core import ( + ConfigSignal, + DeviceVector, + SignalR, + StandardReadable, +) from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw @@ -75,44 +80,51 @@ class PressureJumpCellLimitSwitch(str, Enum): class PressureJumpCellControlValves(StandardReadable): + """ + valves 2, 4, 7, 8 are not controlled by the IOC, + as they are under manual control. + """ + def __init__(self, prefix: str, name: str = "") -> None: with self.add_children_as_readables(): - self.valve1_state = epics_signal_r( - PressureJumpCellValveState, prefix + "V1:STA" - ) - # V2 - valve manual control - self.valve3_state = epics_signal_r( - PressureJumpCellValveState, prefix + "V3:STA" + self.valve_states: DeviceVector[SignalR[PressureJumpCellValveState]] = ( + DeviceVector( + { + i: epics_signal_r( + PressureJumpCellValveState, f"{prefix}V{i}:STA" + ) + for i in [1, 3] + } + ) ) - # V4 - valve manual control - self.valve5_state = epics_signal_r( - PressureJumpCellFastValveState, prefix + "V5:STA" + self.fast_valve_states: DeviceVector[ + SignalR[PressureJumpCellFastValveState] + ] = DeviceVector( + { + i: epics_signal_r( + PressureJumpCellFastValveState, f"{prefix}V{i}:STA" + ) + for i in [5, 6] + } ) - self.valve6_state = epics_signal_r( - PressureJumpCellFastValveState, prefix + "V6:STA" - ) - # V7 - valve manual control - # V8 - valve manual control with self.add_children_as_readables(ConfigSignal): - self.valve1_open = epics_signal_rw(bool, prefix + "V1:OPENSEQ") - self.valve1_control = epics_signal_rw( - PressureJumpCellValveControlRequest, prefix + "V1:CON" - ) - - self.valve3_open = epics_signal_rw(bool, prefix + "V3:OPENSEQ") - self.valve3_control = epics_signal_rw( - PressureJumpCellValveControlRequest, prefix + "V3:CON" + self.valves_open: DeviceVector[SignalR[bool]] = DeviceVector( + { + i: epics_signal_rw(bool, f"{prefix}V{i}:OPENSEQ") + for i in [1, 3, 5, 6] + } ) - self.valve5_open = epics_signal_rw(bool, prefix + "V5:OPENSEQ") - self.valve5_control = epics_signal_rw( - PressureJumpCellValveControlRequest, prefix + "V5:CON" - ) - - self.valve6_open = epics_signal_rw(bool, prefix + "V6:OPENSEQ") - self.valve6_control = epics_signal_rw( - PressureJumpCellValveControlRequest, prefix + "V6CON" + self.valve_control: DeviceVector[ + SignalR[PressureJumpCellValveControlRequest] + ] = DeviceVector( + { + i: epics_signal_rw( + PressureJumpCellValveControlRequest, f"{prefix}V{i}:CON" + ) + for i in [1, 3, 5, 6] + } ) super().__init__(name) @@ -147,51 +159,33 @@ def __init__(self, prefix: str, name: str = "") -> None: super().__init__(name) +class PressureJumpCellPressureTransducer(StandardReadable): + def __init__(self, prefix: str, name: str = "", adc_prefix: str = "") -> None: + with self.add_children_as_readables(): + self.omron_pressure = epics_signal_r(float, prefix + "PP:PRES") + self.omron_voltage = epics_signal_r(float, prefix + "PP:RAW") + self.beckhoff_pressure = epics_signal_r( + float, prefix + "STATP:MeanValue_RBV" + ) + self.beckhoff_voltage = epics_signal_r(float, adc_prefix + "CH1") + # todo this channel might be liable to change + + super().__init__(name) + + class PressureJumpCellPressureTransducers(StandardReadable): def __init__( self, prefix: str, name: str = "", adc1_prefix: str = "", adc2_prefix: str = "" ) -> None: with self.add_children_as_readables(): - ## Pressure Transducer 1 ## - self.pressuretransducer1_omron_pressure = epics_signal_r( - float, prefix + "PP1:PRES" - ) - self.pressuretransducer1_omron_voltage = epics_signal_r( - float, prefix + "PP1:RAW" - ) - self.pressuretransducer1_beckhoff_pressure = epics_signal_r( - float, prefix + "STATP1:MeanValue_RBV" - ) - self.pressuretransducer1_beckhoff_voltage = epics_signal_r( - float, adc2_prefix + "CH1" - ) - - ## Pressure Transducer 2 ## - self.pressuretransducer2_omron_pressure = epics_signal_r( - float, prefix + "PP2:PRES" - ) - self.pressuretransducer2_omron_voltage = epics_signal_r( - float, prefix + "PP2:RAW" - ) - self.pressuretransducer2_beckhoff_pressure = epics_signal_r( - float, prefix + "STATP2:MeanValue_RBV" - ) - self.pressuretransducer2_beckhoff_voltage = epics_signal_r( - float, adc1_prefix + "CH2" - ) - - ## Pressure Transducer 3 ## - self.pressuretransducer3_omron_pressure = epics_signal_r( - float, prefix + "PP3:PRES" - ) - self.pressuretransducer3_omron_voltage = epics_signal_r( - float, prefix + "PP3:RAW" + self.pressure_transducer_1 = PressureJumpCellPressureTransducer( + prefix + "PP1:", name="Pressure Transducer 1", adc_prefix=adc1_prefix ) - self.pressuretransducer3_beckhoff_pressure = epics_signal_r( - float, prefix + "STATP3:MeanValue_RBV" + self.pressure_transducer_2 = PressureJumpCellPressureTransducer( + prefix + "PP2:", name="Pressure Transducer 2", adc_prefix=adc2_prefix ) - self.pressuretransducer3_beckhoff_voltage = epics_signal_r( - float, adc1_prefix + "CH1" + self.pressure_transducer_3 = PressureJumpCellPressureTransducer( + prefix + "PP3:", name="Pressure Transducer 3", adc_prefix=adc1_prefix ) super().__init__(name) From 22106f11d37162b2b720fda2803da3a1eb5ced68 Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Tue, 30 Jul 2024 13:04:01 +0100 Subject: [PATCH 11/25] change names --- src/dodal/devices/pressure_jump_cell.py | 134 ++++++++---------- .../unit_tests/test_pressure_jump_cell.py | 62 ++++---- 2 files changed, 87 insertions(+), 109 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index f39db9cb7e..c2c1058365 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -9,28 +9,28 @@ from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw -class PressureJumpCellPumpMode(str, Enum): +class PumpState(str, Enum): MANUAL = "Manual" AUTO_PRESSURE = "Auto Pressure" AUTO_POSITION = "Auto Position" -class PressureJumpCellBusyStatus(str, Enum): +class BusyState(str, Enum): IDLE = "Idle" BUSY = "Busy" -class PressureJumpCellTimerState(str, Enum): +class TimerState(str, Enum): TIMEOUT = "TIMEOUT" COUNTDOWN = "COUNTDOWN" -class PressureJumpCellStopValue(str, Enum): +class StopState(str, Enum): CONTINUE = "CONTINUE" STOP = "STOP" -class PressureJumpCellValveControlRequest(str, Enum): +class ValveControlRequest(str, Enum): OPEN = "Open" CLOSE = "Close" RESET = "Reset" @@ -38,7 +38,7 @@ class PressureJumpCellValveControlRequest(str, Enum): DISARM = "Disarm" -class PressureJumpCellPumpMotorControlRequest(str, Enum): +class PumpMotorControlRequest(str, Enum): ENABLE = "Enable" DISABLE = "Disable" RESET = "Reset" @@ -46,7 +46,7 @@ class PressureJumpCellPumpMotorControlRequest(str, Enum): REVERSE = "Reverse" -class PressureJumpCellPumpMotorDirection(str, Enum): +class PumpMotorDirectionState(str, Enum): ZERO = "0" FORWARD = "Forward" REVERSE = "Reverse" @@ -57,7 +57,7 @@ class PressureJumpCellPumpMotorDirection(str, Enum): SEVEN = "7" -class PressureJumpCellValveState(str, Enum): +class ValveState(str, Enum): FAULT = "Fault" OPEN = "Open" OPENING = "Opening" @@ -65,7 +65,7 @@ class PressureJumpCellValveState(str, Enum): CLOSING = "Closing" -class PressureJumpCellFastValveState(str, Enum): +class FastValveState(str, Enum): FAULT = "Fault" OPEN = "Open" OPEN_ARMED = "Open Armed" @@ -74,12 +74,12 @@ class PressureJumpCellFastValveState(str, Enum): NONE5 = "Unused" -class PressureJumpCellLimitSwitch(str, Enum): +class LimitSwitchState(str, Enum): OFF = "Off" ON = "On" -class PressureJumpCellControlValves(StandardReadable): +class ControlValves(StandardReadable): """ valves 2, 4, 7, 8 are not controlled by the IOC, as they are under manual control. @@ -87,26 +87,17 @@ class PressureJumpCellControlValves(StandardReadable): def __init__(self, prefix: str, name: str = "") -> None: with self.add_children_as_readables(): - self.valve_states: DeviceVector[SignalR[PressureJumpCellValveState]] = ( + self.valve_states: DeviceVector[SignalR[ValveState]] = DeviceVector( + {i: epics_signal_r(ValveState, f"{prefix}V{i}:STA") for i in [1, 3]} + ) + self.fast_valve_states: DeviceVector[SignalR[FastValveState]] = ( DeviceVector( { - i: epics_signal_r( - PressureJumpCellValveState, f"{prefix}V{i}:STA" - ) - for i in [1, 3] + i: epics_signal_r(FastValveState, f"{prefix}V{i}:STA") + for i in [5, 6] } ) ) - self.fast_valve_states: DeviceVector[ - SignalR[PressureJumpCellFastValveState] - ] = DeviceVector( - { - i: epics_signal_r( - PressureJumpCellFastValveState, f"{prefix}V{i}:STA" - ) - for i in [5, 6] - } - ) with self.add_children_as_readables(ConfigSignal): self.valves_open: DeviceVector[SignalR[bool]] = DeviceVector( @@ -116,50 +107,50 @@ def __init__(self, prefix: str, name: str = "") -> None: } ) - self.valve_control: DeviceVector[ - SignalR[PressureJumpCellValveControlRequest] - ] = DeviceVector( - { - i: epics_signal_rw( - PressureJumpCellValveControlRequest, f"{prefix}V{i}:CON" - ) - for i in [1, 3, 5, 6] - } + self.valve_control: DeviceVector[SignalR[ValveControlRequest]] = ( + DeviceVector( + { + i: epics_signal_rw(ValveControlRequest, f"{prefix}V{i}:CON") + for i in [1, 3, 5, 6] + } + ) ) super().__init__(name) -class PressureJumpCellPump(StandardReadable): +class Pump(StandardReadable): def __init__(self, prefix: str, name: str = "") -> None: with self.add_children_as_readables(): self.pump_position = epics_signal_r(float, prefix + "POS") self.pump_forward_limit = epics_signal_r( - PressureJumpCellLimitSwitch, prefix + "D74IN1" + LimitSwitchState, prefix + "D74IN1" ) self.pump_backward_limit = epics_signal_r( - PressureJumpCellLimitSwitch, prefix + "D74IN0" + LimitSwitchState, prefix + "D74IN0" ) self.pump_motor_direction = epics_signal_r( - PressureJumpCellPumpMotorDirection, prefix + "MTRDIR" + PumpMotorDirectionState, prefix + "MTRDIR" ) self.pump_speed_rbv = epics_signal_r(int, prefix + "MSPEED_RBV") with self.add_children_as_readables(ConfigSignal): - self.pump_mode = epics_signal_rw( - PressureJumpCellPumpMode, prefix + "SP:AUTO" - ) + self.pump_mode = epics_signal_rw(PumpState, prefix + "SP:AUTO") self.pump_speed = epics_signal_rw(float, prefix + "MSPEED") self.pump_move_forward = epics_signal_rw(bool, prefix + "M1:FORW") self.pump_move_backward = epics_signal_rw(bool, prefix + "M1:BACKW") self.pump_move_backward = epics_signal_rw( - PressureJumpCellPumpMotorControlRequest, prefix + "M1:CON" + PumpMotorControlRequest, prefix + "M1:CON" ) super().__init__(name) -class PressureJumpCellPressureTransducer(StandardReadable): +class PressureTransducer(StandardReadable): + """ + todo does this do? + """ + def __init__(self, prefix: str, name: str = "", adc_prefix: str = "") -> None: with self.add_children_as_readables(): self.omron_pressure = epics_signal_r(float, prefix + "PP:PRES") @@ -173,18 +164,18 @@ def __init__(self, prefix: str, name: str = "", adc_prefix: str = "") -> None: super().__init__(name) -class PressureJumpCellPressureTransducers(StandardReadable): +class PressureTransducers(StandardReadable): def __init__( self, prefix: str, name: str = "", adc1_prefix: str = "", adc2_prefix: str = "" ) -> None: with self.add_children_as_readables(): - self.pressure_transducer_1 = PressureJumpCellPressureTransducer( + self.pressure_transducer_1 = PressureTransducer( prefix + "PP1:", name="Pressure Transducer 1", adc_prefix=adc1_prefix ) - self.pressure_transducer_2 = PressureJumpCellPressureTransducer( + self.pressure_transducer_2 = PressureTransducer( prefix + "PP2:", name="Pressure Transducer 2", adc_prefix=adc2_prefix ) - self.pressure_transducer_3 = PressureJumpCellPressureTransducer( + self.pressure_transducer_3 = PressureTransducer( prefix + "PP3:", name="Pressure Transducer 3", adc_prefix=adc1_prefix ) @@ -194,14 +185,9 @@ def __init__( class PressureJumpCellController(StandardReadable): def __init__(self, prefix: str, name: str = "") -> None: with self.add_children_as_readables(): - self.control_gotobusy = epics_signal_r( - PressureJumpCellBusyStatus, prefix + "CTRL:GOTOBUSY" - ) + self.control_gotobusy = epics_signal_r(BusyState, prefix + "CTRL:GOTOBUSY") - ## Control Pressure ## - self.control_timer = epics_signal_r( - PressureJumpCellTimerState, prefix + "CTRL:TIMER" - ) + self.control_timer = epics_signal_r(TimerState, prefix + "CTRL:TIMER") self.control_counter = epics_signal_r(float, prefix + "CTRL:COUNTER") self.control_script_status = epics_signal_r(str, prefix + "CTRL:RESULT") self.control_routine = epics_signal_r(str, prefix + "CTRL:METHOD") @@ -209,9 +195,7 @@ def __init__(self, prefix: str, name: str = "") -> None: self.control_iteration = epics_signal_r(int, prefix + "CTRL:ITER") with self.add_children_as_readables(ConfigSignal): - self.control_stop = epics_signal_rw( - PressureJumpCellStopValue, prefix + "CTRL:STOP" - ) + self.control_stop = epics_signal_rw(StopState, prefix + "CTRL:STOP") self.control_target_pressure = epics_signal_rw( float, prefix + "CTRL:TARGET" @@ -219,7 +203,7 @@ def __init__(self, prefix: str, name: str = "") -> None: self.control_timeout = epics_signal_rw(float, prefix + "CTRL:TIMER.HIGH") self.control_go = epics_signal_rw(bool, prefix + "CTRL:GO") - ## Control Jump ## + ## Jump logic ## self.control_jump_from_pressure = epics_signal_rw( float, prefix + "CTRL:JUMPF" ) @@ -243,20 +227,28 @@ def __init__( adc_prefix: str = "", name: str = "", ): - cellFullPrefix = prefix + cell_prefix - adcFullPrefix = prefix + adc_prefix - - self.valves = PressureJumpCellControlValves(cellFullPrefix, name) - self.pump = PressureJumpCellPump(cellFullPrefix, name) - self.transducers = PressureJumpCellPressureTransducers( - cellFullPrefix, - name, - adc1_prefix=adcFullPrefix + "-01:", - adc2_prefix=adcFullPrefix + "-02:", + self.valves = ControlValves(f"{prefix}{cell_prefix}", name) + self.pump = Pump(f"{prefix}{cell_prefix}", name) + + self.pressure_transducer_1 = PressureTransducer( + prefix + "PP1:", + name="Pressure Transducer 1", + adc_prefix=f"{prefix}{adc_prefix}-01:", + ) + self.pressure_transducer_2 = PressureTransducer( + prefix + "PP2:", + name="Pressure Transducer 2", + adc_prefix=f"{prefix}{adc_prefix}-02:", ) - self.controller = PressureJumpCellController(cellFullPrefix, name) + self.pressure_transducer_3 = PressureTransducer( + prefix + "PP3:", + name="Pressure Transducer 3", + adc_prefix=f"{prefix}{adc_prefix}-01:", + ) + + self.controller = PressureJumpCellController(f"{prefix}{cell_prefix}", name) with self.add_children_as_readables(): - self.cell_temperature = epics_signal_r(float, cellFullPrefix + "TEMP") + self.cell_temperature = epics_signal_r(float, f"{prefix}{cell_prefix}TEMP") super().__init__(name) diff --git a/tests/devices/unit_tests/test_pressure_jump_cell.py b/tests/devices/unit_tests/test_pressure_jump_cell.py index f16a389797..a772271c9a 100644 --- a/tests/devices/unit_tests/test_pressure_jump_cell.py +++ b/tests/devices/unit_tests/test_pressure_jump_cell.py @@ -4,13 +4,13 @@ from ophyd_async.core import DeviceCollector, assert_reading, set_mock_value from dodal.devices.pressure_jump_cell import ( + BusyState, + FastValveState, + LimitSwitchState, PressureJumpCell, - PressureJumpCellBusyStatus, - PressureJumpCellFastValveState, - PressureJumpCellLimitSwitch, - PressureJumpCellPumpMotorDirection, - PressureJumpCellTimerState, - PressureJumpCellValveState, + PumpMotorDirectionState, + TimerState, + ValveState, ) @@ -25,40 +25,34 @@ async def pressurejumpcell() -> PressureJumpCell: async def test_reading_pjumpcell_includes_read_fields_valves( pressurejumpcell: PressureJumpCell, ): - set_mock_value( - pressurejumpcell.valves.valve1_state, PressureJumpCellValveState.CLOSED - ) - set_mock_value( - pressurejumpcell.valves.valve3_state, PressureJumpCellValveState.OPEN - ) + set_mock_value(pressurejumpcell.valves.valve1_state, ValveState.CLOSED) + set_mock_value(pressurejumpcell.valves.valve3_state, ValveState.OPEN) set_mock_value( pressurejumpcell.valves.valve5_state, - PressureJumpCellFastValveState.CLOSED_ARMED, - ) - set_mock_value( - pressurejumpcell.valves.valve6_state, PressureJumpCellFastValveState.OPEN_ARMED + FastValveState.CLOSED_ARMED, ) + set_mock_value(pressurejumpcell.valves.valve6_state, FastValveState.OPEN_ARMED) await assert_reading( pressurejumpcell.valves, { "pjump-valves-valve1_state": { - "value": PressureJumpCellValveState.CLOSED, + "value": ValveState.CLOSED, "timestamp": ANY, "alarm_severity": 0, }, "pjump-valves-valve3_state": { - "value": PressureJumpCellValveState.OPEN, + "value": ValveState.OPEN, "timestamp": ANY, "alarm_severity": 0, }, "pjump-valves-valve5_state": { - "value": PressureJumpCellFastValveState.CLOSED_ARMED, + "value": FastValveState.CLOSED_ARMED, "timestamp": ANY, "alarm_severity": 0, }, "pjump-valves-valve6_state": { - "value": PressureJumpCellFastValveState.OPEN_ARMED, + "value": FastValveState.OPEN_ARMED, "timestamp": ANY, "alarm_severity": 0, }, @@ -70,15 +64,11 @@ async def test_reading_pjumpcell_includes_read_fields_pump( pressurejumpcell: PressureJumpCell, ): set_mock_value(pressurejumpcell.pump.pump_position, 100) - set_mock_value( - pressurejumpcell.pump.pump_forward_limit, PressureJumpCellLimitSwitch.OFF - ) - set_mock_value( - pressurejumpcell.pump.pump_backward_limit, PressureJumpCellLimitSwitch.ON - ) + set_mock_value(pressurejumpcell.pump.pump_forward_limit, LimitSwitchState.OFF) + set_mock_value(pressurejumpcell.pump.pump_backward_limit, LimitSwitchState.ON) set_mock_value( pressurejumpcell.pump.pump_motor_direction, - PressureJumpCellPumpMotorDirection.FORWARD, + PumpMotorDirectionState.FORWARD, ) set_mock_value(pressurejumpcell.pump.pump_speed_rbv, 100) @@ -91,17 +81,17 @@ async def test_reading_pjumpcell_includes_read_fields_pump( "alarm_severity": 0, }, "pjump-pump-pump_forward_limit": { - "value": PressureJumpCellLimitSwitch.OFF, + "value": LimitSwitchState.OFF, "timestamp": ANY, "alarm_severity": 0, }, "pjump-pump-pump_backward_limit": { - "value": PressureJumpCellLimitSwitch.ON, + "value": LimitSwitchState.ON, "timestamp": ANY, "alarm_severity": 0, }, "pjump-pump-pump_motor_direction": { - "value": PressureJumpCellPumpMotorDirection.FORWARD, + "value": PumpMotorDirectionState.FORWARD, "timestamp": ANY, "alarm_severity": 0, }, @@ -218,12 +208,8 @@ async def test_reading_pjumpcell_includes_read_fields_transducers( async def test_reading_pjumpcell_includes_read_fields_controller( pressurejumpcell: PressureJumpCell, ): - set_mock_value( - pressurejumpcell.controller.control_gotobusy, PressureJumpCellBusyStatus.IDLE - ) - set_mock_value( - pressurejumpcell.controller.control_timer, PressureJumpCellTimerState.COUNTDOWN - ) + set_mock_value(pressurejumpcell.controller.control_gotobusy, BusyState.IDLE) + set_mock_value(pressurejumpcell.controller.control_timer, TimerState.COUNTDOWN) set_mock_value(pressurejumpcell.controller.control_counter, 123) set_mock_value(pressurejumpcell.controller.control_script_status, "ABC") set_mock_value(pressurejumpcell.controller.control_routine, "CDE") @@ -234,12 +220,12 @@ async def test_reading_pjumpcell_includes_read_fields_controller( pressurejumpcell.controller, { "pjump-controller-control_gotobusy": { - "value": PressureJumpCellBusyStatus.IDLE, + "value": BusyState.IDLE, "timestamp": ANY, "alarm_severity": 0, }, "pjump-controller-control_timer": { - "value": PressureJumpCellTimerState.COUNTDOWN, + "value": TimerState.COUNTDOWN, "timestamp": ANY, "alarm_severity": 0, }, From 054db167d9d6876208a40dfbe0f135cc0f97df0e Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Tue, 30 Jul 2024 13:21:32 +0100 Subject: [PATCH 12/25] adapt the tests to the changes --- src/dodal/devices/pressure_jump_cell.py | 4 +- .../unit_tests/test_pressure_jump_cell.py | 142 +++++++++--------- 2 files changed, 70 insertions(+), 76 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index c2c1058365..41fc923c6b 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -79,7 +79,7 @@ class LimitSwitchState(str, Enum): ON = "On" -class ControlValves(StandardReadable): +class AllValvesControl(StandardReadable): """ valves 2, 4, 7, 8 are not controlled by the IOC, as they are under manual control. @@ -227,7 +227,7 @@ def __init__( adc_prefix: str = "", name: str = "", ): - self.valves = ControlValves(f"{prefix}{cell_prefix}", name) + self.all_valves_control = AllValvesControl(f"{prefix}{cell_prefix}", name) self.pump = Pump(f"{prefix}{cell_prefix}", name) self.pressure_transducer_1 = PressureTransducer( diff --git a/tests/devices/unit_tests/test_pressure_jump_cell.py b/tests/devices/unit_tests/test_pressure_jump_cell.py index a772271c9a..7dfc0def28 100644 --- a/tests/devices/unit_tests/test_pressure_jump_cell.py +++ b/tests/devices/unit_tests/test_pressure_jump_cell.py @@ -15,7 +15,7 @@ @pytest.fixture -async def pressurejumpcell() -> PressureJumpCell: +async def cell() -> PressureJumpCell: async with DeviceCollector(mock=True): pjump = PressureJumpCell("DEMO-PJUMPCELL-01:") @@ -23,35 +23,37 @@ async def pressurejumpcell() -> PressureJumpCell: async def test_reading_pjumpcell_includes_read_fields_valves( - pressurejumpcell: PressureJumpCell, + cell: PressureJumpCell, ): - set_mock_value(pressurejumpcell.valves.valve1_state, ValveState.CLOSED) - set_mock_value(pressurejumpcell.valves.valve3_state, ValveState.OPEN) + set_mock_value(cell.all_valves_control.valve_states[1], ValveState.CLOSED) + set_mock_value(cell.all_valves_control.valve_states[3], ValveState.OPEN) set_mock_value( - pressurejumpcell.valves.valve5_state, + cell.all_valves_control.fast_valve_states[5], FastValveState.CLOSED_ARMED, ) - set_mock_value(pressurejumpcell.valves.valve6_state, FastValveState.OPEN_ARMED) + set_mock_value( + cell.all_valves_control.fast_valve_states[6], FastValveState.OPEN_ARMED + ) await assert_reading( - pressurejumpcell.valves, + cell.all_valves_control, { - "pjump-valves-valve1_state": { + "pjump-all_valves_control-valve_states-1": { "value": ValveState.CLOSED, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-valves-valve3_state": { + "pjump-all_valves_control-valve_states-3": { "value": ValveState.OPEN, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-valves-valve5_state": { + "pjump-all_valves_control-fast_valve_states-5": { "value": FastValveState.CLOSED_ARMED, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-valves-valve6_state": { + "pjump-all_valves_control-fast_valve_states-6": { "value": FastValveState.OPEN_ARMED, "timestamp": ANY, "alarm_severity": 0, @@ -61,19 +63,19 @@ async def test_reading_pjumpcell_includes_read_fields_valves( async def test_reading_pjumpcell_includes_read_fields_pump( - pressurejumpcell: PressureJumpCell, + cell: PressureJumpCell, ): - set_mock_value(pressurejumpcell.pump.pump_position, 100) - set_mock_value(pressurejumpcell.pump.pump_forward_limit, LimitSwitchState.OFF) - set_mock_value(pressurejumpcell.pump.pump_backward_limit, LimitSwitchState.ON) + set_mock_value(cell.pump.pump_position, 100) + set_mock_value(cell.pump.pump_forward_limit, LimitSwitchState.OFF) + set_mock_value(cell.pump.pump_backward_limit, LimitSwitchState.ON) set_mock_value( - pressurejumpcell.pump.pump_motor_direction, + cell.pump.pump_motor_direction, PumpMotorDirectionState.FORWARD, ) - set_mock_value(pressurejumpcell.pump.pump_speed_rbv, 100) + set_mock_value(cell.pump.pump_speed_rbv, 100) await assert_reading( - pressurejumpcell.pump, + cell.pump, { "pjump-pump-pump_position": { "value": 100, @@ -105,98 +107,90 @@ async def test_reading_pjumpcell_includes_read_fields_pump( async def test_reading_pjumpcell_includes_read_fields_transducers( - pressurejumpcell: PressureJumpCell, + cell: PressureJumpCell, ): - set_mock_value( - pressurejumpcell.transducers.pressuretransducer1_omron_pressure, 1001 - ) - set_mock_value(pressurejumpcell.transducers.pressuretransducer1_omron_voltage, 2.51) - set_mock_value( - pressurejumpcell.transducers.pressuretransducer1_beckhoff_pressure, 1001.1 - ) - set_mock_value( - pressurejumpcell.transducers.pressuretransducer1_beckhoff_voltage, 2.51 - ) - set_mock_value( - pressurejumpcell.transducers.pressuretransducer2_omron_pressure, 1002 - ) - set_mock_value(pressurejumpcell.transducers.pressuretransducer2_omron_voltage, 2.52) - set_mock_value( - pressurejumpcell.transducers.pressuretransducer2_beckhoff_pressure, 1002.2 - ) - set_mock_value( - pressurejumpcell.transducers.pressuretransducer2_beckhoff_voltage, 2.52 - ) - set_mock_value( - pressurejumpcell.transducers.pressuretransducer3_omron_pressure, 1003 - ) - set_mock_value(pressurejumpcell.transducers.pressuretransducer3_omron_voltage, 2.53) - set_mock_value( - pressurejumpcell.transducers.pressuretransducer3_beckhoff_pressure, 1003.3 - ) - set_mock_value( - pressurejumpcell.transducers.pressuretransducer3_beckhoff_voltage, 2.53 - ) + set_mock_value(cell.pressure_transducer_1.omron_pressure, 1001) + set_mock_value(cell.pressure_transducer_1.omron_voltage, 2.51) + set_mock_value(cell.pressure_transducer_1.beckhoff_pressure, 1001.1) + set_mock_value(cell.pressure_transducer_1.beckhoff_voltage, 2.51) + set_mock_value(cell.pressure_transducer_2.omron_pressure, 1002) + set_mock_value(cell.pressure_transducer_2.omron_voltage, 2.52) + set_mock_value(cell.pressure_transducer_2.beckhoff_pressure, 1002.2) + set_mock_value(cell.pressure_transducer_2.beckhoff_voltage, 2.52) + set_mock_value(cell.pressure_transducer_3.omron_pressure, 1003) + set_mock_value(cell.pressure_transducer_3.omron_voltage, 2.53) + set_mock_value(cell.pressure_transducer_3.beckhoff_pressure, 1003.3) + set_mock_value(cell.pressure_transducer_3.beckhoff_voltage, 2.53) await assert_reading( - pressurejumpcell.transducers, + cell.pressure_transducer_1, { - "pjump-transducers-pressuretransducer1_omron_pressure": { + "pjump-pressure_transducer_1-omron_pressure": { "value": 1001, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-transducers-pressuretransducer1_omron_voltage": { + "pjump-pressure_transducer_1-omron_voltage": { "value": 2.51, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-transducers-pressuretransducer1_beckhoff_pressure": { + "pjump-pressure_transducer_1-beckhoff_pressure": { "value": 1001.1, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-transducers-pressuretransducer1_beckhoff_voltage": { + "pjump-pressure_transducer_1-beckhoff_voltage": { "value": 2.51, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-transducers-pressuretransducer2_omron_pressure": { + }, + ) + await assert_reading( + cell.pressure_transducer_2, + { + "pjump-pressure_transducer_2-omron_pressure": { "value": 1002, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-transducers-pressuretransducer2_omron_voltage": { + "pjump-pressure_transducer_2-omron_voltage": { "value": 2.52, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-transducers-pressuretransducer2_beckhoff_pressure": { + "pjump-pressure_transducer_2-beckhoff_pressure": { "value": 1002.2, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-transducers-pressuretransducer2_beckhoff_voltage": { + "pjump-pressure_transducer_2-beckhoff_voltage": { "value": 2.52, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-transducers-pressuretransducer3_omron_pressure": { + }, + ) + await assert_reading( + cell.pressure_transducer_3, + { + "pjump-pressure_transducer_3-omron_pressure": { "value": 1003, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-transducers-pressuretransducer3_omron_voltage": { + "pjump-pressure_transducer_3-omron_voltage": { "value": 2.53, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-transducers-pressuretransducer3_beckhoff_pressure": { + "pjump-pressure_transducer_3-beckhoff_pressure": { "value": 1003.3, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-transducers-pressuretransducer3_beckhoff_voltage": { + "pjump-pressure_transducer_3-beckhoff_voltage": { "value": 2.53, "timestamp": ANY, "alarm_severity": 0, @@ -206,18 +200,18 @@ async def test_reading_pjumpcell_includes_read_fields_transducers( async def test_reading_pjumpcell_includes_read_fields_controller( - pressurejumpcell: PressureJumpCell, + cell: PressureJumpCell, ): - set_mock_value(pressurejumpcell.controller.control_gotobusy, BusyState.IDLE) - set_mock_value(pressurejumpcell.controller.control_timer, TimerState.COUNTDOWN) - set_mock_value(pressurejumpcell.controller.control_counter, 123) - set_mock_value(pressurejumpcell.controller.control_script_status, "ABC") - set_mock_value(pressurejumpcell.controller.control_routine, "CDE") - set_mock_value(pressurejumpcell.controller.control_state, "EFG") - set_mock_value(pressurejumpcell.controller.control_iteration, 456) + set_mock_value(cell.controller.control_gotobusy, BusyState.IDLE) + set_mock_value(cell.controller.control_timer, TimerState.COUNTDOWN) + set_mock_value(cell.controller.control_counter, 123) + set_mock_value(cell.controller.control_script_status, "ABC") + set_mock_value(cell.controller.control_routine, "CDE") + set_mock_value(cell.controller.control_state, "EFG") + set_mock_value(cell.controller.control_iteration, 456) await assert_reading( - pressurejumpcell.controller, + cell.controller, { "pjump-controller-control_gotobusy": { "value": BusyState.IDLE, @@ -259,12 +253,12 @@ async def test_reading_pjumpcell_includes_read_fields_controller( async def test_reading_pjumpcell_includes_read_fields( - pressurejumpcell: PressureJumpCell, + cell: PressureJumpCell, ): - set_mock_value(pressurejumpcell.cell_temperature, 12.3) + set_mock_value(cell.cell_temperature, 12.3) await assert_reading( - pressurejumpcell, + cell, { "pjump-cell_temperature": { "value": 12.3, From 07afb58cac0e7f0025b9bce0e3a10d2c3a75a65b Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Tue, 30 Jul 2024 12:33:52 +0000 Subject: [PATCH 13/25] forgot to delete the not used device --- src/dodal/devices/pressure_jump_cell.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 41fc923c6b..90fcfbecef 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -164,24 +164,6 @@ def __init__(self, prefix: str, name: str = "", adc_prefix: str = "") -> None: super().__init__(name) -class PressureTransducers(StandardReadable): - def __init__( - self, prefix: str, name: str = "", adc1_prefix: str = "", adc2_prefix: str = "" - ) -> None: - with self.add_children_as_readables(): - self.pressure_transducer_1 = PressureTransducer( - prefix + "PP1:", name="Pressure Transducer 1", adc_prefix=adc1_prefix - ) - self.pressure_transducer_2 = PressureTransducer( - prefix + "PP2:", name="Pressure Transducer 2", adc_prefix=adc2_prefix - ) - self.pressure_transducer_3 = PressureTransducer( - prefix + "PP3:", name="Pressure Transducer 3", adc_prefix=adc1_prefix - ) - - super().__init__(name) - - class PressureJumpCellController(StandardReadable): def __init__(self, prefix: str, name: str = "") -> None: with self.add_children_as_readables(): From cc7639e7d74269aad69fd4314ca16f31f9f04c79 Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Tue, 30 Jul 2024 17:13:44 +0100 Subject: [PATCH 14/25] Cell connected following testing in P38 --- src/dodal/devices/pressure_jump_cell.py | 70 +++++++++++++++++-------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 90fcfbecef..2dfc621da7 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -29,14 +29,17 @@ class StopState(str, Enum): CONTINUE = "CONTINUE" STOP = "STOP" - -class ValveControlRequest(str, Enum): +class FastValveControlRequest(str, Enum): OPEN = "Open" CLOSE = "Close" RESET = "Reset" ARM = "Arm" DISARM = "Disarm" +class ValveControlRequest(str, Enum): + OPEN = "Open" + CLOSE = "Close" + RESET = "Reset" class PumpMotorControlRequest(str, Enum): ENABLE = "Enable" @@ -47,14 +50,9 @@ class PumpMotorControlRequest(str, Enum): class PumpMotorDirectionState(str, Enum): - ZERO = "0" + EMPTY = "" FORWARD = "Forward" REVERSE = "Reverse" - THREE = "3" - FOUR = "4" - FIVE = "5" - SIX = "6" - SEVEN = "7" class ValveState(str, Enum): @@ -100,9 +98,9 @@ def __init__(self, prefix: str, name: str = "") -> None: ) with self.add_children_as_readables(ConfigSignal): - self.valves_open: DeviceVector[SignalR[bool]] = DeviceVector( + self.valves_open: DeviceVector[SignalR[int]] = DeviceVector( { - i: epics_signal_rw(bool, f"{prefix}V{i}:OPENSEQ") + i: epics_signal_rw(int, f"{prefix}V{i}:OPENSEQ") for i in [1, 3, 5, 6] } ) @@ -111,7 +109,16 @@ def __init__(self, prefix: str, name: str = "") -> None: DeviceVector( { i: epics_signal_rw(ValveControlRequest, f"{prefix}V{i}:CON") - for i in [1, 3, 5, 6] + for i in [1, 3] + } + ) + ) + + self.fast_valve_control: DeviceVector[SignalR[FastValveControlRequest]] = ( + DeviceVector( + { + i: epics_signal_rw(FastValveControlRequest, f"{prefix}V{i}:CON") + for i in [ 5, 6] } ) ) @@ -132,12 +139,12 @@ def __init__(self, prefix: str, name: str = "") -> None: self.pump_motor_direction = epics_signal_r( PumpMotorDirectionState, prefix + "MTRDIR" ) - self.pump_speed_rbv = epics_signal_r(int, prefix + "MSPEED_RBV") + self.pump_speed_rbv = epics_signal_r(float, prefix + "MSPEED_RBV") with self.add_children_as_readables(ConfigSignal): self.pump_mode = epics_signal_rw(PumpState, prefix + "SP:AUTO") self.pump_speed = epics_signal_rw(float, prefix + "MSPEED") - self.pump_move_forward = epics_signal_rw(bool, prefix + "M1:FORW") + self.pump_move_forward = epics_signal_rw(int, prefix + "M1:FORW") self.pump_move_backward = epics_signal_rw(bool, prefix + "M1:BACKW") self.pump_move_backward = epics_signal_rw( PumpMotorControlRequest, prefix + "M1:CON" @@ -148,15 +155,15 @@ def __init__(self, prefix: str, name: str = "") -> None: class PressureTransducer(StandardReadable): """ - todo does this do? + reads pressure """ - def __init__(self, prefix: str, name: str = "", adc_prefix: str = "") -> None: + def __init__(self, prefix: str, number: int, name: str = "", adc_prefix: str = "" ) -> None: with self.add_children_as_readables(): - self.omron_pressure = epics_signal_r(float, prefix + "PP:PRES") - self.omron_voltage = epics_signal_r(float, prefix + "PP:RAW") + self.omron_pressure = epics_signal_r(float, f"{prefix}PP{number}:PRES") + self.omron_voltage = epics_signal_r(float, f"{prefix}PP{number}:RAW") self.beckhoff_pressure = epics_signal_r( - float, prefix + "STATP:MeanValue_RBV" + float, f"{prefix}STATP{number}:MeanValue_RBV" ) self.beckhoff_voltage = epics_signal_r(float, adc_prefix + "CH1") # todo this channel might be liable to change @@ -174,7 +181,7 @@ def __init__(self, prefix: str, name: str = "") -> None: self.control_script_status = epics_signal_r(str, prefix + "CTRL:RESULT") self.control_routine = epics_signal_r(str, prefix + "CTRL:METHOD") self.control_state = epics_signal_r(str, prefix + "CTRL:STATE") - self.control_iteration = epics_signal_r(int, prefix + "CTRL:ITER") + self.control_iteration = epics_signal_r(float, prefix + "CTRL:ITER") with self.add_children_as_readables(ConfigSignal): self.control_stop = epics_signal_rw(StopState, prefix + "CTRL:STOP") @@ -197,6 +204,22 @@ def __init__(self, prefix: str, name: str = "") -> None: super().__init__(name) +# h_pressure_xray_cell: NotConnected: +# coros: NotConnected: +# pressure_transducer_1: NotConnected: +# omron_pressure: NotConnected: ca://-HPXC-01:PP1:PRES +# omron_voltage: NotConnected: ca://-HPXC-01:PP1:RAW +# beckhoff_pressure: NotConnected: ca://-HPXC-01:PP1:STATP:MeanValue_RBV +# pressure_transducer_2: NotConnected: +# omron_pressure: NotConnected: ca://-HPXC-01:PP2:PRES +# omron_voltage: NotConnected: ca://-HPXC-01:PP2:RAW +# beckhoff_pressure: NotConnected: ca://-HPXC-01:PP2:STATP:MeanValue_RBV +# pressure_transducer_3: NotConnected: +# omron_pressure: NotConnected: ca://-HPXC-01:PP3:PRES +# omron_voltage: NotConnected: ca://-HPXC-01:PP3:RAW +# beckhoff_pressure: NotConnected: ca://-HPXC-01:PP3:STATP:MeanValue_RBV + + class PressureJumpCell(StandardReadable): """ High pressure X-ray cell, used to apply pressure or pressure jumps to a sample. @@ -213,19 +236,22 @@ def __init__( self.pump = Pump(f"{prefix}{cell_prefix}", name) self.pressure_transducer_1 = PressureTransducer( - prefix + "PP1:", + prefix=f"{prefix}{cell_prefix}", name="Pressure Transducer 1", adc_prefix=f"{prefix}{adc_prefix}-01:", + number=1 ) self.pressure_transducer_2 = PressureTransducer( - prefix + "PP2:", + prefix=f"{prefix}{cell_prefix}", name="Pressure Transducer 2", adc_prefix=f"{prefix}{adc_prefix}-02:", + number=2 ) self.pressure_transducer_3 = PressureTransducer( - prefix + "PP3:", + prefix=f"{prefix}{cell_prefix}", name="Pressure Transducer 3", adc_prefix=f"{prefix}{adc_prefix}-01:", + number=3 ) self.controller = PressureJumpCellController(f"{prefix}{cell_prefix}", name) From e7c498013c21d152b81356621772c0254957964d Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Thu, 1 Aug 2024 16:49:24 +0100 Subject: [PATCH 15/25] respond to feedback --- src/dodal/devices/pressure_jump_cell.py | 68 +++++++++---------------- 1 file changed, 23 insertions(+), 45 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 2dfc621da7..80738984f2 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -29,18 +29,21 @@ class StopState(str, Enum): CONTINUE = "CONTINUE" STOP = "STOP" -class FastValveControlRequest(str, Enum): + +class FastValveControlRequest(str, Enum): OPEN = "Open" CLOSE = "Close" RESET = "Reset" ARM = "Arm" DISARM = "Disarm" + class ValveControlRequest(str, Enum): OPEN = "Open" CLOSE = "Close" RESET = "Reset" + class PumpMotorControlRequest(str, Enum): ENABLE = "Enable" DISABLE = "Disable" @@ -50,7 +53,7 @@ class PumpMotorControlRequest(str, Enum): class PumpMotorDirectionState(str, Enum): - EMPTY = "" + EMPTY = "" FORWARD = "Forward" REVERSE = "Reverse" @@ -99,10 +102,7 @@ def __init__(self, prefix: str, name: str = "") -> None: with self.add_children_as_readables(ConfigSignal): self.valves_open: DeviceVector[SignalR[int]] = DeviceVector( - { - i: epics_signal_rw(int, f"{prefix}V{i}:OPENSEQ") - for i in [1, 3, 5, 6] - } + {i: epics_signal_rw(int, f"{prefix}V{i}:OPENSEQ") for i in [1, 3, 5, 6]} ) self.valve_control: DeviceVector[SignalR[ValveControlRequest]] = ( @@ -118,7 +118,7 @@ def __init__(self, prefix: str, name: str = "") -> None: DeviceVector( { i: epics_signal_rw(FastValveControlRequest, f"{prefix}V{i}:CON") - for i in [ 5, 6] + for i in [5, 6] } ) ) @@ -146,7 +146,7 @@ def __init__(self, prefix: str, name: str = "") -> None: self.pump_speed = epics_signal_rw(float, prefix + "MSPEED") self.pump_move_forward = epics_signal_rw(int, prefix + "M1:FORW") self.pump_move_backward = epics_signal_rw(bool, prefix + "M1:BACKW") - self.pump_move_backward = epics_signal_rw( + self.pump_connection = epics_signal_rw( PumpMotorControlRequest, prefix + "M1:CON" ) @@ -155,10 +155,12 @@ def __init__(self, prefix: str, name: str = "") -> None: class PressureTransducer(StandardReadable): """ - reads pressure + reads pressure """ - def __init__(self, prefix: str, number: int, name: str = "", adc_prefix: str = "" ) -> None: + def __init__( + self, prefix: str, number: int, name: str = "", adc_prefix: str = "" + ) -> None: with self.add_children_as_readables(): self.omron_pressure = epics_signal_r(float, f"{prefix}PP{number}:PRES") self.omron_voltage = epics_signal_r(float, f"{prefix}PP{number}:RAW") @@ -204,22 +206,6 @@ def __init__(self, prefix: str, name: str = "") -> None: super().__init__(name) -# h_pressure_xray_cell: NotConnected: -# coros: NotConnected: -# pressure_transducer_1: NotConnected: -# omron_pressure: NotConnected: ca://-HPXC-01:PP1:PRES -# omron_voltage: NotConnected: ca://-HPXC-01:PP1:RAW -# beckhoff_pressure: NotConnected: ca://-HPXC-01:PP1:STATP:MeanValue_RBV -# pressure_transducer_2: NotConnected: -# omron_pressure: NotConnected: ca://-HPXC-01:PP2:PRES -# omron_voltage: NotConnected: ca://-HPXC-01:PP2:RAW -# beckhoff_pressure: NotConnected: ca://-HPXC-01:PP2:STATP:MeanValue_RBV -# pressure_transducer_3: NotConnected: -# omron_pressure: NotConnected: ca://-HPXC-01:PP3:PRES -# omron_voltage: NotConnected: ca://-HPXC-01:PP3:RAW -# beckhoff_pressure: NotConnected: ca://-HPXC-01:PP3:STATP:MeanValue_RBV - - class PressureJumpCell(StandardReadable): """ High pressure X-ray cell, used to apply pressure or pressure jumps to a sample. @@ -235,28 +221,20 @@ def __init__( self.all_valves_control = AllValvesControl(f"{prefix}{cell_prefix}", name) self.pump = Pump(f"{prefix}{cell_prefix}", name) - self.pressure_transducer_1 = PressureTransducer( - prefix=f"{prefix}{cell_prefix}", - name="Pressure Transducer 1", - adc_prefix=f"{prefix}{adc_prefix}-01:", - number=1 - ) - self.pressure_transducer_2 = PressureTransducer( - prefix=f"{prefix}{cell_prefix}", - name="Pressure Transducer 2", - adc_prefix=f"{prefix}{adc_prefix}-02:", - number=2 - ) - self.pressure_transducer_3 = PressureTransducer( - prefix=f"{prefix}{cell_prefix}", - name="Pressure Transducer 3", - adc_prefix=f"{prefix}{adc_prefix}-01:", - number=3 - ) - self.controller = PressureJumpCellController(f"{prefix}{cell_prefix}", name) with self.add_children_as_readables(): + self.pressure_transducers: DeviceVector[PressureTransducer] = DeviceVector( + { + i: PressureTransducer( + prefix=f"{prefix}{cell_prefix}", + number=i, + adc_prefix=f"{prefix}{adc_prefix}-0{i}:", + ) + for i in [1, 2, 3] + } + ) + self.cell_temperature = epics_signal_r(float, f"{prefix}{cell_prefix}TEMP") super().__init__(name) From 1cdf74b6d31b9a3784583ba5dadf2bc388a981e2 Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Fri, 16 Aug 2024 16:20:51 +0100 Subject: [PATCH 16/25] fix test --- .../unit_tests/test_pressure_jump_cell.py | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/tests/devices/unit_tests/test_pressure_jump_cell.py b/tests/devices/unit_tests/test_pressure_jump_cell.py index 7dfc0def28..c4c60de260 100644 --- a/tests/devices/unit_tests/test_pressure_jump_cell.py +++ b/tests/devices/unit_tests/test_pressure_jump_cell.py @@ -109,38 +109,40 @@ async def test_reading_pjumpcell_includes_read_fields_pump( async def test_reading_pjumpcell_includes_read_fields_transducers( cell: PressureJumpCell, ): - set_mock_value(cell.pressure_transducer_1.omron_pressure, 1001) - set_mock_value(cell.pressure_transducer_1.omron_voltage, 2.51) - set_mock_value(cell.pressure_transducer_1.beckhoff_pressure, 1001.1) - set_mock_value(cell.pressure_transducer_1.beckhoff_voltage, 2.51) - set_mock_value(cell.pressure_transducer_2.omron_pressure, 1002) - set_mock_value(cell.pressure_transducer_2.omron_voltage, 2.52) - set_mock_value(cell.pressure_transducer_2.beckhoff_pressure, 1002.2) - set_mock_value(cell.pressure_transducer_2.beckhoff_voltage, 2.52) - set_mock_value(cell.pressure_transducer_3.omron_pressure, 1003) - set_mock_value(cell.pressure_transducer_3.omron_voltage, 2.53) - set_mock_value(cell.pressure_transducer_3.beckhoff_pressure, 1003.3) - set_mock_value(cell.pressure_transducer_3.beckhoff_voltage, 2.53) + set_mock_value(cell.pressure_transducers[1].omron_pressure, 1001) + set_mock_value(cell.pressure_transducers[1].omron_voltage, 2.51) + set_mock_value(cell.pressure_transducers[1].beckhoff_pressure, 1001.1) + set_mock_value(cell.pressure_transducers[1].beckhoff_voltage, 2.51) + + set_mock_value(cell.pressure_transducers[2].omron_pressure, 1002) + set_mock_value(cell.pressure_transducers[2].omron_voltage, 2.52) + set_mock_value(cell.pressure_transducers[2].beckhoff_pressure, 1002.2) + set_mock_value(cell.pressure_transducers[2].beckhoff_voltage, 2.52) + + set_mock_value(cell.pressure_transducers[3].omron_pressure, 1003) + set_mock_value(cell.pressure_transducers[3].omron_voltage, 2.53) + set_mock_value(cell.pressure_transducers[3].beckhoff_pressure, 1003.3) + set_mock_value(cell.pressure_transducers[3].beckhoff_voltage, 2.53) await assert_reading( - cell.pressure_transducer_1, + cell.pressure_transducers[1], { - "pjump-pressure_transducer_1-omron_pressure": { + "pjump-pressure_transducers-1-omron_pressure": { "value": 1001, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressure_transducer_1-omron_voltage": { + "pjump-pressure_transducers-1-omron_voltage": { "value": 2.51, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressure_transducer_1-beckhoff_pressure": { + "pjump-pressure_transducers-1-beckhoff_pressure": { "value": 1001.1, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressure_transducer_1-beckhoff_voltage": { + "pjump-pressure_transducers-1-beckhoff_voltage": { "value": 2.51, "timestamp": ANY, "alarm_severity": 0, @@ -148,24 +150,24 @@ async def test_reading_pjumpcell_includes_read_fields_transducers( }, ) await assert_reading( - cell.pressure_transducer_2, + cell.pressure_transducers[2], { - "pjump-pressure_transducer_2-omron_pressure": { + "pjump-pressure_transducers-2-omron_pressure": { "value": 1002, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressure_transducer_2-omron_voltage": { + "pjump-pressure_transducers-2-omron_voltage": { "value": 2.52, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressure_transducer_2-beckhoff_pressure": { + "pjump-pressure_transducers-2-beckhoff_pressure": { "value": 1002.2, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressure_transducer_2-beckhoff_voltage": { + "pjump-pressure_transducers-2-beckhoff_voltage": { "value": 2.52, "timestamp": ANY, "alarm_severity": 0, @@ -173,24 +175,24 @@ async def test_reading_pjumpcell_includes_read_fields_transducers( }, ) await assert_reading( - cell.pressure_transducer_3, + cell.pressure_transducers[3], { - "pjump-pressure_transducer_3-omron_pressure": { + "pjump-pressure_transducers-3-omron_pressure": { "value": 1003, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressure_transducer_3-omron_voltage": { + "pjump-pressure_transducers-3-omron_voltage": { "value": 2.53, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressure_transducer_3-beckhoff_pressure": { + "pjump-pressure_transducers-3-beckhoff_pressure": { "value": 1003.3, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pressure_transducer_3-beckhoff_voltage": { + "pjump-pressure_transducers-3-beckhoff_voltage": { "value": 2.53, "timestamp": ANY, "alarm_severity": 0, @@ -258,7 +260,7 @@ async def test_reading_pjumpcell_includes_read_fields( set_mock_value(cell.cell_temperature, 12.3) await assert_reading( - cell, + cell.cell_temperature, { "pjump-cell_temperature": { "value": 12.3, From f0a94f633fe803a6340129ddc3f0980640aafb81 Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Wed, 21 Aug 2024 14:58:47 +0100 Subject: [PATCH 17/25] pressure jump cell ready reviewed --- src/dodal/devices/pressure_jump_cell.py | 144 +++++++++--------- .../unit_tests/test_pressure_jump_cell.py | 2 +- 2 files changed, 72 insertions(+), 74 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 80738984f2..70944b37fb 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -1,9 +1,14 @@ +import asyncio +from dataclasses import dataclass from enum import Enum +from bluesky.protocols import HasName, Movable from ophyd_async.core import ( + AsyncStatus, ConfigSignal, DeviceVector, SignalR, + SignalRW, StandardReadable, ) from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw @@ -72,7 +77,7 @@ class FastValveState(str, Enum): OPEN_ARMED = "Open Armed" CLOSED = "Closed" CLOSED_ARMED = "Closed Armed" - NONE5 = "Unused" + NONE = "Unused" class LimitSwitchState(str, Enum): @@ -80,7 +85,15 @@ class LimitSwitchState(str, Enum): ON = "On" -class AllValvesControl(StandardReadable): +@dataclass +class AllValvesControlState: + valve_1: ValveControlRequest | None = None + valve_3: ValveControlRequest | None = None + valve_5: FastValveControlRequest | None = None + valve_6: FastValveControlRequest | None = None + + +class AllValvesControl(StandardReadable, Movable): """ valves 2, 4, 7, 8 are not controlled by the IOC, as they are under manual control. @@ -100,64 +113,61 @@ def __init__(self, prefix: str, name: str = "") -> None: ) ) - with self.add_children_as_readables(ConfigSignal): - self.valves_open: DeviceVector[SignalR[int]] = DeviceVector( - {i: epics_signal_rw(int, f"{prefix}V{i}:OPENSEQ") for i in [1, 3, 5, 6]} - ) - - self.valve_control: DeviceVector[SignalR[ValveControlRequest]] = ( - DeviceVector( - { - i: epics_signal_rw(ValveControlRequest, f"{prefix}V{i}:CON") - for i in [1, 3] - } - ) + self.fast_valve_control: DeviceVector[SignalRW[FastValveControlRequest]] = ( + DeviceVector( + { + i: epics_signal_rw(FastValveControlRequest, f"{prefix}V{i}:CON") + for i in [5, 6] + } ) + ) - self.fast_valve_control: DeviceVector[SignalR[FastValveControlRequest]] = ( - DeviceVector( - { - i: epics_signal_rw(FastValveControlRequest, f"{prefix}V{i}:CON") - for i in [5, 6] - } - ) - ) + self.valve_control: DeviceVector[SignalRW[ValveControlRequest]] = DeviceVector( + { + i: epics_signal_rw(ValveControlRequest, f"{prefix}V{i}:CON") + for i in [1, 3] + } + ) super().__init__(name) + async def set_valve( + self, valve: int, value: ValveControlRequest | FastValveControlRequest + ): + if valve in [1, 3] and isinstance(value, ValveControlRequest): + await self.valve_control[valve].set(value) + elif valve in [5, 6] and isinstance(value, FastValveControlRequest): + await self.fast_valve_control[valve].set(value) + + @AsyncStatus.wrap + async def set(self, value: AllValvesControlState): + await asyncio.gather( + *( + self.set_valve(int(i[-1]), value) + for i, value in value.__dict__.items() + if value is not None + ) + ) + class Pump(StandardReadable): def __init__(self, prefix: str, name: str = "") -> None: with self.add_children_as_readables(): self.pump_position = epics_signal_r(float, prefix + "POS") - self.pump_forward_limit = epics_signal_r( - LimitSwitchState, prefix + "D74IN1" - ) - self.pump_backward_limit = epics_signal_r( - LimitSwitchState, prefix + "D74IN0" - ) self.pump_motor_direction = epics_signal_r( PumpMotorDirectionState, prefix + "MTRDIR" ) - self.pump_speed_rbv = epics_signal_r(float, prefix + "MSPEED_RBV") + self.pump_speed = epics_signal_rw( + float, write_pv=prefix + "MSPEED", read_pv="MSPEED_RBV" + ) with self.add_children_as_readables(ConfigSignal): self.pump_mode = epics_signal_rw(PumpState, prefix + "SP:AUTO") - self.pump_speed = epics_signal_rw(float, prefix + "MSPEED") - self.pump_move_forward = epics_signal_rw(int, prefix + "M1:FORW") - self.pump_move_backward = epics_signal_rw(bool, prefix + "M1:BACKW") - self.pump_connection = epics_signal_rw( - PumpMotorControlRequest, prefix + "M1:CON" - ) super().__init__(name) class PressureTransducer(StandardReadable): - """ - reads pressure - """ - def __init__( self, prefix: str, number: int, name: str = "", adc_prefix: str = "" ) -> None: @@ -168,42 +178,30 @@ def __init__( float, f"{prefix}STATP{number}:MeanValue_RBV" ) self.beckhoff_voltage = epics_signal_r(float, adc_prefix + "CH1") - # todo this channel might be liable to change super().__init__(name) -class PressureJumpCellController(StandardReadable): +class PressureJumpCellController(HasName): def __init__(self, prefix: str, name: str = "") -> None: - with self.add_children_as_readables(): - self.control_gotobusy = epics_signal_r(BusyState, prefix + "CTRL:GOTOBUSY") + PREFIX = prefix + "CTRL:" + self.stop = epics_signal_rw(StopState, f"{PREFIX}STOP") - self.control_timer = epics_signal_r(TimerState, prefix + "CTRL:TIMER") - self.control_counter = epics_signal_r(float, prefix + "CTRL:COUNTER") - self.control_script_status = epics_signal_r(str, prefix + "CTRL:RESULT") - self.control_routine = epics_signal_r(str, prefix + "CTRL:METHOD") - self.control_state = epics_signal_r(str, prefix + "CTRL:STATE") - self.control_iteration = epics_signal_r(float, prefix + "CTRL:ITER") - - with self.add_children_as_readables(ConfigSignal): - self.control_stop = epics_signal_rw(StopState, prefix + "CTRL:STOP") + self.target_pressure = epics_signal_rw(float, f"{PREFIX}TARGET") + self.timeout = epics_signal_rw(float, f"{PREFIX}TIMER.HIGH") + self.go = epics_signal_rw(bool, f"{PREFIX}GO") - self.control_target_pressure = epics_signal_rw( - float, prefix + "CTRL:TARGET" - ) - self.control_timeout = epics_signal_rw(float, prefix + "CTRL:TIMER.HIGH") - self.control_go = epics_signal_rw(bool, prefix + "CTRL:GO") + ## Jump logic ## + self.start_pressure = epics_signal_rw(float, f"{PREFIX}JUMPF") + self.target_pressure = epics_signal_rw(float, f"{PREFIX}JUMPT") + self.jump_ready = epics_signal_rw(bool, f"{PREFIX}SETJUMP") - ## Jump logic ## - self.control_jump_from_pressure = epics_signal_rw( - float, prefix + "CTRL:JUMPF" - ) - self.control_jump_to_pressure = epics_signal_rw( - float, prefix + "CTRL:JUMPT" - ) - self.control_jump_set = epics_signal_rw(bool, prefix + "CTRL:SETJUMP") + self._name = name + super().__init__() - super().__init__(name) + @property + def name(self): + return self._name class PressureJumpCell(StandardReadable): @@ -213,28 +211,28 @@ class PressureJumpCell(StandardReadable): def __init__( self, - prefix: str = "", + beamline_prefix: str = "", cell_prefix: str = "", adc_prefix: str = "", name: str = "", ): - self.all_valves_control = AllValvesControl(f"{prefix}{cell_prefix}", name) - self.pump = Pump(f"{prefix}{cell_prefix}", name) + self.all_valves_control = AllValvesControl(f"{beamline_prefix}{cell_prefix}", name) + self.pump = Pump(f"{beamline_prefix}{cell_prefix}", name) - self.controller = PressureJumpCellController(f"{prefix}{cell_prefix}", name) + self.controller = PressureJumpCellController(f"{beamline_prefix}{cell_prefix}", name) with self.add_children_as_readables(): self.pressure_transducers: DeviceVector[PressureTransducer] = DeviceVector( { i: PressureTransducer( - prefix=f"{prefix}{cell_prefix}", + prefix=f"{beamline_prefix}{cell_prefix}", number=i, - adc_prefix=f"{prefix}{adc_prefix}-0{i}:", + adc_prefix=f"{beamline_prefix}{adc_prefix}-0{i}:", ) for i in [1, 2, 3] } ) - self.cell_temperature = epics_signal_r(float, f"{prefix}{cell_prefix}TEMP") + self.cell_temperature = epics_signal_r(float, f"{beamline_prefix}{cell_prefix}TEMP") super().__init__(name) diff --git a/tests/devices/unit_tests/test_pressure_jump_cell.py b/tests/devices/unit_tests/test_pressure_jump_cell.py index c4c60de260..96b7a5a790 100644 --- a/tests/devices/unit_tests/test_pressure_jump_cell.py +++ b/tests/devices/unit_tests/test_pressure_jump_cell.py @@ -209,7 +209,7 @@ async def test_reading_pjumpcell_includes_read_fields_controller( set_mock_value(cell.controller.control_counter, 123) set_mock_value(cell.controller.control_script_status, "ABC") set_mock_value(cell.controller.control_routine, "CDE") - set_mock_value(cell.controller.control_state, "EFG") + set_mock_value(cell.controller.state, "EFG") set_mock_value(cell.controller.control_iteration, 456) await assert_reading( From e222f1663fb71b5585e8bbe29bf1e8ecb18d221f Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Thu, 22 Aug 2024 11:26:35 +0100 Subject: [PATCH 18/25] adapt pressure jump cell tests --- .../unit_tests/test_pressure_jump_cell.py | 71 ++----------------- 1 file changed, 4 insertions(+), 67 deletions(-) diff --git a/tests/devices/unit_tests/test_pressure_jump_cell.py b/tests/devices/unit_tests/test_pressure_jump_cell.py index 96b7a5a790..9f5128c709 100644 --- a/tests/devices/unit_tests/test_pressure_jump_cell.py +++ b/tests/devices/unit_tests/test_pressure_jump_cell.py @@ -66,13 +66,13 @@ async def test_reading_pjumpcell_includes_read_fields_pump( cell: PressureJumpCell, ): set_mock_value(cell.pump.pump_position, 100) - set_mock_value(cell.pump.pump_forward_limit, LimitSwitchState.OFF) - set_mock_value(cell.pump.pump_backward_limit, LimitSwitchState.ON) + # set_mock_value(cell.pump.pump_forward_limit, LimitSwitchState.OFF) + # set_mock_value(cell.pump.pump_backward_limit, LimitSwitchState.ON) set_mock_value( cell.pump.pump_motor_direction, PumpMotorDirectionState.FORWARD, ) - set_mock_value(cell.pump.pump_speed_rbv, 100) + set_mock_value(cell.pump.pump_speed, 100) await assert_reading( cell.pump, @@ -82,22 +82,12 @@ async def test_reading_pjumpcell_includes_read_fields_pump( "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pump-pump_forward_limit": { - "value": LimitSwitchState.OFF, - "timestamp": ANY, - "alarm_severity": 0, - }, - "pjump-pump-pump_backward_limit": { - "value": LimitSwitchState.ON, - "timestamp": ANY, - "alarm_severity": 0, - }, "pjump-pump-pump_motor_direction": { "value": PumpMotorDirectionState.FORWARD, "timestamp": ANY, "alarm_severity": 0, }, - "pjump-pump-pump_speed_rbv": { + "pjump-pump-pump_speed": { "value": 100, "timestamp": ANY, "alarm_severity": 0, @@ -201,59 +191,6 @@ async def test_reading_pjumpcell_includes_read_fields_transducers( ) -async def test_reading_pjumpcell_includes_read_fields_controller( - cell: PressureJumpCell, -): - set_mock_value(cell.controller.control_gotobusy, BusyState.IDLE) - set_mock_value(cell.controller.control_timer, TimerState.COUNTDOWN) - set_mock_value(cell.controller.control_counter, 123) - set_mock_value(cell.controller.control_script_status, "ABC") - set_mock_value(cell.controller.control_routine, "CDE") - set_mock_value(cell.controller.state, "EFG") - set_mock_value(cell.controller.control_iteration, 456) - - await assert_reading( - cell.controller, - { - "pjump-controller-control_gotobusy": { - "value": BusyState.IDLE, - "timestamp": ANY, - "alarm_severity": 0, - }, - "pjump-controller-control_timer": { - "value": TimerState.COUNTDOWN, - "timestamp": ANY, - "alarm_severity": 0, - }, - "pjump-controller-control_counter": { - "value": 123, - "timestamp": ANY, - "alarm_severity": 0, - }, - "pjump-controller-control_script_status": { - "value": "ABC", - "timestamp": ANY, - "alarm_severity": 0, - }, - "pjump-controller-control_routine": { - "value": "CDE", - "timestamp": ANY, - "alarm_severity": 0, - }, - "pjump-controller-control_state": { - "value": "EFG", - "timestamp": ANY, - "alarm_severity": 0, - }, - "pjump-controller-control_iteration": { - "value": 456, - "timestamp": ANY, - "alarm_severity": 0, - }, - }, - ) - - async def test_reading_pjumpcell_includes_read_fields( cell: PressureJumpCell, ): From 6e73f4781dbd26c3d592b98ade03e0020ba180e2 Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Thu, 22 Aug 2024 11:31:53 +0100 Subject: [PATCH 19/25] ruff --- src/dodal/devices/pressure_jump_cell.py | 12 +++++++++--- tests/devices/unit_tests/test_pressure_jump_cell.py | 3 --- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 70944b37fb..d32ea0019d 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -216,10 +216,14 @@ def __init__( adc_prefix: str = "", name: str = "", ): - self.all_valves_control = AllValvesControl(f"{beamline_prefix}{cell_prefix}", name) + self.all_valves_control = AllValvesControl( + f"{beamline_prefix}{cell_prefix}", name + ) self.pump = Pump(f"{beamline_prefix}{cell_prefix}", name) - self.controller = PressureJumpCellController(f"{beamline_prefix}{cell_prefix}", name) + self.controller = PressureJumpCellController( + f"{beamline_prefix}{cell_prefix}", name + ) with self.add_children_as_readables(): self.pressure_transducers: DeviceVector[PressureTransducer] = DeviceVector( @@ -233,6 +237,8 @@ def __init__( } ) - self.cell_temperature = epics_signal_r(float, f"{beamline_prefix}{cell_prefix}TEMP") + self.cell_temperature = epics_signal_r( + float, f"{beamline_prefix}{cell_prefix}TEMP" + ) super().__init__(name) diff --git a/tests/devices/unit_tests/test_pressure_jump_cell.py b/tests/devices/unit_tests/test_pressure_jump_cell.py index 9f5128c709..8f2a611f55 100644 --- a/tests/devices/unit_tests/test_pressure_jump_cell.py +++ b/tests/devices/unit_tests/test_pressure_jump_cell.py @@ -4,12 +4,9 @@ from ophyd_async.core import DeviceCollector, assert_reading, set_mock_value from dodal.devices.pressure_jump_cell import ( - BusyState, FastValveState, - LimitSwitchState, PressureJumpCell, PumpMotorDirectionState, - TimerState, ValveState, ) From abddcb4313b957cc24f35e6e8a2f4d33234350c5 Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Tue, 27 Aug 2024 10:22:04 +0000 Subject: [PATCH 20/25] chane pressure controller prefix logic --- src/dodal/devices/pressure_jump_cell.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index d32ea0019d..fda20b8241 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -184,17 +184,16 @@ def __init__( class PressureJumpCellController(HasName): def __init__(self, prefix: str, name: str = "") -> None: - PREFIX = prefix + "CTRL:" - self.stop = epics_signal_rw(StopState, f"{PREFIX}STOP") + self.stop = epics_signal_rw(StopState, f"{prefix}STOP") - self.target_pressure = epics_signal_rw(float, f"{PREFIX}TARGET") - self.timeout = epics_signal_rw(float, f"{PREFIX}TIMER.HIGH") - self.go = epics_signal_rw(bool, f"{PREFIX}GO") + self.target_pressure = epics_signal_rw(float, f"{prefix}TARGET") + self.timeout = epics_signal_rw(float, f"{prefix}TIMER.HIGH") + self.go = epics_signal_rw(bool, f"{prefix}GO") ## Jump logic ## - self.start_pressure = epics_signal_rw(float, f"{PREFIX}JUMPF") - self.target_pressure = epics_signal_rw(float, f"{PREFIX}JUMPT") - self.jump_ready = epics_signal_rw(bool, f"{PREFIX}SETJUMP") + self.start_pressure = epics_signal_rw(float, f"{prefix}JUMPF") + self.target_pressure = epics_signal_rw(float, f"{prefix}JUMPT") + self.jump_ready = epics_signal_rw(bool, f"{prefix}SETJUMP") self._name = name super().__init__() @@ -211,9 +210,10 @@ class PressureJumpCell(StandardReadable): def __init__( self, - beamline_prefix: str = "", - cell_prefix: str = "", - adc_prefix: str = "", + beamline_prefix: str, + cell_prefix: str = "-HPXC-01:", + adc_prefix: str = "-ADC", + ctrl_prefix: str = "CTRL:", name: str = "", ): self.all_valves_control = AllValvesControl( @@ -222,7 +222,7 @@ def __init__( self.pump = Pump(f"{beamline_prefix}{cell_prefix}", name) self.controller = PressureJumpCellController( - f"{beamline_prefix}{cell_prefix}", name + f"{beamline_prefix}{cell_prefix}{ctrl_prefix}", name ) with self.add_children_as_readables(): From 3ab8d4fc0ef4b9d1924f4812a567fa2ae95fea0f Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Tue, 27 Aug 2024 10:28:54 +0000 Subject: [PATCH 21/25] respond to feedback --- src/dodal/devices/pressure_jump_cell.py | 29 ++++++++++++++++++------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index fda20b8241..29bfb66088 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -97,18 +97,31 @@ class AllValvesControl(StandardReadable, Movable): """ valves 2, 4, 7, 8 are not controlled by the IOC, as they are under manual control. + fast_valves: tuple[int, ...] = (5, 6) + slow_valves: tuple[int, ...] = (1, 3) """ - def __init__(self, prefix: str, name: str = "") -> None: + def __init__( + self, + prefix: str, + name: str = "", + fast_valves: tuple[int, ...] = (5, 6), + slow_valves: tuple[int, ...] = (1, 3), + ) -> None: + self.fast_valves = fast_valves + self.slow_valves = slow_valves with self.add_children_as_readables(): self.valve_states: DeviceVector[SignalR[ValveState]] = DeviceVector( - {i: epics_signal_r(ValveState, f"{prefix}V{i}:STA") for i in [1, 3]} + { + i: epics_signal_r(ValveState, f"{prefix}V{i}:STA") + for i in self.slow_valves + } ) self.fast_valve_states: DeviceVector[SignalR[FastValveState]] = ( DeviceVector( { i: epics_signal_r(FastValveState, f"{prefix}V{i}:STA") - for i in [5, 6] + for i in self.fast_valves } ) ) @@ -117,7 +130,7 @@ def __init__(self, prefix: str, name: str = "") -> None: DeviceVector( { i: epics_signal_rw(FastValveControlRequest, f"{prefix}V{i}:CON") - for i in [5, 6] + for i in self.fast_valves } ) ) @@ -125,7 +138,7 @@ def __init__(self, prefix: str, name: str = "") -> None: self.valve_control: DeviceVector[SignalRW[ValveControlRequest]] = DeviceVector( { i: epics_signal_rw(ValveControlRequest, f"{prefix}V{i}:CON") - for i in [1, 3] + for i in self.slow_valves } ) @@ -134,9 +147,9 @@ def __init__(self, prefix: str, name: str = "") -> None: async def set_valve( self, valve: int, value: ValveControlRequest | FastValveControlRequest ): - if valve in [1, 3] and isinstance(value, ValveControlRequest): + if valve in self.slow_valves and isinstance(value, ValveControlRequest): await self.valve_control[valve].set(value) - elif valve in [5, 6] and isinstance(value, FastValveControlRequest): + elif valve in self.fast_valves and isinstance(value, FastValveControlRequest): await self.fast_valve_control[valve].set(value) @AsyncStatus.wrap @@ -158,7 +171,7 @@ def __init__(self, prefix: str, name: str = "") -> None: PumpMotorDirectionState, prefix + "MTRDIR" ) self.pump_speed = epics_signal_rw( - float, write_pv=prefix + "MSPEED", read_pv="MSPEED_RBV" + float, write_pv=prefix + "MSPEED", read_pv=prefix + "MSPEED_RBV" ) with self.add_children_as_readables(ConfigSignal): From 68db33d35936d1142225030e54f05169f41189c6 Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Wed, 18 Sep 2024 15:51:35 +0100 Subject: [PATCH 22/25] pjump cell add prefix to initalize correctly --- src/dodal/devices/pressure_jump_cell.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 29bfb66088..0bea4ba29a 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -224,25 +224,26 @@ class PressureJumpCell(StandardReadable): def __init__( self, beamline_prefix: str, + prefix: str, cell_prefix: str = "-HPXC-01:", adc_prefix: str = "-ADC", ctrl_prefix: str = "CTRL:", name: str = "", ): self.all_valves_control = AllValvesControl( - f"{beamline_prefix}{cell_prefix}", name + f"{beamline_prefix}{prefix}{cell_prefix}", name ) - self.pump = Pump(f"{beamline_prefix}{cell_prefix}", name) + self.pump = Pump(f"{beamline_prefix}{prefix}{cell_prefix}", name) self.controller = PressureJumpCellController( - f"{beamline_prefix}{cell_prefix}{ctrl_prefix}", name + f"{beamline_prefix}{prefix}{cell_prefix}{ctrl_prefix}", name ) with self.add_children_as_readables(): self.pressure_transducers: DeviceVector[PressureTransducer] = DeviceVector( { i: PressureTransducer( - prefix=f"{beamline_prefix}{cell_prefix}", + prefix=f"{beamline_prefix}{prefix}{cell_prefix}", number=i, adc_prefix=f"{beamline_prefix}{adc_prefix}-0{i}:", ) @@ -251,7 +252,7 @@ def __init__( ) self.cell_temperature = epics_signal_r( - float, f"{beamline_prefix}{cell_prefix}TEMP" + float, f"{beamline_prefix}{prefix}{cell_prefix}TEMP" ) super().__init__(name) From acaf6bfca7b6f9c8ed71a850e4eecd5cc8308d4f Mon Sep 17 00:00:00 2001 From: Stanislaw Malinowski Date: Wed, 18 Sep 2024 16:25:36 +0100 Subject: [PATCH 23/25] adapt pressure jumpt to use the clear prefix --- src/dodal/beamlines/p38.py | 4 +- src/dodal/devices/pressure_jump_cell.py | 49 ++++++++++++------- .../unit_tests/test_pressure_jump_cell.py | 6 +-- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/dodal/beamlines/p38.py b/src/dodal/beamlines/p38.py index 416abd974b..b86a26d80d 100644 --- a/src/dodal/beamlines/p38.py +++ b/src/dodal/beamlines/p38.py @@ -315,7 +315,7 @@ def linkam( return device_instantiation( Linkam3, "linkam", - "-EA-LINKM-02:", + f"{BeamlinePrefix(BL).insertion_prefix}-EA-LINKM-02:", wait_for_connection, fake_with_ophyd_sim, ) @@ -327,7 +327,7 @@ def high_pressure_xray_cell( return device_instantiation( PressureJumpCell, "high_pressure_xray_cell", - "-EA", + f"{BeamlinePrefix(BL).insertion_prefix}-EA", wait_for_connection, fake_with_ophyd_sim, cell_prefix="-HPXC-01:", diff --git a/src/dodal/devices/pressure_jump_cell.py b/src/dodal/devices/pressure_jump_cell.py index 0bea4ba29a..2b8686e9fc 100644 --- a/src/dodal/devices/pressure_jump_cell.py +++ b/src/dodal/devices/pressure_jump_cell.py @@ -181,16 +181,34 @@ def __init__(self, prefix: str, name: str = "") -> None: class PressureTransducer(StandardReadable): + """ + Pressure transducer for a high pressure X-ray cell. + This is the chamber and there are three of them. + 1 is the start, 3 is where the sample is. + NOTE: the distinction between the adc prefix and the cell prefix is kept here. + + """ + def __init__( - self, prefix: str, number: int, name: str = "", adc_prefix: str = "" + self, + prefix: str, + cell_prefix: str, + number: int, + name: str = "", + full_different_prefix_adc: str = "", ) -> None: + final_prefix = f"{prefix}{cell_prefix}" with self.add_children_as_readables(): - self.omron_pressure = epics_signal_r(float, f"{prefix}PP{number}:PRES") - self.omron_voltage = epics_signal_r(float, f"{prefix}PP{number}:RAW") + self.omron_pressure = epics_signal_r( + float, f"{final_prefix}PP{number}:PRES" + ) + self.omron_voltage = epics_signal_r(float, f"{final_prefix}PP{number}:RAW") self.beckhoff_pressure = epics_signal_r( - float, f"{prefix}STATP{number}:MeanValue_RBV" + float, f"{final_prefix}STATP{number}:MeanValue_RBV" + ) + self.slow_beckhoff_voltage_readout = epics_signal_r( + float, f"{full_different_prefix_adc}CH1" ) - self.beckhoff_voltage = epics_signal_r(float, adc_prefix + "CH1") super().__init__(name) @@ -219,40 +237,37 @@ def name(self): class PressureJumpCell(StandardReadable): """ High pressure X-ray cell, used to apply pressure or pressure jumps to a sample. + prefix: str + The prefix of beamline - SPECIAL - unusual that the cell prefix is computed separately """ def __init__( self, - beamline_prefix: str, prefix: str, cell_prefix: str = "-HPXC-01:", adc_prefix: str = "-ADC", - ctrl_prefix: str = "CTRL:", name: str = "", ): - self.all_valves_control = AllValvesControl( - f"{beamline_prefix}{prefix}{cell_prefix}", name - ) - self.pump = Pump(f"{beamline_prefix}{prefix}{cell_prefix}", name) + self.all_valves_control = AllValvesControl(f"{prefix}{cell_prefix}", name) + self.pump = Pump(f"{prefix}{cell_prefix}", name) self.controller = PressureJumpCellController( - f"{beamline_prefix}{prefix}{cell_prefix}{ctrl_prefix}", name + f"{prefix}{cell_prefix}CTRL:", name ) with self.add_children_as_readables(): self.pressure_transducers: DeviceVector[PressureTransducer] = DeviceVector( { i: PressureTransducer( - prefix=f"{beamline_prefix}{prefix}{cell_prefix}", + prefix=prefix, number=i, - adc_prefix=f"{beamline_prefix}{adc_prefix}-0{i}:", + cell_prefix=cell_prefix, + full_different_prefix_adc=f"{prefix}{adc_prefix}-0{i}:", ) for i in [1, 2, 3] } ) - self.cell_temperature = epics_signal_r( - float, f"{beamline_prefix}{prefix}{cell_prefix}TEMP" - ) + self.cell_temperature = epics_signal_r(float, f"{prefix}{cell_prefix}TEMP") super().__init__(name) diff --git a/tests/devices/unit_tests/test_pressure_jump_cell.py b/tests/devices/unit_tests/test_pressure_jump_cell.py index 8f2a611f55..21c7b1df72 100644 --- a/tests/devices/unit_tests/test_pressure_jump_cell.py +++ b/tests/devices/unit_tests/test_pressure_jump_cell.py @@ -99,17 +99,17 @@ async def test_reading_pjumpcell_includes_read_fields_transducers( set_mock_value(cell.pressure_transducers[1].omron_pressure, 1001) set_mock_value(cell.pressure_transducers[1].omron_voltage, 2.51) set_mock_value(cell.pressure_transducers[1].beckhoff_pressure, 1001.1) - set_mock_value(cell.pressure_transducers[1].beckhoff_voltage, 2.51) + set_mock_value(cell.pressure_transducers[1].slow_beckhoff_voltage_readout, 2.51) set_mock_value(cell.pressure_transducers[2].omron_pressure, 1002) set_mock_value(cell.pressure_transducers[2].omron_voltage, 2.52) set_mock_value(cell.pressure_transducers[2].beckhoff_pressure, 1002.2) - set_mock_value(cell.pressure_transducers[2].beckhoff_voltage, 2.52) + set_mock_value(cell.pressure_transducers[2].slow_beckhoff_voltage_readout, 2.52) set_mock_value(cell.pressure_transducers[3].omron_pressure, 1003) set_mock_value(cell.pressure_transducers[3].omron_voltage, 2.53) set_mock_value(cell.pressure_transducers[3].beckhoff_pressure, 1003.3) - set_mock_value(cell.pressure_transducers[3].beckhoff_voltage, 2.53) + set_mock_value(cell.pressure_transducers[3].slow_beckhoff_voltage_readout, 2.53) await assert_reading( cell.pressure_transducers[1], From 04cc496b0fbad54148d3398215d12f1fea7179e6 Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Wed, 7 Aug 2024 14:58:59 +0100 Subject: [PATCH 24/25] Pressure jump adc initial attempt based on area detector. --- src/dodal/beamlines/p38.py | 15 +++++ src/dodal/devices/pressure_jump_cell_adc.py | 63 +++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/dodal/devices/pressure_jump_cell_adc.py diff --git a/src/dodal/beamlines/p38.py b/src/dodal/beamlines/p38.py index b86a26d80d..24d388c470 100644 --- a/src/dodal/beamlines/p38.py +++ b/src/dodal/beamlines/p38.py @@ -16,6 +16,7 @@ from dodal.devices.i22.fswitch import FSwitch from dodal.devices.linkam3 import Linkam3 from dodal.devices.pressure_jump_cell import PressureJumpCell +from dodal.devices.pressure_jump_cell_adc import PressureJumpCellADC, PressureJumpAdcConfigParams from dodal.devices.slits import Slits from dodal.devices.tetramm import TetrammDetector from dodal.devices.undulator import Undulator @@ -333,3 +334,17 @@ def high_pressure_xray_cell( cell_prefix="-HPXC-01:", adc_prefix="-ADC", ) + +def high_pressure_xray_cell_adc( + wait_for_connection: bool = True, + fake_with_ophyd_sim: bool = False, + params: PressureJumpAdcConfigParams | None = None, +) -> PressureJumpCellADC: + return device_instantiation( + PressureJumpCellADC, + "high_pressure_xray_cell_adc", + "", + wait_for_connection, + fake_with_ophyd_sim, + params=params or None, + ) diff --git a/src/dodal/devices/pressure_jump_cell_adc.py b/src/dodal/devices/pressure_jump_cell_adc.py new file mode 100644 index 0000000000..63665401af --- /dev/null +++ b/src/dodal/devices/pressure_jump_cell_adc.py @@ -0,0 +1,63 @@ +from enum import Enum +from functools import partial + +from ophyd_async.core import ( + ConfigSignal, + DeviceVector, + SignalR, + StandardReadable, +) +from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw + +from ophyd import ADComponent as ADC +from ophyd import ( + AreaDetector, + CamBase, + Component, + Device, + EpicsSignal, + HDF5Plugin, + OverlayPlugin, + ProcessPlugin, + ROIPlugin, + StatsPlugin, + Signal, + StatusBase, +) + +class PressureJumpAdcConfigParams: + pass + +class PressureJumpCellADC(AreaDetector): + """ + High pressure X-ray cell fast ADC, used to capture pressure jumps. + """ + cam = ADC(CamBase, "-EA-HPXC-01:CAM:") + scale = ADC(ROIPlugin, "-EA-HPXC-01:SCALE:") + # trig = # TODO support module adUtil NDPluginReframe? + # arr = # TODO support module ADCore NDPluginStdArrays? required? + hdf5 = ADC(HDF5Plugin, "-DI-OAV-01:HDF5:") + + p1Roi = ADC(ROIPlugin, "-EA-HPXC-01:ROIP1:") + p1Proc = ADC(ProcessPlugin, "-EA-HPXC-01:PROCP1:") + p1Stats = ADC(StatsPlugin, "-EA-HPXC-01:STATP1:") + + p2Roi = ADC(ROIPlugin, "-EA-HPXC-01:ROIP2:") + p2Proc = ADC(ProcessPlugin, "-EA-HPXC-01:PROCP2:") + p2Stats = ADC(StatsPlugin, "-EA-HPXC-01:STATP2:") + + p3Roi = ADC(ROIPlugin, "-EA-HPXC-01:ROIP3:") + p3Proc = ADC(ProcessPlugin, "-EA-HPXC-01:PROCP3:") + p3Stats = ADC(StatsPlugin, "-EA-HPXC-01:STATP3:") + + def __init__(self, *args, params: PressureJumpAdcConfigParams, **kwargs): + super().__init__(*args, **kwargs) + self.parameters = params + self.snapshot.oav_params = params + self.subscription_id = None + self._snapshot_trigger_subscription_id = None + + def wait_for_connection(self, all_signals=False, timeout=2): + connected = super().wait_for_connection(all_signals, timeout) + return connected + From 5f9f808cbd5260e22fc69b09b8524aabc9ea0434 Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Fri, 27 Sep 2024 14:37:44 +0100 Subject: [PATCH 25/25] Revised pressure jump cell adc to use ophyd-async. --- src/dodal/beamlines/p38.py | 17 ++-- src/dodal/devices/areadetector/__init__.py | 2 + .../devices/areadetector/pressurejumpcell.py | 48 +++++++++++ .../pressurejumpcell_controller.py | 82 +++++++++++++++++++ .../areadetector/pressurejumpcell_io.py | 29 +++++++ src/dodal/devices/pressure_jump_cell_adc.py | 63 -------------- 6 files changed, 170 insertions(+), 71 deletions(-) create mode 100644 src/dodal/devices/areadetector/pressurejumpcell.py create mode 100644 src/dodal/devices/areadetector/pressurejumpcell_controller.py create mode 100644 src/dodal/devices/areadetector/pressurejumpcell_io.py delete mode 100644 src/dodal/devices/pressure_jump_cell_adc.py diff --git a/src/dodal/beamlines/p38.py b/src/dodal/beamlines/p38.py index 24d388c470..33e0798810 100644 --- a/src/dodal/beamlines/p38.py +++ b/src/dodal/beamlines/p38.py @@ -16,7 +16,7 @@ from dodal.devices.i22.fswitch import FSwitch from dodal.devices.linkam3 import Linkam3 from dodal.devices.pressure_jump_cell import PressureJumpCell -from dodal.devices.pressure_jump_cell_adc import PressureJumpCellADC, PressureJumpAdcConfigParams +from dodal.devices.areadetector import PressureJumpCellDetector from dodal.devices.slits import Slits from dodal.devices.tetramm import TetrammDetector from dodal.devices.undulator import Undulator @@ -336,15 +336,16 @@ def high_pressure_xray_cell( ) def high_pressure_xray_cell_adc( - wait_for_connection: bool = True, - fake_with_ophyd_sim: bool = False, - params: PressureJumpAdcConfigParams | None = None, -) -> PressureJumpCellADC: + wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False +) -> PressureJumpCellDetector: return device_instantiation( - PressureJumpCellADC, + PressureJumpCellDetector, "high_pressure_xray_cell_adc", - "", + "-EA-HPXC-01:", wait_for_connection, fake_with_ophyd_sim, - params=params or None, + adc_suffix="TRIG:", + drv_suffix="DET:", + hdf_suffix="FILE:", + path_provider=get_path_provider(), ) diff --git a/src/dodal/devices/areadetector/__init__.py b/src/dodal/devices/areadetector/__init__.py index 78171d5ef5..e2ba794ab8 100644 --- a/src/dodal/devices/areadetector/__init__.py +++ b/src/dodal/devices/areadetector/__init__.py @@ -1,10 +1,12 @@ from .adaravis import AdAravisDetector from .adsim import AdSimDetector from .adutils import Hdf5Writer, SynchronisedAdDriverBase +from .pressurejumpcell import PressureJumpCellDetector __all__ = [ "AdSimDetector", "SynchronisedAdDriverBase", "Hdf5Writer", "AdAravisDetector", + "PressureJumpCellDetector", ] diff --git a/src/dodal/devices/areadetector/pressurejumpcell.py b/src/dodal/devices/areadetector/pressurejumpcell.py new file mode 100644 index 0000000000..ae7c3650ac --- /dev/null +++ b/src/dodal/devices/areadetector/pressurejumpcell.py @@ -0,0 +1,48 @@ +from typing import get_args + +from bluesky.protocols import HasHints, Hints + +from ophyd_async.core import PathProvider, StandardDetector +from ophyd_async.epics import adcore + +from .pressurejumpcell_controller import PressureJumpCellController +from .pressurejumpcell_io import PressureJumpCellDriverIO, PressureJumpCellAdcIO + + +class PressureJumpCellDetector(StandardDetector, HasHints): + """ + Ophyd-async implementation of a Pressure Jump Cell ADC Detector for fast pressure jumps. + The detector may be configured for an external trigger on the TTL Trig input. + """ + + _controller: PressureJumpCellController + _writer: adcore.ADHDFWriter + + def __init__( + self, + prefix: str, + path_provider: PathProvider, + drv_suffix="cam1:", + adc_suffix="TRIG", + hdf_suffix="HDF1:", + name="", + ): + self.drv = PressureJumpCellDriverIO(prefix + drv_suffix) + self.adc = PressureJumpCellAdcIO(prefix + adc_suffix) + self.hdf = adcore.NDFileHDFIO(prefix + hdf_suffix) + + super().__init__( + PressureJumpCellController(self.drv, self.adc), + adcore.ADHDFWriter( + self.hdf, + path_provider, + lambda: self.name, + adcore.ADBaseDatasetDescriber(self.drv), + ), + config_sigs=(self.drv.acquire_time,), + name=name, + ) + + @property + def hints(self) -> Hints: + return self._writer.hints diff --git a/src/dodal/devices/areadetector/pressurejumpcell_controller.py b/src/dodal/devices/areadetector/pressurejumpcell_controller.py new file mode 100644 index 0000000000..986f0d361c --- /dev/null +++ b/src/dodal/devices/areadetector/pressurejumpcell_controller.py @@ -0,0 +1,82 @@ +import asyncio +from typing import Optional, Tuple + +from ophyd_async.core import ( + AsyncStatus, + DetectorControl, + DetectorTrigger, + set_and_wait_for_value, +) +from ophyd_async.epics import adcore + +from .pressurejumpcell_io import ( + PressureJumpCellDriverIO, + PressureJumpCellAdcIO, + PressureJumpCellTriggerMode, + PressureJumpCellAdcTriggerMode, +) + + +#TODO Find out what the deadtime should be and if it can be retrieved from the device +_HIGHEST_POSSIBLE_DEADTIME = 1e-3 + + +class PressureJumpCellController(DetectorControl): + + def __init__(self, driver: PressureJumpCellDriverIO, adc: PressureJumpCellAdcIO) -> None: + self._drv = driver + self._adc = adc + + def get_deadtime(self, exposure: float | None) -> float: + return _HIGHEST_POSSIBLE_DEADTIME + + async def arm( + self, + num: int = 0, + trigger: DetectorTrigger = DetectorTrigger.internal, + exposure: Optional[float] = None, + ) -> AsyncStatus: + if num == 0: + image_mode = adcore.ImageMode.continuous + else: + image_mode = adcore.ImageMode.multiple + if exposure is not None: + await self._drv.acquire_time.set(exposure) + + trigger_mode, adc_trigger_mode = self._get_trigger_info(trigger) + + # trigger mode must be set first and on it's own! + await self._drv.trigger_mode.set(trigger_mode) + await self._adc.adc_trigger_mode.set(adc_trigger_mode) + + await asyncio.gather( + self._drv.num_images.set(num), + self._drv.image_mode.set(image_mode), + ) + + status = await set_and_wait_for_value(self._drv.acquire, True) + return status + + def _get_trigger_info( + self, trigger: DetectorTrigger + ) -> Tuple[PressureJumpCellTriggerMode, PressureJumpCellAdcTriggerMode]: + supported_trigger_types = ( + DetectorTrigger.edge_trigger, + DetectorTrigger.internal, + ) + if trigger not in supported_trigger_types: + raise ValueError( + f"{self.__class__.__name__} only supports the following trigger " + f"types: {supported_trigger_types} but was asked to " + f"use {trigger}" + ) + if trigger == DetectorTrigger.internal: + return (PressureJumpCellTriggerMode.internal, PressureJumpCellAdcTriggerMode.continuous) + else: + return (PressureJumpCellTriggerMode.external, PressureJumpCellAdcTriggerMode.single) + + async def disarm(self): + await asyncio.gather( + adcore.stop_busy_record(self._drv.acquire, False, timeout=1), + adcore.stop_busy_record(self._adc.acquire, False, timeout=1) + ) diff --git a/src/dodal/devices/areadetector/pressurejumpcell_io.py b/src/dodal/devices/areadetector/pressurejumpcell_io.py new file mode 100644 index 0000000000..d0104916b6 --- /dev/null +++ b/src/dodal/devices/areadetector/pressurejumpcell_io.py @@ -0,0 +1,29 @@ +from enum import Enum + +from ophyd_async.core import SubsetEnum +from ophyd_async.epics import adcore +from ophyd_async.epics.signal import epics_signal_rw_rbv + + +class PressureJumpCellTriggerMode(str, Enum): + internal = "Internal" + external = "Exernal" + +class PressureJumpCellAdcTriggerMode(str, Enum): + single = "Single" + multiple = "Multiple" + continuous = "Continuous" + +class PressureJumpCellDriverIO(adcore.ADBaseIO): + def __init__(self, prefix: str, name: str = "") -> None: + self.trigger_mode = epics_signal_rw_rbv( + PressureJumpCellTriggerMode, prefix + "TriggerMode" + ) + super().__init__(prefix, name=name) + +class PressureJumpCellAdcIO(adcore.ADBaseIO): + def __init__(self, prefix: str, name: str = "") -> None: + self.adc_trigger_mode = epics_signal_rw_rbv( + PressureJumpCellAdcTriggerMode, prefix + "TriggerMode" + ) + super().__init__(prefix, name=name) diff --git a/src/dodal/devices/pressure_jump_cell_adc.py b/src/dodal/devices/pressure_jump_cell_adc.py deleted file mode 100644 index 63665401af..0000000000 --- a/src/dodal/devices/pressure_jump_cell_adc.py +++ /dev/null @@ -1,63 +0,0 @@ -from enum import Enum -from functools import partial - -from ophyd_async.core import ( - ConfigSignal, - DeviceVector, - SignalR, - StandardReadable, -) -from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw - -from ophyd import ADComponent as ADC -from ophyd import ( - AreaDetector, - CamBase, - Component, - Device, - EpicsSignal, - HDF5Plugin, - OverlayPlugin, - ProcessPlugin, - ROIPlugin, - StatsPlugin, - Signal, - StatusBase, -) - -class PressureJumpAdcConfigParams: - pass - -class PressureJumpCellADC(AreaDetector): - """ - High pressure X-ray cell fast ADC, used to capture pressure jumps. - """ - cam = ADC(CamBase, "-EA-HPXC-01:CAM:") - scale = ADC(ROIPlugin, "-EA-HPXC-01:SCALE:") - # trig = # TODO support module adUtil NDPluginReframe? - # arr = # TODO support module ADCore NDPluginStdArrays? required? - hdf5 = ADC(HDF5Plugin, "-DI-OAV-01:HDF5:") - - p1Roi = ADC(ROIPlugin, "-EA-HPXC-01:ROIP1:") - p1Proc = ADC(ProcessPlugin, "-EA-HPXC-01:PROCP1:") - p1Stats = ADC(StatsPlugin, "-EA-HPXC-01:STATP1:") - - p2Roi = ADC(ROIPlugin, "-EA-HPXC-01:ROIP2:") - p2Proc = ADC(ProcessPlugin, "-EA-HPXC-01:PROCP2:") - p2Stats = ADC(StatsPlugin, "-EA-HPXC-01:STATP2:") - - p3Roi = ADC(ROIPlugin, "-EA-HPXC-01:ROIP3:") - p3Proc = ADC(ProcessPlugin, "-EA-HPXC-01:PROCP3:") - p3Stats = ADC(StatsPlugin, "-EA-HPXC-01:STATP3:") - - def __init__(self, *args, params: PressureJumpAdcConfigParams, **kwargs): - super().__init__(*args, **kwargs) - self.parameters = params - self.snapshot.oav_params = params - self.subscription_id = None - self._snapshot_trigger_subscription_id = None - - def wait_for_connection(self, all_signals=False, timeout=2): - connected = super().wait_for_connection(all_signals, timeout) - return connected -