docs(flomni): document at_each_angle hooks in the user manual and AI_docs
CI for csaxs_bec / test (push) Successful in 1m33s
CI for csaxs_bec / test (push) Successful in 1m33s
Adds a "Custom behavior at each projection angle" subsection to the Tomography section of the flOMNI user manual (docs/user/ptychography/flomni.md): what a hook function looks like, a polarizer-modulation example, and how to register/activate/deactivate/list/unregister one, with an explicit warning about resetting at_each_angle_hook before queuing a normal follow-up job. Also links it from the quick-start queueing section. AI_docs/TOMO_QUEUE_COMMAND_JOBS_PLAN.md gets a new section 3.4 recording the design decision (session-only registry, not a hardcoded one; a new _TOMO_SCAN_PARAM_NAMES entry, not a new job kind; the GUI param-snapshot leak found and fixed while wiring this up; no GUI widget yet). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -88,7 +88,7 @@ Several parameter sets can be queued and run one after another automatically, e.
|
||||
|
||||
If a queued scan is interrupted, the next call to `flomni.tomo_queue_execute()` resumes it automatically rather than starting over, then continues with the remaining entries.
|
||||
|
||||
The same queue can also hold **command jobs** that reconfigure the beamline between scans (e.g. change energy, then re-peak the undulator gap) instead of running a tomogram, so "scan A, reconfigure, scan B" runs unattended as one queue. See [Tomography](user.ptychography.flomni.tomography) below for the full command reference, including command jobs.
|
||||
The same queue can also hold **command jobs** that reconfigure the beamline between scans (e.g. change energy, then re-peak the undulator gap) instead of running a tomogram, so "scan A, reconfigure, scan B" runs unattended as one queue. A queued tomogram can also run custom code at each projection angle (e.g. moving a polarizer in and out between two exposures) via a registered **at_each_angle hook**. See [Tomography](user.ptychography.flomni.tomography) below for the full command reference, including command jobs and hooks.
|
||||
|
||||
#### If something went wrong…
|
||||
|
||||
@@ -406,6 +406,59 @@ whole job is either safe to redo from the top or it isn't:
|
||||
- If any step is not idempotent, you are asked whether to re-run the job from the top
|
||||
or mark it done as-is.
|
||||
|
||||
#### Custom behavior at each projection angle
|
||||
|
||||
By default, every projection in a tomo scan is a single ptychography scan at that
|
||||
angle. For cases that need something more — e.g. record a projection, move a
|
||||
polarizer in, record again, move it back out, at every angle — write a small Python
|
||||
function and register it as an **at_each_angle hook**. Once registered, it can be
|
||||
selected per tomo-queue job, so the whole modulated tomogram runs unattended along
|
||||
with any other queued jobs.
|
||||
|
||||
A hook is a function `func(flomni, angle)`, called once per projection angle instead
|
||||
of the normal acquisition:
|
||||
```python
|
||||
def polarizer_modulation(flomni, angle):
|
||||
flomni.tomo_scan_projection(angle, _internal=True)
|
||||
umv(dev.polarizer, "in")
|
||||
flomni.tomo_scan_projection(angle, _internal=True)
|
||||
umv(dev.polarizer, "out")
|
||||
```
|
||||
|
||||
| command | explanation |
|
||||
| --- | --- |
|
||||
| `flomni.register_at_each_angle_hook("name", func)` | Load a hook function under `name`. |
|
||||
| `flomni.at_each_angle_hook = "name"` | Activate it — the next tomo-queue job added will use it. |
|
||||
| `flomni.at_each_angle_hook = None` | Deactivate it — back to normal projections for the next job. |
|
||||
| `flomni.list_at_each_angle_hooks()` | Print the names of all currently registered hooks (the active one is marked). |
|
||||
| `flomni.unregister_at_each_angle_hook("name")` | Remove a hook by name. |
|
||||
|
||||
Example — queue a polarizer-modulated tomogram, then a normal one:
|
||||
```python
|
||||
flomni.register_at_each_angle_hook("polarizer_mod", polarizer_modulation)
|
||||
|
||||
flomni.tomo_parameters() # set up the scan parameters as usual
|
||||
flomni.at_each_angle_hook = "polarizer_mod" # activate the hook
|
||||
flomni.tomo_queue_add("polarizer run")
|
||||
|
||||
flomni.at_each_angle_hook = None # back to normal -- do not skip this!
|
||||
flomni.tomo_queue_add("plain follow-up scan")
|
||||
|
||||
flomni.tomo_queue_execute() # runs both, hook active only for the first
|
||||
```
|
||||
**Do not forget to reset `flomni.at_each_angle_hook = None`** before adding a job
|
||||
that should run normally — each queued job remembers whatever `at_each_angle_hook`
|
||||
was set to at the moment it was added (like every other tomo parameter), so a job
|
||||
added right after a hook-using one without resetting it first will silently run with
|
||||
that hook still active.
|
||||
|
||||
Registered hooks are **session-only** — they live in memory and do not survive a
|
||||
kernel restart. If `tomo_queue_execute()` reaches a job whose `at_each_angle_hook`
|
||||
isn't registered in the current session (e.g. after restarting BEC), it stops with a
|
||||
clear error rather than silently running a plain scan; re-run
|
||||
`register_at_each_angle_hook()` for that hook, then call `tomo_queue_execute()`
|
||||
again to resume.
|
||||
|
||||
### Sample storage and transfer
|
||||
|
||||
[See short version](user.ptychography.flomni.transfer)
|
||||
|
||||
Reference in New Issue
Block a user