diff --git a/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py b/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py index f5d4695b..d013a68f 100644 --- a/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py +++ b/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py @@ -3118,12 +3118,27 @@ class Flomni( random_offset_x: float | None = None, random_offset_y: float | None = None, ): - """write the tomo reconstruct file for the reconstruction queue""" + """Write the tomo reconstruct file for the reconstruction queue. + + Normally called automatically at the end of tomo_scan_projection()/ + tomo_acquire_at_angle(), which keep self._current_scan_list up to + date with the scan number(s) of the projection just acquired + (possibly several, when stitching). When called directly -- e.g. + from the command line after a plain scans.flomni_fermat_scan(), + without going through either of those -- that cached list is either + stale (left over from an earlier tomo scan) or not set at all, so + fall back to just the most recently completed scan number. + """ bec = builtins.__dict__.get("bec") + next_scan_number = bec.queue.next_scan_number + last_scan_number = next_scan_number - 1 + scan_list = getattr(self, "_current_scan_list", None) + if not scan_list or scan_list[-1] != last_scan_number: + scan_list = [last_scan_number] self.reconstructor.folder_name = self.ptycho_reconstruct_foldername self.reconstructor.write( - scan_list=self._current_scan_list, - next_scan_number=bec.queue.next_scan_number, + scan_list=scan_list, + next_scan_number=next_scan_number, base_path=base_path, probe_file_propagation=probe_propagation, random_offset_x=random_offset_x, diff --git a/csaxs_bec/bec_ipython_client/plugins/omny/AI_docs/TODO_tomo_reconstruct_stale_scan_list.md b/csaxs_bec/bec_ipython_client/plugins/omny/AI_docs/TODO_tomo_reconstruct_stale_scan_list.md new file mode 100644 index 00000000..a6722d81 --- /dev/null +++ b/csaxs_bec/bec_ipython_client/plugins/omny/AI_docs/TODO_tomo_reconstruct_stale_scan_list.md @@ -0,0 +1,68 @@ +# TODO: OMNY.tomo_reconstruct() writes a stale/missing scan list + +Found while fixing the same bug in `Flomni.tomo_reconstruct()` +(`csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py:3114`, branch +`flomni_fixes_during_beamtimes`). Not applied to OMNY yet to avoid conflicting +with other in-progress OMNY changes on a separate branch — do it there. + +## The bug + +`OMNY.tomo_reconstruct()` (`csaxs_bec/bec_ipython_client/plugins/omny/omny.py:1217`) +names the reconstruction queue file from a fresh `bec.queue.next_scan_number` +(so the *filename* is always correct), but writes the file's *content* from +`self._current_scan_list`: + +```python +def tomo_reconstruct(self, base_path="~/Data10/specES1"): + """write the tomo reconstruct file for the reconstruction queue""" + bec = builtins.__dict__.get("bec") + base_path = os.path.expanduser(base_path) + ptycho_queue_path = Path(os.path.join(base_path, self.ptycho_reconstruct_foldername)) + ptycho_queue_path.mkdir(parents=True, exist_ok=True) + + last_scan_number = bec.queue.next_scan_number - 1 + ptycho_queue_file = os.path.abspath( + os.path.join(ptycho_queue_path, f"scan_{last_scan_number:05d}.dat") + ) + with open(ptycho_queue_file, "w") as queue_file: + scans = " ".join([str(scan) for scan in self._current_scan_list]) + queue_file.write(f"p.scan_number {scans}\n") + queue_file.write("p.check_nextscan_started 1\n") +``` + +`self._current_scan_list` is only kept up to date by whichever internal method +last ran and then called `tomo_reconstruct()` itself right after (the OMNY +equivalents of flomni's `tomo_scan_projection()`/`tomo_acquire_at_angle()` — +check where `_current_scan_list` is assigned in `omny.py` for the exact call +sites). Call `tomo_reconstruct()` directly from the command line instead — +e.g. after a plain fermat scan run by hand, not through those internal +flows — and the file gets written with whatever scan list happened to be +cached from the *previous* tomo scan (or raises `AttributeError` if none ran +yet this session). Filename right, content wrong/stale. + +## The fix (already applied to flomni, mirror it here) + +`Flomni.tomo_reconstruct()` now falls back to just the most recently +completed scan number whenever the cached list doesn't actually match it: + +```python +bec = builtins.__dict__.get("bec") +next_scan_number = bec.queue.next_scan_number +last_scan_number = next_scan_number - 1 +scan_list = getattr(self, "_current_scan_list", None) +if not scan_list or scan_list[-1] != last_scan_number: + scan_list = [last_scan_number] +``` + +Internal callers are unaffected (their cached list's last entry always equals +`next_scan_number - 1` at the point they call `tomo_reconstruct()`), while a +direct/standalone call now correctly falls back to `[last_scan_number]` +instead of writing stale content or crashing. + +Port the same `getattr(...)`/fallback logic into `OMNY.tomo_reconstruct()` +(note OMNY's version doesn't go through the shared `PtychoReconstructor` +class like flomni's does — it writes the file inline — so the fix applies +directly to the `scans = " ".join(...)` line, not to a shared `write()` +method). + +Not scoped/designed further here — just flagging it so it isn't lost.