diff --git a/doc/devices/dae.md b/doc/devices/dae.md index 3a9dcde7..76f68581 100644 --- a/doc/devices/dae.md +++ b/doc/devices/dae.md @@ -23,14 +23,15 @@ suitable; instead the [`Dae`](ibex_bluesky_core.devices.dae.Dae) class should be ```python from ibex_bluesky_core.utils import get_pv_prefix -from ibex_bluesky_core.devices.simpledae import SimpleDae, RunPerPointController, GoodFramesWaiter, GoodFramesNormalizer +from ibex_bluesky_core.devices.simpledae import SimpleDae, RunPerPointController, PeriodGoodFramesWaiter, PeriodGoodFramesNormalizer prefix = get_pv_prefix() # One DAE run for each scan point, save the runs after each point. controller = RunPerPointController(save_run=True) -# Wait for 500 good frames on each run -waiter = GoodFramesWaiter(500) +# Wait for 500 good frames on each run. +# Note despite using RunPerPointController here we are still using PeriodGoodFramesWaiter and PeriodGoodFramesNormalizer. +waiter = PeriodGoodFramesWaiter(500) # Sum spectra 1..99 inclusive, then normalize by total good frames -reducer = GoodFramesNormalizer( +reducer = PeriodGoodFramesNormalizer( prefix=prefix, detector_spectra=[i for i in range(1, 100)], ) @@ -161,22 +162,11 @@ DAE signals. For example, normalizing intensities are implemented as a reducer. A reducer may produce any number of reduced signals. -### {py:obj}`GoodFramesNormalizer` - -This normalizer sums a set of user-defined detector spectra, and then divides by the number -of good frames. - -Published signals: -- `simpledae.good_frames` - the number of good frames reported by the DAE -- `reducer.det_counts` - summed detector counts for all of the user-provided spectra -- `reducer.intensity` - normalized intensity (`det_counts / good_frames`) -- `reducer.det_counts_stddev` - uncertainty (standard deviation) of the summed detector counts -- `reducer.intensity_stddev` - uncertainty (standard deviation) of the normalised intensity - ### {py:obj}`PeriodGoodFramesNormalizer` -Equivalent to the `GoodFramesNormalizer` above, but uses good frames only from the current -period. This should be used if a controller which counts into multiple periods is being used. +Uses good frames only from the current period. +This should be used if a controller which counts into multiple periods is being used OR if a +controller counts into multiple runs. Published signals: - `simpledae.period.good_frames` - the number of good frames reported by the DAE @@ -345,20 +335,11 @@ Waits for a user-specified number of microamp-hours. Published signals: - `simpledae.good_uah` - actual good uAh for this run. -### GoodFramesWaiter - -[`GoodFramesWaiter`](ibex_bluesky_core.devices.simpledae.GoodFramesWaiter) - -Waits for a user-specified number of good frames (in total for the entire run) - -Published signals: -- `simpledae.good_frames` - actual good frames for this run. - ### PeriodGoodFramesWaiter [`PeriodGoodFramesWaiter`](ibex_bluesky_core.devices.simpledae.PeriodGoodFramesWaiter) -Waits for a user-specified number of good frames (in the current period) +Waits for a user-specified number of good frames (in the current period) - this should be used even if the controller is splitting up points into separate runs. Published signals: - `simpledae.period.good_frames` - actual period good frames for this run. diff --git a/manual_system_tests/dae_scan.py b/manual_system_tests/dae_scan.py index fc381730..5174e65e 100644 --- a/manual_system_tests/dae_scan.py +++ b/manual_system_tests/dae_scan.py @@ -13,8 +13,8 @@ from ibex_bluesky_core.callbacks import ISISCallbacks from ibex_bluesky_core.devices.block import block_rw_rbv from ibex_bluesky_core.devices.simpledae import ( - GoodFramesNormalizer, - GoodFramesWaiter, + PeriodGoodFramesNormalizer, + PeriodGoodFramesWaiter, RunPerPointController, SimpleDae, ) @@ -47,8 +47,8 @@ def dae_scan_plan() -> Generator[Msg, None, None]: block = block_rw_rbv(float, "mot") controller = RunPerPointController(save_run=True) - waiter = GoodFramesWaiter(500) - reducer = GoodFramesNormalizer( + waiter = PeriodGoodFramesWaiter(500) + reducer = PeriodGoodFramesNormalizer( prefix=prefix, detector_spectra=[i for i in range(1, 100)], ) diff --git a/src/ibex_bluesky_core/devices/simpledae/__init__.py b/src/ibex_bluesky_core/devices/simpledae/__init__.py index 60e91078..b9ba94db 100644 --- a/src/ibex_bluesky_core/devices/simpledae/__init__.py +++ b/src/ibex_bluesky_core/devices/simpledae/__init__.py @@ -18,7 +18,6 @@ from ibex_bluesky_core.devices.simpledae._reducers import ( VARIANCE_ADDITION, DSpacingMappingReducer, - GoodFramesNormalizer, MonitorNormalizer, PeriodGoodFramesNormalizer, PeriodSpecIntegralsReducer, @@ -35,7 +34,6 @@ Waiter, ) from ibex_bluesky_core.devices.simpledae._waiters import ( - GoodFramesWaiter, GoodUahWaiter, MEventsWaiter, PeriodGoodFramesWaiter, @@ -44,6 +42,11 @@ ) from ibex_bluesky_core.utils import get_pv_prefix +# For backwards compatibility. +# These were removed in https://github.com/ISISComputingGroup/ibex_bluesky_core/issues/136 +GoodFramesWaiter = PeriodGoodFramesWaiter +GoodFramesNormalizer = PeriodGoodFramesNormalizer + logger = logging.getLogger(__name__) __all__ = [ @@ -182,12 +185,12 @@ def monitor_normalising_dae( """ prefix = get_pv_prefix() + waiter = PeriodGoodFramesWaiter(frames) + if periods: controller = PeriodPerPointController(save_run=save_run) - waiter = PeriodGoodFramesWaiter(frames) else: controller = RunPerPointController(save_run=save_run) - waiter = GoodFramesWaiter(frames) reducer = MonitorNormalizer( prefix=prefix, diff --git a/src/ibex_bluesky_core/devices/simpledae/_reducers.py b/src/ibex_bluesky_core/devices/simpledae/_reducers.py index 1611aaae..963a8c6c 100644 --- a/src/ibex_bluesky_core/devices/simpledae/_reducers.py +++ b/src/ibex_bluesky_core/devices/simpledae/_reducers.py @@ -278,14 +278,6 @@ def denominator(self, dae: "SimpleDae") -> SignalR[int]: return dae.period.good_frames -class GoodFramesNormalizer(ScalarNormalizer): - """Sum a set of user-specified spectra, then normalize by total good frames.""" - - def denominator(self, dae: "SimpleDae") -> SignalR[int]: - """Get normalization denominator (total good frames).""" - return dae.good_frames - - class MonitorNormalizer(Reducer, StandardReadable): """Normalize a set of user-specified detector spectra by user-specified monitor spectra.""" diff --git a/src/ibex_bluesky_core/devices/simpledae/_waiters.py b/src/ibex_bluesky_core/devices/simpledae/_waiters.py index 59d1f562..63dbb085 100644 --- a/src/ibex_bluesky_core/devices/simpledae/_waiters.py +++ b/src/ibex_bluesky_core/devices/simpledae/_waiters.py @@ -60,14 +60,6 @@ def get_signal(self, dae: "SimpleDae") -> SignalR[int]: return dae.period.good_frames -class GoodFramesWaiter(SimpleWaiter[int]): - """Wait for good frames to reach a user-specified value.""" - - def get_signal(self, dae: "SimpleDae") -> SignalR[int]: - """Wait for good frames.""" - return dae.good_frames - - class GoodUahWaiter(SimpleWaiter[float]): """Wait for good microamp-hours to reach a user-specified value.""" diff --git a/tests/devices/simpledae/test_reducers.py b/tests/devices/simpledae/test_reducers.py index 8d852a85..f5aa9447 100644 --- a/tests/devices/simpledae/test_reducers.py +++ b/tests/devices/simpledae/test_reducers.py @@ -11,7 +11,6 @@ from ibex_bluesky_core.devices.simpledae import ( VARIANCE_ADDITION, - GoodFramesNormalizer, MonitorNormalizer, PeriodGoodFramesNormalizer, PeriodSpecIntegralsReducer, @@ -30,13 +29,6 @@ async def period_good_frames_reducer() -> PeriodGoodFramesNormalizer: return reducer -@pytest.fixture -async def good_frames_reducer() -> GoodFramesNormalizer: - reducer = GoodFramesNormalizer(prefix="", detector_spectra=[1, 2]) - await reducer.connect(mock=True) - return reducer - - # detector summer sum_spectra/default, monitor summer sum_spectra/default 1, 1 @pytest.fixture async def monitor_normalizer() -> MonitorNormalizer: @@ -340,24 +332,13 @@ def test_period_good_frames_normalizer_publishes_period_good_frames( assert period_good_frames_reducer.denominator(fake_dae) == fake_dae.period.good_frames -def test_good_frames_normalizer_publishes_good_frames( - good_frames_reducer: GoodFramesNormalizer, -): - fake_dae: SimpleDae = FakeDae() # type: ignore - readables = good_frames_reducer.additional_readable_signals(fake_dae) - assert fake_dae.good_uah not in readables - assert fake_dae.good_frames in readables - - assert good_frames_reducer.denominator(fake_dae) == fake_dae.good_frames - - def test_scalar_normalizer_publishes_uncertainties( simpledae: SimpleDae, - good_frames_reducer: GoodFramesNormalizer, + period_good_frames_reducer: PeriodGoodFramesNormalizer, ): - readables = good_frames_reducer.additional_readable_signals(simpledae) - assert good_frames_reducer.intensity_stddev in readables - assert good_frames_reducer.det_counts_stddev in readables + readables = period_good_frames_reducer.additional_readable_signals(simpledae) + assert period_good_frames_reducer.intensity_stddev in readables + assert period_good_frames_reducer.det_counts_stddev in readables async def test_period_good_frames_normalizer( diff --git a/tests/devices/simpledae/test_simpledae.py b/tests/devices/simpledae/test_simpledae.py index d4edfc6d..df501988 100644 --- a/tests/devices/simpledae/test_simpledae.py +++ b/tests/devices/simpledae/test_simpledae.py @@ -7,8 +7,9 @@ from ibex_bluesky_core.devices.dae import DaeCheckingSignal from ibex_bluesky_core.devices.simpledae import ( Controller, - GoodFramesNormalizer, GoodFramesWaiter, + GoodUahWaiter, + MonitorNormalizer, PeriodGoodFramesNormalizer, PeriodGoodFramesWaiter, PeriodPerPointController, @@ -181,15 +182,15 @@ def test_check_dae(): check_dae_strategies(dae, expected_controller=RunPerPointController) with pytest.raises( - TypeError, match=r"DAE waiter must be of type GoodFramesWaiter, got PeriodGoodFramesWaiter" + TypeError, match=r"DAE waiter must be of type GoodUahWaiter, got PeriodGoodFramesWaiter" ): - check_dae_strategies(dae, expected_waiter=GoodFramesWaiter) + check_dae_strategies(dae, expected_waiter=GoodUahWaiter) with pytest.raises( TypeError, - match=r"DAE reducer must be of type GoodFramesNormalizer, got PeriodGoodFramesNormalizer", + match=r"DAE reducer must be of type MonitorNormalizer, got PeriodGoodFramesNormalizer", ): - check_dae_strategies(dae, expected_reducer=GoodFramesNormalizer) + check_dae_strategies(dae, expected_reducer=MonitorNormalizer) # Should not raise check_dae_strategies( diff --git a/tests/devices/simpledae/test_waiters.py b/tests/devices/simpledae/test_waiters.py index 44cc3151..5e1053ef 100644 --- a/tests/devices/simpledae/test_waiters.py +++ b/tests/devices/simpledae/test_waiters.py @@ -4,7 +4,6 @@ from ophyd_async.testing import set_mock_value from ibex_bluesky_core.devices.simpledae import ( - GoodFramesWaiter, GoodUahWaiter, MEventsWaiter, PeriodGoodFramesWaiter, @@ -49,23 +48,6 @@ async def test_period_good_frames_waiter(simpledae: "SimpleDae"): assert waiter.get_signal(simpledae) == simpledae.period.good_frames -async def test_good_frames_waiter(simpledae: "SimpleDae"): - waiter = GoodFramesWaiter(5000) - - set_mock_value(simpledae.good_frames, 4999) - - with pytest.raises(asyncio.TimeoutError): - await asyncio.wait_for(waiter.wait(simpledae), timeout=SHORT_TIMEOUT) - - set_mock_value(simpledae.good_frames, 5000) - - # Check this returns - will raise a timeout error if not. - await asyncio.wait_for(waiter.wait(simpledae), timeout=SHORT_TIMEOUT) - - assert waiter.additional_readable_signals(simpledae) == [simpledae.good_frames] - assert waiter.get_signal(simpledae) == simpledae.good_frames - - async def test_mevents_waiter(simpledae: "SimpleDae"): waiter = MEventsWaiter(5000)