mod filter trans to check CCM in use
All checks were successful
CI for csaxs_bec / test (push) Successful in 1m14s

This commit is contained in:
x12sa
2026-01-16 14:10:39 +01:00
parent 4776b909e8
commit 568daff014
2 changed files with 169 additions and 19 deletions

View File

@@ -31,6 +31,8 @@ from importlib import resources
# Resolve the filter_data/ folder via importlib.resources
import csaxs_bec.bec_ipython_client.plugins.cSAXS.filter_transmission as ft_pkg
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get
from bec_lib import bec_logger
import builtins
@@ -155,8 +157,6 @@ class cSAXSFilterTransmission:
# -----------------------------
# Public API
# -----------------------------
def fil_trans(
self,
transmission: Optional[float] = None,
@@ -167,17 +167,27 @@ class cSAXSFilterTransmission:
Set exposure-box filters to achieve a target transmission.
If called without 'transmission', prints usage and current status.
Safety:
- fil_trans(1) is always allowed.
- fil_trans(<1) is only allowed if:
- epics_get("X12SA-OP-DMM-EMLS-3010:THRU") == 1 (DMM translation THROUGH)
- epics_get("X12SA-OP-DMM-EMLS-3030:THRU") == 1 (DMM rotation THROUGH)
- epics_get("X12SA-OP-CCM1:ENERGY-GET") > 1 (CCM active, energy in keV)
Otherwise, prompt with default NO.
"""
# --- No-arg usage helper ---
if transmission is None:
print("\nUsage example:")
print(" csaxs.fil_trans(0.10, energy_kev=6.2)")
print(" First parameter is the transmission factor requested.\nIf energy is not specified it will be read from the monochromator (in the future)")
print(" First parameter is the transmission factor requested.")
print(" If energy is not specified it will be read from the CCM energy PV.")
print("\nCurrent filter transmission:")
self._fil_trans_report(energy_kev=energy_kev)
return None
# --- Validation ---
# --- Validation of transmission ---
try:
transmission = float(transmission)
except Exception:
@@ -186,17 +196,64 @@ class cSAXSFilterTransmission:
if not (0.0 < transmission <= 1.0):
raise ValueError("Transmission must be between 0 and 1.")
# --- Energy handling ---
# -------------------------------------------------------
# SAFETY CHECK (before any calculation/motion):
# Only allow fil_trans < 1 when DMM is in THROUGH (both)
# and CCM energy > 1 keV. fil_trans(1) is always allowed.
# -------------------------------------------------------
if transmission < 1.0:
try:
dmm_trans = float(epics_get("X12SA-OP-DMM-EMLS-3010:THRU"))
except Exception:
dmm_trans = -1
try:
dmm_rot = float(epics_get("X12SA-OP-DMM-EMLS-3030:THRU"))
except Exception:
dmm_rot = -1
try:
ccm_energy = float(epics_get("X12SA-OP-CCM1:ENERGY-GET"))
except Exception:
ccm_energy = -1
allowed = (dmm_trans == 1) and (dmm_rot == 1) and (ccm_energy > 1)
if not allowed:
print("\n⚠️ SAFETY WARNING: Reducing transmission (< 1) typically requires:")
print(" - DMM translation in THROUGH (THRU == 1)")
print(" - DMM rotation in THROUGH (THRU == 1)")
print(" - CCM energy > 1 keV")
print("\nCurrent state:")
print(f" DMM translation THRU : {dmm_trans}")
print(f" DMM rotation THRU : {dmm_rot}")
print(f" CCM energy (keV) : {ccm_energy}")
# Ask user (default = NO)
if hasattr(self, "OMNYTools") and hasattr(self.OMNYTools, "yesno"):
proceed = self.OMNYTools.yesno(
"Conditions not satisfied. Proceed anyway?",
default="n",
)
else:
# Safe fallback
proceed = False
if not proceed:
print("Aborted. Transmission unchanged.")
return None
# --- Energy handling (EPICS only) ---
if energy_kev is None:
try:
energy_kev = float(dev.mokev.read()) # using global dev
energy_kev = float(epics_get("X12SA-OP-CCM1:ENERGY-GET"))
except Exception as exc:
raise RuntimeError(
"Energy not specified and could not read current beam energy."
"Energy not specified and could not read EPICS PV "
"'X12SA-OP-CCM1:ENERGY-GET'."
) from exc
else:
energy_kev = float(energy_kev)
# --- Summary header ---
print("\nExposure-box filter transmission request")
print("-" * 60)
@@ -221,20 +278,23 @@ class cSAXSFilterTransmission:
# --- Dry run prompt ---
if print_only:
print("\n[DRY RUN] No motion executed yet.")
if self.OMNYTools.yesno(
"Execute motion to the selected filter combination now?",
"y", # default YES
):
self._execute_combination(best, energy_kev)
if hasattr(self, "OMNYTools") and hasattr(self.OMNYTools, "yesno"):
if self.OMNYTools.yesno(
"Execute motion to the selected filter combination now?",
"y", # default YES
):
self._execute_combination(best, energy_kev)
else:
print("Execution skipped.")
else:
print("Execution skipped.")
# If yesno not available, default to 'skip' on print_only
print("No interactive prompt available. Execution skipped (print_only=True).")
return None
# --- Execute motion directly ---
self._execute_combination(best, energy_kev)
return None
# -----------------------------
# Physics helpers
# -----------------------------
@@ -522,13 +582,18 @@ class cSAXSFilterTransmission:
print("ERROR: Global 'dev' object not found.")
return
# Determine energy
# --- Energy handling (EPICS only) ---
if energy_kev is None:
try:
energy_kev = float(dev.mokev.read())
except Exception:
print("WARNING: Could not read current beam energy. Assuming 6.2 keV.")
energy_kev = 6.2
energy_kev = float(epics_get("X12SA-OP-CCM1:ENERGY-GET"))
except Exception as exc:
raise RuntimeError(
"Energy not specified and could not read EPICS PV "
"'X12SA-OP-CCM1:ENERGY-GET'."
) from exc
else:
energy_kev = float(energy_kev)
print("\nCurrent filter transmission report")
print("-" * 60)

View File

@@ -0,0 +1,85 @@
############################################################
#################### OWIS LTM80 ############################
############################################################
samx:
description: Owis motor stage samx
deviceClass: ophyd_devices.devices.psi_motor.EpicsUserMotorVME
deviceConfig:
prefix: X12SA-ES2-ES02
motor_resolution: 0.00125
base_velocity: 0.0625
velocity: 10
backlash_distance: 0.125
acceleration: 0.2
user_offset_dir: 0
deviceTags:
- cSAXS
- owis_samx
onFailure: buffer
enabled: true
readoutPriority: baseline
softwareTrigger: false
############################################################
#################### OWIS Rotation DMT65 ###################
############################################################
rotx:
description: Rotation stage rotx
deviceClass: ophyd_devices.devices.psi_motor.EpicsUserMotorVME
deviceConfig:
prefix: X12SA-ES2-ES03
motor_resolution: 0.0025
base_velocity: 0.5
velocity: 7.5
backlash_distance: 0.25
acceleration: 0.2
user_offset_dir: 1
limits:
- -0.1
- 0.1
deviceTags:
- cSAXS
- rotx
onFailure: buffer
enabled: true
readoutPriority: baseline
softwareTrigger: false
############################################################
#################### npoint motors #########################
############################################################
npx:
description: nPoint x axis on the big npoint controller
deviceClass: csaxs_bec.devices.npoint.npoint.NPointAxis
deviceConfig:
axis_Id: A
host: "nPoint000003.psi.ch"
limits:
- -50
- 50
port: 23
sign: 1
enabled: true
onFailure: buffer
readOnly: false
readoutPriority: baseline
deviceTags:
- npoint
npy:
description: nPoint y axis on the big npoint controller
deviceClass: csaxs_bec.devices.npoint.npoint.NPointAxis
deviceConfig:
axis_Id: B
host: "nPoint000003.psi.ch"
limits:
- -50
- 50
port: 23
sign: 1
enabled: true
onFailure: buffer
readOnly: false
readoutPriority: baseline
deviceTags:
- npoint