|
1 | 1 | """Muon scan that uses two DAEs to scan a magnet."""
|
2 | 2 |
|
3 |
| -import os |
4 | 3 | from collections.abc import Generator
|
5 | 4 |
|
6 | 5 | import bluesky.plans as bp
|
7 |
| -import matplotlib |
8 | 6 | import matplotlib.pyplot as plt
|
9 | 7 | from bluesky.callbacks import LiveFitPlot, LiveTable
|
10 | 8 | from bluesky.preprocessors import subs_decorator
|
11 | 9 | from bluesky.utils import Msg
|
| 10 | +from ibex_bluesky_core.callbacks import LiveFitLogger |
12 | 11 | from ophyd_async.plan_stubs import ensure_connected
|
13 | 12 |
|
14 | 13 | from ibex_bluesky_core.callbacks.fitting import LiveFit
|
15 |
| -from ibex_bluesky_core.callbacks.fitting.fitting_utils import Linear |
| 14 | +from ibex_bluesky_core.callbacks.fitting.fitting_utils import Gaussian |
16 | 15 | from ibex_bluesky_core.callbacks.plotting import LivePlot
|
17 |
| -from ibex_bluesky_core.devices.block import block_rw_rbv |
| 16 | +from ibex_bluesky_core.devices.block import block_rw_rbv, BlockWriteConfig |
18 | 17 | from ibex_bluesky_core.devices.simpledae import SimpleDae
|
19 | 18 | from ibex_bluesky_core.devices.simpledae.controllers import (
|
20 | 19 | RunPerPointController,
|
21 | 20 | )
|
22 | 21 | from ibex_bluesky_core.devices.simpledae.reducers import (
|
23 |
| - GoodFramesNormalizer, |
| 22 | + PeriodGoodFramesNormalizer, |
24 | 23 | )
|
25 | 24 | from ibex_bluesky_core.devices.simpledae.waiters import GoodFramesWaiter
|
26 | 25 | from ibex_bluesky_core.plan_stubs import call_qt_aware
|
27 |
| -from ibex_bluesky_core.run_engine import get_run_engine |
28 | 26 |
|
29 |
| -NUM_POINTS: int = 3 |
30 |
| - |
31 |
| - |
32 |
| -def two_dae_scan() -> Generator[Msg, None, None]: |
33 |
| - """Scan a block using two DAEs.""" |
34 |
| - magnet = block_rw_rbv(float, "p3") |
| 27 | +from ibex_bluesky_core.callbacks.file_logger import HumanReadableFileCallback |
| 28 | + |
| 29 | + |
| 30 | +def two_dae_scan( |
| 31 | + magnet_1_block, |
| 32 | + start_1, |
| 33 | + stop_1, |
| 34 | + magnet_2_block, |
| 35 | + start_2, |
| 36 | + stop_2, |
| 37 | + num, |
| 38 | + frames=500, |
| 39 | + save_run=True, |
| 40 | + magnet_tolerance=0.01, |
| 41 | + magnet_settle_time=1, |
| 42 | + dae_1_prefix="IN:ARGUS:", |
| 43 | + dae_2_prefix="IN:CHRONUS:", |
| 44 | + spectra_total_1=96, |
| 45 | + spectra_total_2=32, |
| 46 | +) -> Generator[Msg, None, None]: |
| 47 | + """Scan a block using two DAEs and two magnets.""" |
| 48 | + |
| 49 | + def check_within_tolerance(setpoint: float, actual: float) -> bool: |
| 50 | + return setpoint - magnet_tolerance <= actual <= setpoint + magnet_tolerance |
| 51 | + |
| 52 | + magnet_1 = block_rw_rbv( |
| 53 | + float, |
| 54 | + magnet_1_block, |
| 55 | + write_config=BlockWriteConfig( |
| 56 | + settle_time_s=magnet_settle_time, set_success_func=check_within_tolerance |
| 57 | + ), |
| 58 | + ) |
35 | 59 |
|
36 |
| - emu_prefix = "IN:EMU:" |
37 |
| - controller_emu = RunPerPointController(save_run=True) |
38 |
| - waiter_emu = GoodFramesWaiter(500) |
39 |
| - reducer_emu = GoodFramesNormalizer( |
40 |
| - prefix=emu_prefix, |
41 |
| - detector_spectra=[i for i in range(1, 100)], |
| 60 | + magnet_2 = block_rw_rbv( |
| 61 | + float, |
| 62 | + magnet_2_block, |
| 63 | + write_config=BlockWriteConfig( |
| 64 | + settle_time_s=magnet_settle_time, set_success_func=check_within_tolerance |
| 65 | + ), |
42 | 66 | )
|
43 | 67 |
|
44 |
| - dae_emu = SimpleDae( |
45 |
| - prefix=emu_prefix, |
46 |
| - controller=controller_emu, |
47 |
| - waiter=waiter_emu, |
48 |
| - reducer=reducer_emu, |
49 |
| - name="emu_dae", |
| 68 | + controller_1 = RunPerPointController(save_run=save_run) |
| 69 | + waiter_1 = GoodFramesWaiter(frames) |
| 70 | + reducer_1 = PeriodGoodFramesNormalizer( |
| 71 | + prefix=dae_1_prefix, |
| 72 | + detector_spectra=[i for i in range(1, spectra_total_1 + 1)], |
50 | 73 | )
|
51 | 74 |
|
52 |
| - musr_prefix = "IN:MUSR:" |
| 75 | + dae_1 = SimpleDae( |
| 76 | + prefix=dae_1_prefix, |
| 77 | + controller=controller_1, |
| 78 | + waiter=waiter_1, |
| 79 | + reducer=reducer_1, |
| 80 | + name="dae_1", |
| 81 | + ) |
53 | 82 |
|
54 |
| - controller_musr = RunPerPointController(save_run=True) |
55 |
| - waiter_musr = GoodFramesWaiter(500) |
56 |
| - reducer_musr = GoodFramesNormalizer( |
57 |
| - prefix=musr_prefix, |
58 |
| - detector_spectra=[i for i in range(1, 96)], |
| 83 | + controller_2 = RunPerPointController(save_run=save_run) |
| 84 | + waiter_2 = GoodFramesWaiter(frames) |
| 85 | + reducer_2 = PeriodGoodFramesNormalizer( |
| 86 | + prefix=dae_2_prefix, |
| 87 | + detector_spectra=[i for i in range(1, spectra_total_2 + 1)], |
59 | 88 | )
|
60 | 89 |
|
61 |
| - dae_musr = SimpleDae( |
62 |
| - prefix=musr_prefix, |
63 |
| - controller=controller_musr, |
64 |
| - waiter=waiter_musr, |
65 |
| - reducer=reducer_musr, |
66 |
| - name="musr_dae", |
| 90 | + dae_2 = SimpleDae( |
| 91 | + prefix=dae_2_prefix, |
| 92 | + controller=controller_2, |
| 93 | + waiter=waiter_2, |
| 94 | + reducer=reducer_2, |
| 95 | + name="dae_2", |
67 | 96 | )
|
68 | 97 |
|
69 | 98 | _, ax = yield from call_qt_aware(plt.subplots)
|
70 | 99 |
|
71 |
| - lf = LiveFit( |
72 |
| - Linear.fit(), |
73 |
| - y=reducer_emu.intensity.name, |
74 |
| - x=magnet.name, |
75 |
| - yerr=reducer_emu.intensity_stddev.name, |
| 100 | + lf_1 = LiveFit( |
| 101 | + Gaussian().fit(), |
| 102 | + y=reducer_1.intensity.name, |
| 103 | + x=magnet_1.name, |
| 104 | + yerr=reducer_1.intensity_stddev.name, |
| 105 | + ) |
| 106 | + lf_2 = LiveFit( |
| 107 | + Gaussian().fit(), |
| 108 | + y=reducer_2.intensity.name, |
| 109 | + x=magnet_1.name, |
| 110 | + yerr=reducer_2.intensity_stddev.name, |
76 | 111 | )
|
77 | 112 |
|
78 |
| - yield from ensure_connected(magnet, dae_emu, dae_musr, force_reconnect=True) |
| 113 | + yield from ensure_connected(magnet_1, magnet_2, dae_1, dae_2, force_reconnect=True) |
79 | 114 |
|
80 | 115 | @subs_decorator(
|
81 | 116 | [
|
82 |
| - LiveFitPlot(livefit=lf, ax=ax), |
| 117 | + LiveFitPlot(livefit=lf_1, ax=ax), |
| 118 | + LiveFitPlot(livefit=lf_2, ax=ax), |
83 | 119 | LivePlot(
|
84 |
| - y=reducer_emu.intensity.name, |
85 |
| - x=magnet.name, |
| 120 | + y=reducer_1.intensity.name, |
| 121 | + x=magnet_1.name, |
86 | 122 | marker="x",
|
87 | 123 | linestyle="none",
|
88 | 124 | ax=ax,
|
89 |
| - yerr=reducer_emu.intensity_stddev.name, |
| 125 | + yerr=reducer_1.intensity_stddev.name, |
90 | 126 | ),
|
91 | 127 | LivePlot(
|
92 |
| - y=reducer_musr.intensity.name, |
93 |
| - x=magnet.name, |
| 128 | + y=reducer_2.intensity.name, |
| 129 | + x=magnet_1.name, |
94 | 130 | marker="x",
|
95 | 131 | linestyle="none",
|
96 | 132 | ax=ax,
|
97 |
| - yerr=reducer_musr.intensity_stddev.name, |
| 133 | + yerr=reducer_2.intensity_stddev.name, |
98 | 134 | ),
|
99 | 135 | LiveTable(
|
100 | 136 | [
|
101 |
| - magnet.name, |
102 |
| - controller_emu.run_number.name, |
103 |
| - reducer_emu.intensity.name, |
104 |
| - reducer_emu.intensity_stddev.name, |
105 |
| - reducer_emu.det_counts.name, |
106 |
| - reducer_emu.det_counts_stddev.name, |
107 |
| - dae_emu.good_frames.name, |
108 |
| - controller_musr.run_number.name, |
109 |
| - reducer_musr.intensity.name, |
110 |
| - reducer_musr.intensity_stddev.name, |
111 |
| - reducer_musr.det_counts.name, |
112 |
| - reducer_musr.det_counts_stddev.name, |
113 |
| - dae_musr.good_frames.name, |
| 137 | + magnet_1.name, |
| 138 | + magnet_2.name, |
| 139 | + controller_1.run_number.name, |
| 140 | + reducer_1.intensity.name, |
| 141 | + reducer_1.intensity_stddev.name, |
| 142 | + reducer_1.det_counts.name, |
| 143 | + reducer_1.det_counts_stddev.name, |
| 144 | + dae_1.good_frames.name, |
| 145 | + controller_2.run_number.name, |
| 146 | + reducer_2.intensity.name, |
| 147 | + reducer_2.intensity_stddev.name, |
| 148 | + reducer_2.det_counts.name, |
| 149 | + reducer_2.det_counts_stddev.name, |
| 150 | + dae_2.good_frames.name, |
114 | 151 | ]
|
115 | 152 | ),
|
| 153 | + HumanReadableFileCallback( |
| 154 | + fields=[ |
| 155 | + magnet_1.name, |
| 156 | + magnet_2.name, |
| 157 | + controller_1.run_number.name, |
| 158 | + reducer_1.intensity.name, |
| 159 | + reducer_1.intensity_stddev.name, |
| 160 | + reducer_1.det_counts.name, |
| 161 | + reducer_1.det_counts_stddev.name, |
| 162 | + dae_1.good_frames.name, |
| 163 | + controller_2.run_number.name, |
| 164 | + reducer_2.intensity.name, |
| 165 | + reducer_2.intensity_stddev.name, |
| 166 | + reducer_2.det_counts.name, |
| 167 | + reducer_2.det_counts_stddev.name, |
| 168 | + dae_2.good_frames.name, |
| 169 | + ] |
| 170 | + ), |
| 171 | + LiveFitLogger( |
| 172 | + lf_1, |
| 173 | + x=magnet_1.name, |
| 174 | + y=reducer_1.intensity.name, |
| 175 | + yerr=reducer_1.intensity_stddev.name, |
| 176 | + postfix="lf_1", |
| 177 | + ), |
| 178 | + LiveFitLogger( |
| 179 | + lf_2, |
| 180 | + x=magnet_1.name, |
| 181 | + y=reducer_2.intensity.name, |
| 182 | + yerr=reducer_2.intensity_stddev.name, |
| 183 | + postfix="lf_2", |
| 184 | + ), |
116 | 185 | ]
|
117 | 186 | )
|
118 | 187 | def _inner() -> Generator[Msg, None, None]:
|
119 |
| - yield from bp.scan([dae_musr, dae_emu], magnet, 0, 10, num=NUM_POINTS) |
120 |
| - print(lf.result.fit_report()) |
| 188 | + yield from bp.scan( |
| 189 | + [dae_2, dae_1], magnet_1, start_1, stop_1, magnet_2, start_2, stop_2, num=num |
| 190 | + ) |
| 191 | + print(lf_1.result.fit_report()) |
| 192 | + print(lf_2.result.fit_report()) |
121 | 193 |
|
122 | 194 | yield from _inner()
|
123 |
| - |
124 |
| - |
125 |
| -if __name__ == "__main__" and not os.environ.get("FROM_IBEX") == "True": |
126 |
| - matplotlib.use("qtagg") |
127 |
| - plt.ion() |
128 |
| - RE = get_run_engine() |
129 |
| - RE(two_dae_scan()) |
130 |
| - input("Plan complete, press return to close plot and exit") |
|
0 commit comments