Fix/tensor row device lookup #312
No Reviewers
Labels
Clear labels
issue::not confirmed
issue::not reproducible
issue::reproducible
priority::critical
priority::needed
priority::nice to have
scope::backend
scope::frontend
stage::in development
stage::on hold
stage::pre_release
stage::ready for review
stage::selected for development
stage::weekly backlog
type::bug
type::discussion
type::doc
type::feature
type::improvement
type::test
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
Used if an issue has not yet been confirmed by a developer
Used if an issue is not reproducible
Used if a developer was able to reproduce the issue
Should be done as soon as possible
An important update to the code base
Not really needed but a good improvement
An issue regarding the backend services
An issue regarding the user-facing services
This issue is currently being worked on
Something is blocking the development
For issues that have been merged into a pre-release branch and are waiting for their release.
For issues that have been resolved and are ready for review
This issue has been selected for development but has not been scheduled yet
This issue has been selected for development for the next development cycle
It's a bug!
A discussion is wanted/needed
Improvements to the documentation
A new feature
Neither a feature nor a bug but an improvement to the code base
Missing tests or improvements to the test suite
Something is not working
This issue or pull request already exists
New feature
Need some help
Something is wrong
More information is needed
This won't be fixed
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Assignees
acerbo_a (acerbo_a)
bec-gitea
debenjak_l (debenjak_l)
diaz (diaz)
divall_e (divall_e)
guizar_m (guizar_m)
haghta_s (haghta_s)
holler (holler)
lombosi_c (lombosi_c)
malu_s (malu_s)
menzel (menzel)
perl_d (perl_d)
usov_i (usov_i)
wakonig_k (wakonig_k)
wang_x1 (wang_x1)
wyzula_j (wyzula_j)
zamofing_t (zamofing_t)
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: bec/csaxs_bec#312
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The tensor branch of run_cont_grid_scan_for_table_row had never executed successfully. dev is already the device container — bec_lib binds dev = device_manager.devices — so dev.devices[name] asked DeviceContainer for a device literally called "devices" and raised DeviceConfigError before any motor moved.
Deployed at cSAXS on 2026-09-04; scan 725 completed with 6076 frames and both rotation axes moving — the first successful run of that branch.
Merged into current main: 101 failed / 545 passed / 12 skipped, against a baseline of 101 failed / 532 passed. The 101 are pre-existing motor-controller failures from a local ophyd_devices version skew, unchanged.
The tensor-tomography branch of run_cont_grid_scan_for_table_row has never worked. `dev` is already the device container -- bec_lib binds dev = device_manager.devices in the client namespace -- so dev.devices[name] asks DeviceContainer for a device literally called "devices" and its __getattr__ raises DeviceConfigError before any motor moves. Observed at the beamline on a tensor table using sgchi/sgphi as the rotation axes: --> 72 roty_motor = dev.devices[row["roty_axis"]] DeviceConfigError: Device devices does not exist. The failure is deterministic, so @scan_repeat(max_repeats=3, default=True) retried it three times, and the surrounding except reported only "Error while moving motors to starting position for sample ..." -- the traceback goes to SciLog and nowhere else, which is why this survived undetected. Adds tests/tests_macros, which had no equivalent: macros run in the client namespace and are not executed by any test, so mistakes in them reach the beamline unfiltered. The check parses each macro and flags dev.devices attribute access rather than matching text, so comments and docstrings that mention the pattern do not trip it. Verified to fail against the unfixed macro. The rotation axes themselves are not hard-coded: rotx_axis/roty_axis are row fields holding a device name chosen from the SAXS widget's positioner combo boxes. Only the four row keys are fixed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0148tn6uK6oiTH25mzLfJcycWhen a table row failed, the macro printed a headline, sent the actual error text to SciLog alone, and left both the SciLog post and the SMS unguarded. So the detail existed in exactly one place that nobody was watching, and if SciLog was unreachable its exception replaced the one being reported -- the bare `raise` at the end never ran. Combined with @scan_repeat retrying three times, a deterministic one-line DeviceConfigError produced three identical context-free messages and survived several hours of beamtime. Failures now go through _report_failure, which: - prints the exception type, message and full traceback to the console; - logs the same through bec_logger, so it reaches the log files AND Redis and is therefore visible in `bec-log-monitor` and afterwards in the logs, rather than only on whichever console ran the macro; - includes _row_context: sample, template, both scan axes with ranges and step sizes, exposure time, and for tensor rows the rotation axes and angles, so a report identifies the row without needing the table alongside it; - guards SciLog and SMS separately, each reporting its own failure without touching the original exception. The caller still re-raises, so scan_repeat and the queue behave as before. Tests cover the two masking cases that mattered -- an unreachable SciLog and a failing SMS must not replace the original error -- plus the tensor context and that no SMS is attempted without phone numbers. Not changed, but flagged: @scan_repeat(max_repeats=3, default=True) retries any error three times, including deterministic ones. The file's own TODO warns about this. It triples the noise while diagnosing a reliably failing scan. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0148tn6uK6oiTH25mzLfJcycThe previous commit added `logger = bec_logger.logger` at module level. The macro loader rejects any module-level ast.Assign (bec_lib.macro_update_handler.has_executable_code) and then refuses the whole file, so run_cont_grid_scan_for_table_row stopped being loaded at all: Macro file .../run_cont_grid_scan_for_table_row.py contains executable code at module level (line 16) and will not be loaded for security reasons. Imports, defs, classes, annotated assignments and docstrings are permitted; plain assignments are not. The logger is now fetched inside the functions. Adds a test that runs the real has_executable_code over every macro, so this is caught by the suite instead of by a WARNING in the log stream. Verified to fail when a module-level assignment is reintroduced. Noticed only because bec-log-monitor happened to be running at the time -- a refused macro is otherwise indistinguishable from one that was never installed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0148tn6uK6oiTH25mzLfJcyc