feat(filters): accept fil_comb(1411) as well as fil_comb(1, 4, 1, 1)
CI for csaxs_bec / test (pull_request) Successful in 1m41s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m52s

The four-digit code is already the currency of this module: it is what
_all_combinations builds, what fil_trans prints as the selected
combination, and what _fil_trans_report prints for what is currently in
the beam. Requiring commas on the way back in meant reading a code off
the screen and retyping it as four separate arguments.

fil_comb now takes 1411, "1411", (1, 4, 1, 1) or [1, 4, 1, 1], so a
reported combination can be pasted straight back.

A code of the wrong length is rejected with the length it needs rather
than falling through to "expects 4 positions, got 1", which was the
unhelpful error a code would have produced before. bool is excluded from
the integer branch so fil_comb(True) does not quietly become "True".
Digits outside 1..6 are left to the existing per-unit range check, which
names the offending unit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017kLGTqTyXzTT4swt3CfTkV
This commit was merged in pull request #306.
This commit is contained in:
2026-08-30 12:47:26 +02:00
co-authored by Claude Opus 5
parent 0874ca3b38
commit d120740dbb
@@ -293,31 +293,55 @@ class cSAXSFilterTransmission:
as the SPEC fil_comb. Use this when a particular filter is wanted; use
fil_trans when a particular transmission is wanted.
The four slot numbers may also be given as a single code, which is the
form fil_trans prints and _fil_trans_report matches, so a reported
combination can be pasted straight back in.
Examples:
csaxs.fil_comb(1, 4, 1, 1) # Ti 400 only
csaxs.fil_comb(1, 2, 3, 1) # Si 200 (unit 2) + Si 1600 (unit 3)
csaxs.fil_comb(1, 1, 1, 1) # all out
csaxs.fil_comb(1411) # the same thing
csaxs.fil_comb(1, 2, 3, 1) # Si 234.6 (unit 2) + Si 1661.5 (unit 3)
csaxs.fil_comb(1111) # all out
Safety: identical to fil_trans. Any combination with transmission < 1
requires DMM through and the CCM active, or an explicit confirmation.
Args:
*positions: four slot numbers, one per unit, 1..6 (1 = out). A single
list or tuple of four is also accepted.
list, tuple, or four-digit code such as 1411 is also accepted.
energy_kev: photon energy. Read from the CCM energy PV if omitted.
print_only: dry run first and prompt before moving. Defaults to True.
"""
if not positions:
print("\nUsage example:")
print(" csaxs.fil_comb(1, 4, 1, 1) # one slot number per unit, 1 = out")
print(" csaxs.fil_comb(1411) # or the same as a single code")
print(" Use csaxs.fil_trans(T) to select by transmission instead.")
print("\nCurrent filter transmission:")
self._fil_trans_report(energy_kev=energy_kev)
return None
# Accept fil_comb([1, 4, 1, 1]) as well as fil_comb(1, 4, 1, 1)
if len(positions) == 1 and isinstance(positions[0], (list, tuple)):
positions = tuple(positions[0])
# Accept fil_comb(1411) and fil_comb("1411") -- the same four-digit code
# that fil_trans prints and _fil_trans_report matches -- as well as
# fil_comb(1, 4, 1, 1) and fil_comb([1, 4, 1, 1]).
if len(positions) == 1:
only = positions[0]
if isinstance(only, (list, tuple)):
positions = tuple(only)
elif isinstance(only, (int, str)) and not isinstance(only, bool):
digits = str(only).strip()
if not digits.isdigit():
raise ValueError(
f"Cannot read {only!r} as a filter combination. Give one slot "
f"number per unit, e.g. fil_comb(1, 4, 1, 1) or fil_comb(1411)."
)
if len(digits) != self._UNITS:
raise ValueError(
f"A filter code has exactly {self._UNITS} digits, one per unit; "
f"got {digits!r}. Slot numbers run 1..{self._PER_UNIT} with 1 = out, "
f"so fil_comb(1411) is unit 2 at position 4 and the rest out."
)
positions = tuple(digits)
# --- Energy handling (EPICS only) ---
if energy_kev is None: