feat/auto-refresh stale at_each_angle hooks on redefinition

register_at_each_angle_hook() stores a function object by reference, so
editing a hook's def and forgetting to re-register left the old version
running silently -- easy to miss mid-beamtime. Detect it via
func.__globals__ (a redefined top-level def, or a reloaded module,
mutates the same namespace dict in place) and auto-adopt the new
definition with a printed note instead of failing or staying stale.

Centralizes the shared lookup/error logic (previously duplicated in
lamni.py and flomni.py) into TomoQueueMixin._resolve_at_each_angle_hook().

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
x01dc
2026-07-21 15:08:11 +02:00
co-authored by Claude Sonnet 5
parent f25eea9488
commit d963cd6dfd
6 changed files with 150 additions and 22 deletions
+16 -3
View File
@@ -515,9 +515,22 @@ again to resume.
**Editing a hook after registering it:** `register_at_each_angle_hook()` stores
whichever function object you pass it at that moment — it is not a live link to the
function's name. If you edit the function's source and re-run the `def` in your
session but do **not** call `register_at_each_angle_hook()` again, the *old* version
keeps running. Always re-register after an edit.
function's name. If you edit the function's source and re-run the `def` (in a cell,
or reload the file it's defined in — see below), the change is picked up
automatically the next time the hook runs, and a note is printed telling you so.
You don't need to call `register_at_each_angle_hook()` again after an edit.
**Recommended: define hooks in a file, not inline in the shell.** For anything
beyond a quick one-off, put the hook function in a `.py` file — ideally together
with the `tomo_queue_add()`/`at_each_angle_hook` calls that use it, so the file is a
single, compact record of exactly what ran during the experiment. Load it with
`import myhooks` (or `from myhooks import my_hook`) and, after editing, reload with
`importlib.reload(myhooks)` — the automatic pick-up described above still works,
because it detects the change via the module's own namespace, not the local name
you imported it under. `%run -i myhooks.py` also works (runs in the current
namespace, same as a cell). **Avoid plain `%run myhooks.py`** (without `-i`): it
executes in a fresh, throwaway namespace each time, so an edit-and-rerun is *not*
picked up automatically and the old version keeps running silently.
**`tomo_scan_projection()` vs `tomo_acquire_at_angle()`:** these are not
interchangeable. `tomo_scan_projection(angle)` always runs a full Fermat-scan
+16 -3
View File
@@ -282,9 +282,22 @@ again to resume.
**Editing a hook after registering it:** `register_at_each_angle_hook()` stores
whichever function object you pass it at that moment — it is not a live link to the
function's name. If you edit the function's source and re-run the `def` in your
session but do **not** call `register_at_each_angle_hook()` again, the *old* version
keeps running. Always re-register after an edit.
function's name. If you edit the function's source and re-run the `def` (in a cell,
or reload the file it's defined in — see below), the change is picked up
automatically the next time the hook runs, and a note is printed telling you so.
You don't need to call `register_at_each_angle_hook()` again after an edit.
**Recommended: define hooks in a file, not inline in the shell.** For anything
beyond a quick one-off, put the hook function in a `.py` file — ideally together
with the `tomo_queue_add()`/`at_each_angle_hook` calls that use it, so the file is a
single, compact record of exactly what ran during the experiment. Load it with
`import myhooks` (or `from myhooks import my_hook`) and, after editing, reload with
`importlib.reload(myhooks)` — the automatic pick-up described above still works,
because it detects the change via the module's own namespace, not the local name
you imported it under. `%run -i myhooks.py` also works (runs in the current
namespace, same as a cell). **Avoid plain `%run myhooks.py`** (without `-i`): it
executes in a fresh, throwaway namespace each time, so an edit-and-rerun is *not*
picked up automatically and the old version keeps running silently.
**GUI:** the tomo parameters panel has an "At-each-angle hook" dropdown, listing
whatever is currently registered from the CLI (`register_at_each_angle_hook()`) —