diff --git a/debye_bec/devices/ionization_chambers/ionization_chamber.py b/debye_bec/devices/ionization_chambers/ionization_chamber.py index 6c2b9e0..572dd9c 100644 --- a/debye_bec/devices/ionization_chambers/ionization_chamber.py +++ b/debye_bec/devices/ionization_chambers/ionization_chamber.py @@ -1,4 +1,6 @@ -from typing import Literal +from __future__ import annotations + +from typing import Literal, TYPE_CHECKING import numpy as np from ophyd import Component as Cpt @@ -15,6 +17,9 @@ from debye_bec.devices.ionization_chambers.ionization_chamber_enums import ( AmplifierGain, ) +if TYPE_CHECKING: #pragma: no cover + from bec_lib.devicemanager import ScanInfo + class EpicsSignalSplit(EpicsSignal): """Wrapper around EpicsSignal with different read and write pv""" @@ -44,21 +49,22 @@ class GasMixSetupControl(Device): gas2 = Cpt(EpicsSignalRO, suffix="Gas2", kind="config", doc="Gas 2") conc2 = Cpt(EpicsSignalRO, suffix="Conc2", kind="config", doc="Concentration 2") press = Cpt(EpicsSignalRO, suffix="PressTransm", kind="config", doc="Current Pressure") - status_msg = Cpt(EpicsSignalRO, suffix="StatusMsg0", kind="config", doc="Status") class HighVoltageSuppliesControl(Device): """HighVoltage Supplies Control for Ionization Chamber 0""" - hv_v = Cpt(EpicsSignalSplit, suffix="HV1-V", kind="config", doc="HV voltage") - hv_i = Cpt(EpicsSignalSplit, suffix="HV1-I", kind="config", doc="HV current") - grid_v = Cpt(EpicsSignalSplit, suffix="HV2-V", kind="config", doc="Grid voltage") - grid_i = Cpt(EpicsSignalSplit, suffix="HV2-I", kind="config", doc="Grid current") + hv_v = Cpt(EpicsSignalSplit, suffix="HV2-V", kind="config", doc="HV voltage") + hv_i = Cpt(EpicsSignalSplit, suffix="HV2-I", kind="config", doc="HV current") + grid_v = Cpt(EpicsSignalSplit, suffix="HV1-V", kind="config", doc="Grid voltage") + grid_i = Cpt(EpicsSignalSplit, suffix="HV1-I", kind="config", doc="Grid current") class IonizationChamber0(PSIDeviceBase): """Ionization Chamber 0, prefix should be 'X01DA-'.""" + USER_ACCESS = ['set_gain', 'set_filter', 'set_hv', 'set_grid', 'fill'] + num = 1 amp_signals = { "cOnOff": ( @@ -79,6 +85,9 @@ class IonizationChamber0(PSIDeviceBase): } amp = Dcpt(amp_signals) gmes = Cpt(GasMixSetupControl, suffix=f"ES-GMES:IC{num-1}") + gmes_status = Cpt( + EpicsSignalRO, suffix="ES-GMES:StatusMsg0", kind="config", doc='Status' + ) hv = Cpt(HighVoltageSuppliesControl, suffix=f"ES1-IC{num-1}:") hv_en_signals = { "ext_ena": ( @@ -86,13 +95,13 @@ class IonizationChamber0(PSIDeviceBase): "ES1-IC0:HV-Ext-Ena", {"kind": "config", "doc": "External enable signal of HV"}, ), - "ena": (EpicsSignalRO, "ES1-IC0:HV-Ena", {"kind": "config", "doc": "Enable signal of HV"}), + "ena": (EpicsSignal, "ES1-IC0:HV-Ena", {"kind": "config", "doc": "Enable signal of HV"}), } hv_en = Dcpt(hv_en_signals) - def __init__(self, name: str, scan_info=None, **kwargs): + def __init__(self, name: str, prefix: str = "", scan_info: ScanInfo | None = None, **kwargs): self.timeout_for_pvwait = 2.5 - super().__init__(name=name, scan_info=scan_info, **kwargs) + super().__init__(name=name, prefix=prefix, scan_info=scan_info, **kwargs) @typechecked def set_gain(self, gain: Literal["1e6", "1e7", "5e7", "1e8", "1e9"] | AmplifierGain) -> None: @@ -180,9 +189,9 @@ class IonizationChamber0(PSIDeviceBase): hv (float) : Desired voltage for the 'HV' terminal. Voltage has to be between 0...3000 """ - if not 0 < hv < 3000: + if not 0 <= hv <= 3000: raise ValueError(f"specified HV {hv} not within range [0 .. 3000]") - if self.hv.grid_v.get() > hv: + if not np.isclose(np.abs(hv - self.hv.grid_v.get()), 0, atol=3): raise ValueError(f"Grid {self.hv.grid_v.get()} must not be higher than HV {hv}!") if not self.hv_en.ena.get() == 1: @@ -208,9 +217,9 @@ class IonizationChamber0(PSIDeviceBase): grid (float) : Desired voltage for the 'Grid' terminal, Grid Voltage has to be between 0...3000 """ - if not 0 < grid < 3000: + if not 0 <= grid <= 3000: raise ValueError(f"specified Grid {grid} not within range [0 .. 3000]") - if grid > self.hv.hv_v.get(): + if not np.isclose(np.abs(grid - self.hv.hv_v.get()), 0, atol=3): raise ValueError(f"Grid {grid} must not be higher than HV {self.hv.hv_v.get()}!") if not self.hv_en.ena.get() == 1: @@ -271,7 +280,7 @@ class IonizationChamber0(PSIDeviceBase): timeout = 3 if not self.wait_for_condition(wait_for_status, timeout=timeout, check_stopped=True): raise TimeoutError( - f"Ionization chamber filling process did not start after {timeout}s. Last log message {self.gmes.status_msg.get()}" + f"Ionization chamber filling process did not start after {timeout}s. Last log message {self.gmes_status.get()}" ) def wait_for_filling_finished(): @@ -286,8 +295,8 @@ class IonizationChamber0(PSIDeviceBase): return status -class IonizationChamber1(PSIDeviceBase): - """Ionization Chamber 0, prefix should be 'X01DA-'.""" +class IonizationChamber1(IonizationChamber0): + """Ionization Chamber 1, prefix should be 'X01DA-'.""" num = 2 amp_signals = { @@ -309,6 +318,9 @@ class IonizationChamber1(PSIDeviceBase): } amp = Dcpt(amp_signals) gmes = Cpt(GasMixSetupControl, suffix=f"ES-GMES:IC{num-1}") + gmes_status = Cpt( + EpicsSignalRO, suffix="ES-GMES:StatusMsg0", kind="config", doc='Status' + ) hv = Cpt(HighVoltageSuppliesControl, suffix=f"ES2-IC{num-1}:") hv_en_signals = { "ext_ena": ( @@ -316,13 +328,13 @@ class IonizationChamber1(PSIDeviceBase): "ES2-IC12:HV-Ext-Ena", {"kind": "config", "doc": "External enable signal of HV"}, ), - "ena": (EpicsSignalRO, "ES2-IC12:HV-Ena", {"kind": "config", "doc": "Enable signal of HV"}), + "ena": (EpicsSignal, "ES2-IC12:HV-Ena", {"kind": "config", "doc": "Enable signal of HV"}), } hv_en = Dcpt(hv_en_signals) -class IonizationChamber2(PSIDeviceBase): - """Ionization Chamber 0, prefix should be 'X01DA-'.""" +class IonizationChamber2(IonizationChamber0): + """Ionization Chamber 2, prefix should be 'X01DA-'.""" num = 3 amp_signals = { @@ -344,6 +356,9 @@ class IonizationChamber2(PSIDeviceBase): } amp = Dcpt(amp_signals) gmes = Cpt(GasMixSetupControl, suffix=f"ES-GMES:IC{num-1}") + gmes_status = Cpt( + EpicsSignalRO, suffix="ES-GMES:StatusMsg0", kind="config", doc='Status' + ) hv = Cpt(HighVoltageSuppliesControl, suffix=f"ES2-IC{num-1}:") hv_en_signals = { "ext_ena": ( @@ -351,6 +366,6 @@ class IonizationChamber2(PSIDeviceBase): "ES2-IC12:HV-Ext-Ena", {"kind": "config", "doc": "External enable signal of HV"}, ), - "ena": (EpicsSignalRO, "ES2-IC12:HV-Ena", {"kind": "config", "doc": "Enable signal of HV"}), + "ena": (EpicsSignal, "ES2-IC12:HV-Ena", {"kind": "config", "doc": "Enable signal of HV"}), } hv_en = Dcpt(hv_en_signals)