diff --git a/csaxs_bec/bec_ipython_client/plugins/cSAXS/cSAXS.py b/csaxs_bec/bec_ipython_client/plugins/cSAXS/cSAXS.py index 859f43f..f24d80d 100644 --- a/csaxs_bec/bec_ipython_client/plugins/cSAXS/cSAXS.py +++ b/csaxs_bec/bec_ipython_client/plugins/cSAXS/cSAXS.py @@ -17,6 +17,7 @@ from csaxs_bec.bec_ipython_client.plugins.cSAXS.smaract import cSAXSSmaract from csaxs_bec.bec_ipython_client.plugins.omny.omny_general_tools import OMNYTools from csaxs_bec.bec_ipython_client.plugins.cSAXS.filter_transmission import cSAXSFilterTransmission from csaxs_bec.bec_ipython_client.plugins.cSAXS.diagnostics import cSAXSDiagnostics +from csaxs_bec.bec_ipython_client.plugins.cSAXS.slits import cSAXSSlits class cSAXSError(Exception): pass @@ -25,6 +26,7 @@ class cSAXS( cSAXSInitSmaractStages, cSAXSSmaract, cSAXSFilterTransmission, + cSAXSSlits, ): def __init__(self, client): self.client = client diff --git a/csaxs_bec/bec_ipython_client/plugins/cSAXS/slits.py b/csaxs_bec/bec_ipython_client/plugins/cSAXS/slits.py new file mode 100644 index 0000000..fdcb35f --- /dev/null +++ b/csaxs_bec/bec_ipython_client/plugins/cSAXS/slits.py @@ -0,0 +1,107 @@ +from __future__ import annotations + +import builtins +from typing import Optional + +# Make dev visible if running inside BEC (same pattern as diagnostics) +if builtins.dict.get("dev") is not None: + dev = builtins.dict.get("dev") + + +class cSAXSSlits: + """ + User-visible slits namespace. + + Provides read-only overview and helper methods for all cSAXS slits. + """ + + def __init__(self, client): + self.client = client + self.device_manager = client.device_manager + + # ------------------------------------------------------------------ + # internal helpers + # ------------------------------------------------------------------ + + def _get_position(self, device_name: str) -> Optional[float]: + """ + Safely return the position of a device or None if unavailable. + """ + try: + dev = self.device_manager.devices[device_name] + return dev.position + except Exception: + return None + + @staticmethod + def _fmt(value: Optional[float]) -> str: + """ + Format numeric values consistently, SPEC-style. + """ + if value is None: + return " --- " + return f"{value:7.4f}" + + # ------------------------------------------------------------------ + # public API + # ------------------------------------------------------------------ + + def show_all(self): + """ + Show all slits with center and width, ordered along the beamline. + Equivalent to the historic SPEC macro slits_show_all. + """ + + print("") + print("========== cSAXS Slits Overview ==========") + print("") + + # -------------------------------------------------------------- + # Slit 1 – frontend (white beam) + # -------------------------------------------------------------- + print("Slit 1 (frontend):") + + ch = self._get_position("sl1xc") + wh = self._get_position("sl1xs") + cv = self._get_position("sl1yc") + wv = self._get_position("sl1ys") + + print( + f" center horizontal = {self._fmt(ch)} " + f"width horizontal = {self._fmt(wh)}" + ) + print( + f" center vertical = {self._fmt(cv)} " + f"width vertical = {self._fmt(wv)}" + ) + print("") + + # -------------------------------------------------------------- + # Slits 3–5 – exposure boxes + # -------------------------------------------------------------- + slit_map = { + 3: "exposure box 1 entrance", + 4: "exposure box 1 exit", + 5: "exposure box 2 exit", + } + + for slit, label in slit_map.items(): + print(f"Slit {slit} ({label}):") + + ch = self._get_position(f"sl{slit}ch") + wh = self._get_position(f"sl{slit}wh") + cv = self._get_position(f"sl{slit}cv") + wv = self._get_position(f"sl{slit}wv") + + print( + f" center horizontal = {self._fmt(ch)} " + f"width horizontal = {self._fmt(wh)}" + ) + print( + f" center vertical = {self._fmt(cv)} " + f"width vertical = {self._fmt(wv)}" + ) + print("") + + print("==========================================") + print("") diff --git a/csaxs_bec/device_configs/bl_endstation.yaml b/csaxs_bec/device_configs/bl_endstation.yaml index c543a76..0d00ebc 100644 --- a/csaxs_bec/device_configs/bl_endstation.yaml +++ b/csaxs_bec/device_configs/bl_endstation.yaml @@ -196,6 +196,68 @@ sl3trxt: # bl_smar_stage to use csaxs reference method. assign number according to axis channel bl_smar_stage: 5 +sl3ch: + description: ESbox1 slit 3 center horizontal + deviceClass: ophyd_devices.devices.virtual_slit.VirtualSlitCenter + deviceConfig: + left_slit: sl3trxi + right_slit: sl3trxo + offset: 0 + enabled: true + onFailure: retry + readOnly: false + readoutPriority: baseline + needs: + - sl3trxi + - sl3trxo + + +sl3wh: + description: ESbox1 slit 3 width horizontal + deviceClass: ophyd_devices.devices.virtual_slit.VirtualSlitWidth + deviceConfig: + left_slit: sl3trxi + right_slit: sl3trxo + offset: 0 + enabled: true + onFailure: retry + readOnly: false + readoutPriority: baseline + needs: + - sl3trxi + - sl3trxo + +sl3cv: + description: ESbox1 slit 3 center vertical + deviceClass: ophyd_devices.devices.virtual_slit.VirtualSlitCenter + deviceConfig: + left_slit: sl3trxb + right_slit: sl3trxt + offset: 0 + enabled: true + onFailure: retry + readOnly: false + readoutPriority: baseline + needs: + - sl3trxb + - sl3trxt + + +sl3wv: + description: ESbox1 slit 3 width vertical + deviceClass: ophyd_devices.devices.virtual_slit.VirtualSlitWidth + deviceConfig: + left_slit: sl3trxb + right_slit: sl3trxt + offset: 0 + enabled: true + onFailure: retry + readOnly: false + readoutPriority: baseline + needs: + - sl3trxb + - sl3trxt + fast_shutter_n1_x: description: ESbox1 New fast shutter 1 x movment deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor @@ -450,7 +512,71 @@ sl4trxt: # bl_smar_stage to use csaxs reference method. assign number according to axis channel bl_smar_stage: 0 -################## XBOX 2 ES ##################### +sl4ch: + description: ESbox1 slit 4 center horizontal + deviceClass: ophyd_devices.devices.virtual_slit.VirtualSlitCenter + deviceConfig: + left_slit: sl4trxi + right_slit: sl4trxo + offset: 0 + enabled: true + onFailure: retry + readOnly: false + readoutPriority: baseline + needs: + - sl4trxi + - sl4trxo + + +sl4wh: + description: ESbox1 slit 4 width horizontal + deviceClass: ophyd_devices.devices.virtual_slit.VirtualSlitWidth + deviceConfig: + left_slit: sl4trxi + right_slit: sl4trxo + offset: 0 + enabled: true + onFailure: retry + readOnly: false + readoutPriority: baseline + needs: + - sl4trxi + - sl4trxo + + +sl4cv: + description: ESbox1 slit 4 center vertical + deviceClass: ophyd_devices.devices.virtual_slit.VirtualSlitCenter + deviceConfig: + left_slit: sl4trxb + right_slit: sl4trxt + offset: 0 + enabled: true + onFailure: retry + readOnly: false + readoutPriority: baseline + needs: + - sl4trxb + - sl4trxt + + +sl4wv: + description: ESbox1 slit 4 width vertical + deviceClass: ophyd_devices.devices.virtual_slit.VirtualSlitWidth + deviceConfig: + left_slit: sl4trxb + right_slit: sl4trxt + offset: 0 + enabled: true + onFailure: retry + readOnly: false + readoutPriority: baseline + needs: + - sl4trxb + - sl4trxt + + +############## XBOX 3 (XBOX 2 ES) ##################### sl5trxi: description: ESbox2 slit 5 inner blade movement