From a0555def4d5fb52e723ed2d0c35509bb5b0e5440 Mon Sep 17 00:00:00 2001 From: x12sa Date: Mon, 23 Mar 2026 15:48:17 +0100 Subject: [PATCH] changed progress dict to global variable --- .../plugins/flomni/flomni.py | 113 ++++++++++++++++-- .../plugins/flomni/gui_tools.py | 8 ++ 2 files changed, 113 insertions(+), 8 deletions(-) diff --git a/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py b/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py index e578b18..e300f32 100644 --- a/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py +++ b/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py @@ -1211,6 +1211,73 @@ class FlomniAlignmentMixin: return additional_correction_shift +class _ProgressProxy: + """Dict-like proxy that persists the flOMNI progress dict as a BEC global variable. + + Every read (`proxy["key"]`) fetches the current dict from the global var store, + and every write (`proxy["key"] = val`) fetches, updates, and saves it back. + This makes the progress state visible to all BEC client sessions via + ``client.get_global_var("tomo_progress")``. + """ + + _GLOBAL_VAR_KEY = "tomo_progress" + _DEFAULTS: dict = { + "subtomo": 0, + "subtomo_projection": 0, + "subtomo_total_projections": 1, + "projection": 0, + "total_projections": 1, + "angle": 0, + "tomo_type": 0, + } + + def __init__(self, client): + self._client = client + + # ------------------------------------------------------------------ + # Internal helpers + # ------------------------------------------------------------------ + def _load(self) -> dict: + val = self._client.get_global_var(self._GLOBAL_VAR_KEY) + if val is None: + return dict(self._DEFAULTS) + return val + + def _save(self, data: dict) -> None: + self._client.set_global_var(self._GLOBAL_VAR_KEY, data) + + # ------------------------------------------------------------------ + # Dict-like interface + # ------------------------------------------------------------------ + def __getitem__(self, key): + return self._load()[key] + + def __setitem__(self, key, value) -> None: + data = self._load() + data[key] = value + self._save(data) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self._load()!r})" + + def get(self, key, default=None): + return self._load().get(key, default) + + def update(self, *args, **kwargs) -> None: + """Update multiple fields in a single round-trip.""" + data = self._load() + data.update(*args, **kwargs) + self._save(data) + + def reset(self) -> None: + """Reset all progress fields to their default values.""" + self._save(dict(self._DEFAULTS)) + + def as_dict(self) -> dict: + """Return a plain copy of the current progress state.""" + return self._load() + + class Flomni( FlomniInitStagesMixin, FlomniSampleTransferMixin, @@ -1233,14 +1300,8 @@ class Flomni( self.corr_angle_y = [] self.corr_pos_y_2 = [] self.corr_angle_y_2 = [] - self.progress = {} - self.progress["subtomo"] = 0 - self.progress["subtomo_projection"] = 0 - self.progress["subtomo_total_projections"] = 1 - self.progress["projection"] = 0 - self.progress["total_projections"] = 1 - self.progress["angle"] = 0 - self.progress["tomo_type"] = 0 + self._progress_proxy = _ProgressProxy(self.client) + self._progress_proxy.reset() self.OMNYTools = OMNYTools(self.client) self.reconstructor = PtychoReconstructor(self.ptycho_reconstruct_foldername) self.tomo_id_manager = TomoIDManager() @@ -1296,6 +1357,42 @@ class Flomni( self.special_angles = [] self.special_angle_repeats = 1 + @property + def progress(self) -> _ProgressProxy: + """Proxy dict backed by the BEC global variable ``tomo_progress``. + + Readable from any BEC client session via:: + + client.get_global_var("tomo_progress") + + Individual fields can be read and written just like a regular dict:: + + flomni.progress["projection"] # read + flomni.progress["projection"] = 42 # write (persists immediately) + + To update multiple fields atomically use :py:meth:`_ProgressProxy.update`:: + + flomni.progress.update(projection=42, angle=90.0) + + To reset all fields to their defaults:: + + flomni.progress.reset() + """ + return self._progress_proxy + + @progress.setter + def progress(self, val: dict) -> None: + """Replace the entire progress dict. + + Accepts a plain :class:`dict` and persists it to the global var store. + Example:: + + flomni.progress = {"projection": 0, "total_projections": 100, ...} + """ + if not isinstance(val, dict): + raise TypeError(f"progress must be a dict, got {type(val).__name__!r}") + self._progress_proxy._save(val) + @property def tomo_shellstep(self): val = self.client.get_global_var("tomo_shellstep") diff --git a/csaxs_bec/bec_ipython_client/plugins/flomni/gui_tools.py b/csaxs_bec/bec_ipython_client/plugins/flomni/gui_tools.py index 653883f..329a4d3 100644 --- a/csaxs_bec/bec_ipython_client/plugins/flomni/gui_tools.py +++ b/csaxs_bec/bec_ipython_client/plugins/flomni/gui_tools.py @@ -223,6 +223,14 @@ class flomniGuiTools: self._flomnigui_update_progress() def _flomnigui_update_progress(self): + """Update the progress ring bar and center label from the current progress state. + + ``self.progress`` is backed by the BEC global variable ``tomo_progress`` + (see :class:`_ProgressProxy` in ``flomni.py``), so this method reflects + the live state that is also accessible from other BEC client sessions via:: + + client.get_global_var("tomo_progress") + """ main_progress_ring = self.progressbar.rings[0] subtomo_progress_ring = self.progressbar.rings[1] if self.progressbar is not None: