diff --git a/xtreme_bec/devices/pgm_otf.py b/xtreme_bec/devices/pgm_otf.py index 56d2419..1bbfbeb 100644 --- a/xtreme_bec/devices/pgm_otf.py +++ b/xtreme_bec/devices/pgm_otf.py @@ -2,7 +2,14 @@ from __future__ import annotations from ophyd import Component as Cpt from ophyd import Device, EpicsSignal, EpicsSignalRO, Kind -from ophyd_devices import AsyncSignal, DeviceStatus, PSIDeviceBase, StatusBase, TransitionStatus +from ophyd_devices import ( + AsyncSignal, + DeviceStatus, + ProgressSignal, + PSIDeviceBase, + StatusBase, + TransitionStatus, +) class PGMOtfControl(Device): @@ -62,10 +69,8 @@ class PGMOtf(PSIDeviceBase, PGMOtfControl): docs="Aggregated fdata signal from the PGM OTF scan.", ) - # FIXME: Once we have the proper energy readback, we should set up the progress update - # to use the energy progress between e1 and e2. - # energy = Cpt(EpicsSignalRO, "ENERGY_RBV", kind=Kind.omitted, auto_monitor=True) - # progress = Cpt(ProgressSignal) + energy = Cpt(EpicsSignalRO, "X07MA-PGM:rbkenergy", kind=Kind.omitted, auto_monitor=True) + progress = Cpt(ProgressSignal) ######################################## # Beamline Specific Implementations # @@ -118,10 +123,14 @@ class PGMOtf(PSIDeviceBase, PGMOtfControl): def on_complete(self) -> DeviceStatus | StatusBase | None: """Called to inquire if a device has completed a scans.""" + self.complete_status.add_callback( + lambda status: self.progress.put(value=100, max_value=100, done=True) + ) return self.complete_status def on_kickoff(self) -> DeviceStatus | StatusBase | None: """Called to kickoff a device for a fly scan. Has to be called explicitly.""" + self.progress.put(value=0, max_value=100, done=False) self.acquire.put(1, use_complete=True) def on_stop(self) -> None: @@ -131,6 +140,21 @@ class PGMOtf(PSIDeviceBase, PGMOtfControl): def on_destroy(self) -> None: """Called when the device is destroyed. Cleanup resources here.""" + def _get_progress(self) -> float: + """ + Get the current progress of the OTF scan. The progress is calculated + based on the energy range (e2 - e1) and the current energy readback. + + Returns: + float: The current progress as a percentage (0 to 100). + """ + e1 = self.e1.get() + e2 = self.e2.get() + energy_range = abs(e2 - e1) + current_energy = self.current_energy.get() + progress = (current_energy - e1) / energy_range * 100 + return progress + def _update_data(self, value, obj, **kwargs): """ Callback function to update the aggregated data signals when the raw signals change. @@ -144,3 +168,4 @@ class PGMOtf(PSIDeviceBase, PGMOtfControl): self.idata.put(value) case "raw_fdata": self.fdata.put(value) + self.progress.put(value=self._get_progress(), max_value=100, done=False)