dls-dodal 1.56.0__py3-none-any.whl → 1.58.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dls_dodal-1.56.0.dist-info → dls_dodal-1.58.0.dist-info}/METADATA +2 -2
- {dls_dodal-1.56.0.dist-info → dls_dodal-1.58.0.dist-info}/RECORD +24 -22
- dodal/_version.py +2 -2
- dodal/beamlines/i03.py +2 -1
- dodal/beamlines/i04.py +15 -0
- dodal/beamlines/i17.py +37 -0
- dodal/beamlines/i19_2.py +9 -0
- dodal/beamlines/i22.py +3 -3
- dodal/beamlines/i24.py +2 -21
- dodal/common/beamlines/commissioning_mode.py +33 -0
- dodal/devices/baton.py +4 -0
- dodal/devices/i19/backlight.py +17 -0
- dodal/devices/i24/beam_center.py +1 -2
- dodal/devices/smargon.py +33 -16
- dodal/devices/thawer.py +17 -5
- dodal/devices/undulator.py +13 -9
- dodal/devices/webcam.py +1 -0
- dodal/devices/xbpm_feedback.py +12 -6
- dodal/testing/__init__.py +3 -0
- dodal/testing/setup.py +67 -0
- dodal/devices/i24/pilatus_metadata.py +0 -44
- dodal/devices/util/test_utils.py +0 -37
- {dls_dodal-1.56.0.dist-info → dls_dodal-1.58.0.dist-info}/WHEEL +0 -0
- {dls_dodal-1.56.0.dist-info → dls_dodal-1.58.0.dist-info}/entry_points.txt +0 -0
- {dls_dodal-1.56.0.dist-info → dls_dodal-1.58.0.dist-info}/licenses/LICENSE +0 -0
- {dls_dodal-1.56.0.dist-info → dls_dodal-1.58.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dls-dodal
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.58.0
|
|
4
4
|
Summary: Ophyd devices and other utils that could be used across DLS beamlines
|
|
5
5
|
Author-email: Dominic Oram <dominic.oram@diamond.ac.uk>, Joseph Ware <joseph.ware@diamond.ac.uk>, Oliver Silvester <Oliver.Silvester@diamond.ac.uk>, Noemi Frisina <noemi.frisina@diamond.ac.uk>
|
|
6
6
|
License: Apache License
|
|
@@ -215,7 +215,7 @@ Description-Content-Type: text/markdown
|
|
|
215
215
|
License-File: LICENSE
|
|
216
216
|
Requires-Dist: click
|
|
217
217
|
Requires-Dist: ophyd
|
|
218
|
-
Requires-Dist: ophyd-async[ca,pva]>=0.13.
|
|
218
|
+
Requires-Dist: ophyd-async[ca,pva]>=0.13.2
|
|
219
219
|
Requires-Dist: bluesky==1.14.2
|
|
220
220
|
Requires-Dist: pyepics
|
|
221
221
|
Requires-Dist: dataclasses-json
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
dls_dodal-1.
|
|
1
|
+
dls_dodal-1.58.0.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
|
|
2
2
|
dodal/__init__.py,sha256=Ksms_WJF8LTkbm38gEpm1jBpGqcQ8NGvmb2ZJlOE1j8,198
|
|
3
3
|
dodal/__main__.py,sha256=kP2S2RPitnOWpNGokjZ1Yq-1umOtp5sNOZk2B3tBPLM,111
|
|
4
|
-
dodal/_version.py,sha256
|
|
4
|
+
dodal/_version.py,sha256=0S_WOya-t7UDFMpZKDOCqr088G6Obb9i_ReErRJRu3o,706
|
|
5
5
|
dodal/cli.py,sha256=yi8dXOp0hqzlg4ZZXCRGU-LpDa_ydaropDjyREWbZ5Y,4152
|
|
6
6
|
dodal/log.py,sha256=Rt5O3hFZfMnJvQueZvgagQuXnPqHrFxhponOvVkpfrk,9871
|
|
7
7
|
dodal/utils.py,sha256=abGitd4FLpLnmckF7lUqOKYUL88r5Ex_NGSVgO4gOf4,19305
|
|
@@ -19,8 +19,8 @@ dodal/beamlines/b16.py,sha256=rK00hEj8KLGNkLZr9omAuoMz_DyLN9rK4eUQssETR9E,1703
|
|
|
19
19
|
dodal/beamlines/b18.py,sha256=ryxrGtcCdwoFgZ8ljWYgr1g9gKvoA7nxkARVxl1IE78,1189
|
|
20
20
|
dodal/beamlines/b21.py,sha256=mN21vnOBmnwzG695HuV7P5DkuTtU8joflJI-evOpgwc,3333
|
|
21
21
|
dodal/beamlines/i02_1.py,sha256=d2IyqFMgeaSEyZYm7GMSjTKr7_02SakyC_oARx-XwnY,1204
|
|
22
|
-
dodal/beamlines/i03.py,sha256=
|
|
23
|
-
dodal/beamlines/i04.py,sha256=
|
|
22
|
+
dodal/beamlines/i03.py,sha256=wYeOyVn7UKhj7NhoGSeiFzK3TduL6YHMIHg37tVmE18,16170
|
|
23
|
+
dodal/beamlines/i04.py,sha256=mRzHnKSKHVmJzs6fwpfBi0QSiry72ixYqa-bs96-0gU,13717
|
|
24
24
|
dodal/beamlines/i05.py,sha256=v4QKd8-neh4Og205oovm6NDRnAU6Oktu1WrxalXsI40,656
|
|
25
25
|
dodal/beamlines/i05_1.py,sha256=R6JFFg8Bj-Izw355mx3mOd4IDvJb5ipB4p7_S0I_4Z0,670
|
|
26
26
|
dodal/beamlines/i09.py,sha256=OrqOcVanJU4F7erRZZDkjLwV8VnLlUzz3LUduaCBgUc,1629
|
|
@@ -29,14 +29,15 @@ dodal/beamlines/i09_2.py,sha256=lyYO1rOaIsXNuVOL39Psh-8jQjkhQBXEQMpbXa-Zcw0,713
|
|
|
29
29
|
dodal/beamlines/i10.py,sha256=0rSWOlIihkDtq7ZZaJ5O2jkMBrteRYjl4Hhqe8EP1Yc,5697
|
|
30
30
|
dodal/beamlines/i11.py,sha256=rjb5iARfbToNzeP-gewYljTu0f__V7bYj3JkJ5bWkGE,4349
|
|
31
31
|
dodal/beamlines/i13_1.py,sha256=VYVqMN8-njy7YSI08gskRccT-K2paRC9edAx0ah-Cwo,1602
|
|
32
|
+
dodal/beamlines/i17.py,sha256=Nickt8CKQ9JcQ1D_ulNICUT4jjLF1Aib7D9jblSnzA4,987
|
|
32
33
|
dodal/beamlines/i18.py,sha256=FuU8G-q1piu6BRou-Shj3BQEbNtsF7CUsSIqqkvCKZc,3615
|
|
33
34
|
dodal/beamlines/i19_1.py,sha256=tg3eALJTn9p686VFV7GjfUvChGS1mrh8-98uzjdLj_g,2934
|
|
34
|
-
dodal/beamlines/i19_2.py,sha256=
|
|
35
|
+
dodal/beamlines/i19_2.py,sha256=qotmAulSL2zTLaoxG1Mf6UabeJV-X4iekL0cotTtTww,2929
|
|
35
36
|
dodal/beamlines/i19_optics.py,sha256=8hdlDAAMgFrhcXrp5xCPZtLUlrDUEC9VwKnnuUAMbbU,1150
|
|
36
37
|
dodal/beamlines/i20_1.py,sha256=Zsr1lsH7ySbOgK7RhMVMWzNWZAV-fuYW0iAjSEJZicY,2625
|
|
37
|
-
dodal/beamlines/i22.py,sha256=
|
|
38
|
+
dodal/beamlines/i22.py,sha256=009Tk5cYyHfmm1DfIwR562WzomXRvyv_5chiBbPgQUs,8100
|
|
38
39
|
dodal/beamlines/i23.py,sha256=ZXvPEiMA4mPbRTXOxvL1NcoVWDg4Deyl8k57cveDg90,3060
|
|
39
|
-
dodal/beamlines/i24.py,sha256=
|
|
40
|
+
dodal/beamlines/i24.py,sha256=FvK7MqC_dX_alUFMEoS8L4HACThky9lQ7w7rwy0gXdA,6259
|
|
40
41
|
dodal/beamlines/k11.py,sha256=sBOl-MLk7FMo10KFykuK5aLqH1zyW4FnI0XXmtQhUfg,978
|
|
41
42
|
dodal/beamlines/p38.py,sha256=lxFGzmQhth0JhOFbTrZd9LEbUgvKmQdMtiHDW6UJgDs,5763
|
|
42
43
|
dodal/beamlines/p45.py,sha256=tQ7EkWfr7o2okK7Prw1C7DNGYdKPU2ofqjm98wu_-G0,2158
|
|
@@ -57,13 +58,14 @@ dodal/common/watcher_utils.py,sha256=jWtXjr2a2NAcTy8A9OnvtB_hWh3GuuLvWxVWHouSvOs
|
|
|
57
58
|
dodal/common/beamlines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
59
|
dodal/common/beamlines/beamline_parameters.py,sha256=nYTy5TDYegvon6iNCxf7Uez3hbdu9GCoLUmJhRO1qhE,2665
|
|
59
60
|
dodal/common/beamlines/beamline_utils.py,sha256=UnDJlRs7p8srjv-peX05jHZBb8J2d2lPSyG9118x560,5286
|
|
61
|
+
dodal/common/beamlines/commissioning_mode.py,sha256=KL24Ia4IOkSxi7M4CKRRQQW0T3HUDpj7K3Y5_DtALRA,1314
|
|
60
62
|
dodal/common/beamlines/device_helpers.py,sha256=8sasAIFRDwo6ElHqLrXnpj_v7xcEg-29Zhey_e4r9u8,84
|
|
61
63
|
dodal/devices/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
62
64
|
dodal/devices/aperture.py,sha256=S7AoIoQg_kFxaQk7HUMijbm1kYkOEi2csbdj76kp1ys,427
|
|
63
65
|
dodal/devices/aperturescatterguard.py,sha256=FH2oru3DU-I6BwOJOVEgHdFplLKIIknxtEBUBAXZ_WA,13946
|
|
64
66
|
dodal/devices/apple2_undulator.py,sha256=KbAX1GstP01XOm-QpXlyWCJewfxXKKawnoqbsfsksyY,26265
|
|
65
67
|
dodal/devices/backlight.py,sha256=y40kR6N3qSFVLRaGU8CjJJpwv_hq2QALf_85fLQqras,1415
|
|
66
|
-
dodal/devices/baton.py,sha256=
|
|
68
|
+
dodal/devices/baton.py,sha256=315I_0V73_DYYVT0PBs0luVy4CMqdPo0kLvHBi12MIU,606
|
|
67
69
|
dodal/devices/bimorph_mirror.py,sha256=OGe6aCczG0gVco4OvIRLJVxn2kw5F2QG1e06uqhFLTw,4609
|
|
68
70
|
dodal/devices/collimation_table.py,sha256=64HunSPJH-L2gZdfIj_RYdOlOuwRFEfMHfLHzu4BAKI,1681
|
|
69
71
|
dodal/devices/common_dcm.py,sha256=8QSRE6Z10RQjfL3g4JZhyHRNI_aCKxWlzKSsDgiJHhE,3049
|
|
@@ -90,16 +92,16 @@ dodal/devices/robot.py,sha256=k4Vkjpd3R-wXWf6YbYC1225sSdjvTrZS54v5v6Qy_EU,7003
|
|
|
90
92
|
dodal/devices/s4_slit_gaps.py,sha256=4KdarIQoRqX4ry3LUS1Km7fkjUFahA0VuTd2DvYEqQ8,446
|
|
91
93
|
dodal/devices/scintillator.py,sha256=JresF8SY_-t1raibzR4f0UoMXnFi-Abh3ywGm2DjhKs,3003
|
|
92
94
|
dodal/devices/slits.py,sha256=b_7ku2sHlzhMHTvWrwiRwee6ufrbxNX9JB_Z0lvk15o,1105
|
|
93
|
-
dodal/devices/smargon.py,sha256=
|
|
95
|
+
dodal/devices/smargon.py,sha256=48oOBOKlsvPhlUlK41ozXzCMUKMp3QkQx-pVqKL2Xts,6569
|
|
94
96
|
dodal/devices/status.py,sha256=hVrJS1yooQo6PRumRACoIEh-SKBUKxvBlQl-MtLFUMQ,327
|
|
95
97
|
dodal/devices/synchrotron.py,sha256=OHBrTrm4K39XE8BrE9b_Jn_ZfMRyDp9CHCwvmiV-KOc,1989
|
|
96
98
|
dodal/devices/tetramm.py,sha256=qBu2ClXRM4RFO-y4C2pXVKsp5sX4VpOelbVHOAkkUHQ,8936
|
|
97
|
-
dodal/devices/thawer.py,sha256=
|
|
99
|
+
dodal/devices/thawer.py,sha256=HexahKZ1rUxF9jBMeULruqYt6I7fsl6OgXkvcxPQY3M,1963
|
|
98
100
|
dodal/devices/turbo_slit.py,sha256=xhcnhfbdcTYSYozogw6Li4fF4ofoPsc350rEyrRdaNE,1460
|
|
99
|
-
dodal/devices/undulator.py,sha256=
|
|
101
|
+
dodal/devices/undulator.py,sha256=SsgYvIEQUNs_zZiUPAzlw0yJPaSExdmBFltlq5ypbc8,5530
|
|
100
102
|
dodal/devices/watsonmarlow323_pump.py,sha256=xNwjoxW3NJIDkeDWHfb0A8Yj95_KKRXMD9AghvX-WLk,1337
|
|
101
|
-
dodal/devices/webcam.py,sha256=
|
|
102
|
-
dodal/devices/xbpm_feedback.py,sha256=
|
|
103
|
+
dodal/devices/webcam.py,sha256=UAx2KF0mKi6I-mJJUb5z56MHY-Wd89-tqyPcFbouQFg,2491
|
|
104
|
+
dodal/devices/xbpm_feedback.py,sha256=HKLY3k52FPe2G-EAg8ir2LSdeUuGvhRD73ibDZ4mjH8,1418
|
|
103
105
|
dodal/devices/aithre_lasershaping/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
104
106
|
dodal/devices/aithre_lasershaping/goniometer.py,sha256=-2ewYMcdzB1DqP9sMpr4L1i4KeTCrGAJfngAt9-eFWw,1005
|
|
105
107
|
dodal/devices/aithre_lasershaping/laser_robot.py,sha256=vy-I1ASYflFYIUYePhT2l3l7g2iekrIFzLxA0GLmKY8,717
|
|
@@ -181,6 +183,7 @@ dodal/devices/i13_1/merlin_controller.py,sha256=myfmByOEXyMrlJZfsjOxDHeGQVwZGfsR
|
|
|
181
183
|
dodal/devices/i18/KBMirror.py,sha256=W4R3TeulSjosUqAFIIznyWzje_Y2AoEf9f8N-NkisYM,710
|
|
182
184
|
dodal/devices/i18/diode.py,sha256=nk5kvn4LsbhczRpCwHOO0_jJTYOz7MP9qm_uvBWuv7c,1468
|
|
183
185
|
dodal/devices/i19/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
186
|
+
dodal/devices/i19/backlight.py,sha256=c3F8RTessUJmJHlCWATSj-W25qlkAttb-c95eS28lKs,662
|
|
184
187
|
dodal/devices/i19/beamstop.py,sha256=JkcvkEmcC3eY3GHrvYNGqv2yDwrfgdpWKVZJWSadWW8,715
|
|
185
188
|
dodal/devices/i19/blueapi_device.py,sha256=Tsl4vsREz7FM2d-kKJK-9tGrYbyKq4SLxnMlEKIM-g8,3966
|
|
186
189
|
dodal/devices/i19/diffractometer.py,sha256=QCEi0Gko6Ja9_ec2vfdazwMspknvX63jcz8hQ2XW1xo,1182
|
|
@@ -192,12 +195,11 @@ dodal/devices/i22/fswitch.py,sha256=kpgegs4Wv_weBSzbrlXLXqXOOZdzTn3X9k5PlEN5F6c,
|
|
|
192
195
|
dodal/devices/i22/nxsas.py,sha256=093GCM2H2LESt28RF-JfxEljJ8QzRPkL1ByXI2XVhoA,6012
|
|
193
196
|
dodal/devices/i24/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
194
197
|
dodal/devices/i24/aperture.py,sha256=dlH_g7OPTBc5QRMd-ADU3_GDTKh668kkMHo4k_JxUcY,770
|
|
195
|
-
dodal/devices/i24/beam_center.py,sha256=
|
|
198
|
+
dodal/devices/i24/beam_center.py,sha256=nQyOif6JtlU_qP7kZP-8wN1ldW81MIbFUykPC1bEm70,446
|
|
196
199
|
dodal/devices/i24/beamstop.py,sha256=6tbiQLlcTlp4PCPhHJ_mlHtkv0kz5ArQ99zg9rwTnrw,1133
|
|
197
200
|
dodal/devices/i24/dcm.py,sha256=l7qbJh2JKL-5ANlMYXDeU5EBYY6mDiLxn7kp_Z9KNaM,1206
|
|
198
201
|
dodal/devices/i24/dual_backlight.py,sha256=N0R7M1mHPRmQ4fks5lGU1wrXjOvcW_ZKIXaRoC8aLDE,2084
|
|
199
202
|
dodal/devices/i24/focus_mirrors.py,sha256=DYiYLpDw8FJ1LYHxLOxE_om5qGfUo2itzskgqhmQZlg,1763
|
|
200
|
-
dodal/devices/i24/pilatus_metadata.py,sha256=I-AR8vd67qf6p0vZnRPTv4aNPN5T4KpSt2Iog4_jvn0,1781
|
|
201
203
|
dodal/devices/i24/pmac.py,sha256=-HYf2HPzaqWvszp4T8TXohdp40-xmKqQq4V0mLvVri8,7028
|
|
202
204
|
dodal/devices/i24/vgonio.py,sha256=sxSmcYZayVJPJz_D_91j9PmNor7Tbl1RGQFRrdtESlw,533
|
|
203
205
|
dodal/devices/mx_phase1/beamstop.py,sha256=GeHLqHVf3XwJSszUHuxZ2JBwQlcDiFs6jVpdHuw7snM,3127
|
|
@@ -224,7 +226,6 @@ dodal/devices/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
|
|
|
224
226
|
dodal/devices/util/adjuster_plans.py,sha256=c40PFZpXFw0YmJLh9jU4VIb8vRxHyafZlmvprTKAOhM,824
|
|
225
227
|
dodal/devices/util/epics_util.py,sha256=4useFL8ngsVF08fhOn48BlnO4oh0T4sEKqjdS6mjvG0,4687
|
|
226
228
|
dodal/devices/util/lookup_tables.py,sha256=jH9f_D8JbTSqzL-RKHUWOORLt8lEoNQL3o9HpXE98TY,3476
|
|
227
|
-
dodal/devices/util/test_utils.py,sha256=tnKKmSBaHEyx-qTQjoR3COqraRMmTdRJe9s-pWjuTPk,1176
|
|
228
229
|
dodal/devices/xspress3/xspress3.py,sha256=OerapEy-IuK7EFz13B5z0BzBmESVl6pYUlqAWHIwJck,4555
|
|
229
230
|
dodal/devices/xspress3/xspress3_channel.py,sha256=w8tAx2lz5kJ_LeJ_eb_4o--Dtt8MRijsYNgDG6oEIVg,1626
|
|
230
231
|
dodal/devices/zebra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -250,11 +251,12 @@ dodal/plans/verify_undulator_gap.py,sha256=OcDN09-eCoMzsmhKGxvzsH5EapG2zYz0yGCqU
|
|
|
250
251
|
dodal/plans/wrapped.py,sha256=BPMw__RcWvk9v5XnhMsi9_k4KsDEbmXogzD2n1ecbUg,2098
|
|
251
252
|
dodal/plans/preprocessors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
252
253
|
dodal/plans/preprocessors/verify_undulator_gap.py,sha256=cBZEGq8TW1jrXFXB00iClQVXSEaE_jP_rHMY9WTgYyY,1813
|
|
253
|
-
dodal/testing/__init__.py,sha256=
|
|
254
|
+
dodal/testing/__init__.py,sha256=AUYZKAvVOs7ZvxO1dVhL0pDTleRO34FQlO5MNe_cwgU,96
|
|
255
|
+
dodal/testing/setup.py,sha256=8cQnrzE5MQD4Etf0eqMarmtr-opsUOMQww-k1V7DzIQ,2442
|
|
254
256
|
dodal/testing/electron_analyser/__init__.py,sha256=-lc1opD2dCv0x678-J-ApOhHtvEvcslfOQ7E613U8-Y,118
|
|
255
257
|
dodal/testing/electron_analyser/device_factory.py,sha256=tkMY6fW3iI02DTD1XXHi4lH6sjo8RHHZBGDHSuTdmNU,2243
|
|
256
|
-
dls_dodal-1.
|
|
257
|
-
dls_dodal-1.
|
|
258
|
-
dls_dodal-1.
|
|
259
|
-
dls_dodal-1.
|
|
260
|
-
dls_dodal-1.
|
|
258
|
+
dls_dodal-1.58.0.dist-info/METADATA,sha256=FL_laMKISMqDK1hq8tvlBEF1M-r4XhFjVYBfT8yya5E,16928
|
|
259
|
+
dls_dodal-1.58.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
260
|
+
dls_dodal-1.58.0.dist-info/entry_points.txt,sha256=bycw_EKUzup_rxfCetOwcauXV4kLln_OPpPT8jEnr-I,94
|
|
261
|
+
dls_dodal-1.58.0.dist-info/top_level.txt,sha256=xIozdmZk_wmMV4wugpq9-6eZs0vgADNUKz3j2UAwlhc,6
|
|
262
|
+
dls_dodal-1.58.0.dist-info/RECORD,,
|
dodal/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '1.
|
|
32
|
-
__version_tuple__ = version_tuple = (1,
|
|
31
|
+
__version__ = version = '1.58.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 58, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
dodal/beamlines/i03.py
CHANGED
|
@@ -261,6 +261,7 @@ def undulator(daq_configuration_path: str | None = None) -> Undulator:
|
|
|
261
261
|
f"{BeamlinePrefix(BL).insertion_prefix}-MO-SERVC-01:",
|
|
262
262
|
# evaluate here not as parameter default to enable post-import mocking
|
|
263
263
|
id_gap_lookup_table_path=f"{daq_configuration_path or DAQ_CONFIGURATION_PATH}/lookup/BeamLine_Undulator_toGap.txt",
|
|
264
|
+
baton=baton(),
|
|
264
265
|
)
|
|
265
266
|
|
|
266
267
|
|
|
@@ -333,7 +334,7 @@ def xbpm_feedback() -> XBPMFeedback:
|
|
|
333
334
|
"""Get the i03 XBPM feeback device, instantiate it if it hasn't already been.
|
|
334
335
|
If this is called when already instantiated in i03, it will return the existing object.
|
|
335
336
|
"""
|
|
336
|
-
return XBPMFeedback(f"{PREFIX.beamline_prefix}-EA-FDBK-01:")
|
|
337
|
+
return XBPMFeedback(f"{PREFIX.beamline_prefix}-EA-FDBK-01:", baton=baton())
|
|
337
338
|
|
|
338
339
|
|
|
339
340
|
@device_factory()
|
dodal/beamlines/i04.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from ophyd_async.core import Reference
|
|
2
|
+
|
|
1
3
|
from dodal.common.beamlines.beamline_parameters import get_beamline_parameters
|
|
2
4
|
from dodal.common.beamlines.beamline_utils import (
|
|
3
5
|
device_factory,
|
|
@@ -30,6 +32,7 @@ from dodal.devices.oav.oav_to_redis_forwarder import OAVToRedisForwarder
|
|
|
30
32
|
from dodal.devices.oav.pin_image_recognition import PinTipDetection
|
|
31
33
|
from dodal.devices.robot import BartRobot
|
|
32
34
|
from dodal.devices.s4_slit_gaps import S4SlitGaps
|
|
35
|
+
from dodal.devices.scintillator import Scintillator
|
|
33
36
|
from dodal.devices.smargon import Smargon
|
|
34
37
|
from dodal.devices.synchrotron import Synchrotron
|
|
35
38
|
from dodal.devices.thawer import Thawer
|
|
@@ -357,3 +360,15 @@ def pin_tip_detection() -> PinTipDetection:
|
|
|
357
360
|
If this is called when already instantiated in i04, it will return the existing object.
|
|
358
361
|
"""
|
|
359
362
|
return PinTipDetection(f"{PREFIX.beamline_prefix}-DI-OAV-01:")
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
@device_factory()
|
|
366
|
+
def scintillator() -> Scintillator:
|
|
367
|
+
"""Get the i04 scintillator device, instantiate it if it hasn't already been.
|
|
368
|
+
If this is called when already instantiated in i04, it will return the existing object.
|
|
369
|
+
"""
|
|
370
|
+
return Scintillator(
|
|
371
|
+
f"{PREFIX.beamline_prefix}-MO-SCIN-01:",
|
|
372
|
+
Reference(aperture_scatterguard()),
|
|
373
|
+
get_beamline_parameters(),
|
|
374
|
+
)
|
dodal/beamlines/i17.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""The I17 hardware doesn't exist yet, but this configuration file is useful for
|
|
2
|
+
creating plans in sm-bluesky as devices build up."""
|
|
3
|
+
|
|
4
|
+
from ophyd_async.core import StrictEnum
|
|
5
|
+
|
|
6
|
+
from dodal.common.beamlines.beamline_utils import (
|
|
7
|
+
device_factory,
|
|
8
|
+
)
|
|
9
|
+
from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
|
|
10
|
+
from dodal.devices.pgm import PGM
|
|
11
|
+
from dodal.devices.synchrotron import Synchrotron
|
|
12
|
+
from dodal.log import set_beamline as set_log_beamline
|
|
13
|
+
from dodal.utils import BeamlinePrefix, get_beamline_name
|
|
14
|
+
|
|
15
|
+
BL = get_beamline_name("i17")
|
|
16
|
+
PREFIX = BeamlinePrefix(BL)
|
|
17
|
+
set_log_beamline(BL)
|
|
18
|
+
set_utils_beamline(BL)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class I17Grating(StrictEnum):
|
|
22
|
+
AU_400 = "400 line/mm Au"
|
|
23
|
+
SI_400 = "400 line/mm Si"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@device_factory()
|
|
27
|
+
def synchrotron() -> Synchrotron:
|
|
28
|
+
return Synchrotron()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@device_factory(skip=True)
|
|
32
|
+
def pgm() -> PGM:
|
|
33
|
+
return PGM(
|
|
34
|
+
prefix=f"{PREFIX.beamline_prefix}-OP-PGM-01:",
|
|
35
|
+
grating=I17Grating,
|
|
36
|
+
gratingPv="NLINES2",
|
|
37
|
+
)
|
dodal/beamlines/i19_2.py
CHANGED
|
@@ -4,6 +4,7 @@ from dodal.common.beamlines.beamline_utils import (
|
|
|
4
4
|
from dodal.common.beamlines.beamline_utils import (
|
|
5
5
|
set_beamline as set_utils_beamline,
|
|
6
6
|
)
|
|
7
|
+
from dodal.devices.i19.backlight import BacklightPosition
|
|
7
8
|
from dodal.devices.i19.beamstop import BeamStop
|
|
8
9
|
from dodal.devices.i19.blueapi_device import HutchState
|
|
9
10
|
from dodal.devices.i19.diffractometer import FourCircleDiffractometer
|
|
@@ -75,3 +76,11 @@ def synchrotron() -> Synchrotron:
|
|
|
75
76
|
If this is called when already instantiated in i19-2, it will return the existing object.
|
|
76
77
|
"""
|
|
77
78
|
return Synchrotron()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@device_factory()
|
|
82
|
+
def backlight() -> BacklightPosition:
|
|
83
|
+
"""Get the i19-2 backlight device, instantiate it if it hasn't already been.
|
|
84
|
+
If this is called when already instantiated in i19-2, it will return the existing object.
|
|
85
|
+
"""
|
|
86
|
+
return BacklightPosition(prefix=f"{PREFIX.beamline_prefix}-EA-IOC-12:")
|
dodal/beamlines/i22.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
3
|
from ophyd_async.epics.adaravis import AravisDetector
|
|
4
|
-
from ophyd_async.epics.adcore import
|
|
4
|
+
from ophyd_async.epics.adcore import NDPluginBaseIO
|
|
5
5
|
from ophyd_async.epics.adpilatus import PilatusDetector
|
|
6
6
|
from ophyd_async.fastcs.panda import HDFPanda
|
|
7
7
|
|
|
@@ -103,7 +103,7 @@ def i0() -> TetrammDetector:
|
|
|
103
103
|
path_provider=get_path_provider(),
|
|
104
104
|
type="Cividec Diamond XBPM",
|
|
105
105
|
plugins={
|
|
106
|
-
"stats":
|
|
106
|
+
"stats": NDPluginBaseIO(
|
|
107
107
|
prefix=f"{PREFIX.beamline_prefix}-EA-XBPM-02:SumAll:"
|
|
108
108
|
)
|
|
109
109
|
},
|
|
@@ -117,7 +117,7 @@ def it() -> TetrammDetector:
|
|
|
117
117
|
path_provider=get_path_provider(),
|
|
118
118
|
type="PIN Diode",
|
|
119
119
|
plugins={
|
|
120
|
-
"stats":
|
|
120
|
+
"stats": NDPluginBaseIO(
|
|
121
121
|
prefix=f"{PREFIX.beamline_prefix}-EA-TTRM-02:SumAll:"
|
|
122
122
|
)
|
|
123
123
|
},
|
dodal/beamlines/i24.py
CHANGED
|
@@ -11,7 +11,6 @@ from dodal.devices.i24.beamstop import Beamstop
|
|
|
11
11
|
from dodal.devices.i24.dcm import DCM
|
|
12
12
|
from dodal.devices.i24.dual_backlight import DualBacklight
|
|
13
13
|
from dodal.devices.i24.focus_mirrors import FocusMirrorsMode
|
|
14
|
-
from dodal.devices.i24.pilatus_metadata import PilatusMetadata
|
|
15
14
|
from dodal.devices.i24.pmac import PMAC
|
|
16
15
|
from dodal.devices.i24.vgonio import VerticalGoniometer
|
|
17
16
|
from dodal.devices.motors import YZStage
|
|
@@ -100,8 +99,8 @@ def dcm() -> DCM:
|
|
|
100
99
|
If this is called when already instantiated in i24, it will return the existing object.
|
|
101
100
|
"""
|
|
102
101
|
return DCM(
|
|
103
|
-
prefix=f"{PREFIX.beamline_prefix}-DI-DCM-01",
|
|
104
|
-
motion_prefix=f"{PREFIX.beamline_prefix}-MO-DCM-01",
|
|
102
|
+
prefix=f"{PREFIX.beamline_prefix}-DI-DCM-01:",
|
|
103
|
+
motion_prefix=f"{PREFIX.beamline_prefix}-MO-DCM-01:",
|
|
105
104
|
)
|
|
106
105
|
|
|
107
106
|
|
|
@@ -188,21 +187,3 @@ def eiger_beam_center() -> DetectorBeamCenter:
|
|
|
188
187
|
f"{PREFIX.beamline_prefix}-EA-EIGER-01:CAM:",
|
|
189
188
|
"eiger_bc",
|
|
190
189
|
)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
@device_factory()
|
|
194
|
-
def pilatus_beam_center() -> DetectorBeamCenter:
|
|
195
|
-
"""A device for setting/reading the beamcenter from the pilatus on i24."""
|
|
196
|
-
return DetectorBeamCenter(
|
|
197
|
-
f"{PREFIX.beamline_prefix}-EA-PILAT-01:cam1:",
|
|
198
|
-
"pilatus_bc",
|
|
199
|
-
)
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
@device_factory()
|
|
203
|
-
def pilatus_metadata() -> PilatusMetadata:
|
|
204
|
-
"""A small pilatus driver device for figuring out the filename template."""
|
|
205
|
-
return PilatusMetadata(
|
|
206
|
-
f"{PREFIX.beamline_prefix}-EA-PILAT-01:",
|
|
207
|
-
"pilatus_meta",
|
|
208
|
-
)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Functions relating to commissioning mode.
|
|
2
|
+
|
|
3
|
+
Commissioning Mode can be enabled for a production beamline when there is no
|
|
4
|
+
beam. The intent is that when it is enabled, bluesky plans may be run without beam
|
|
5
|
+
and plans and devices will as far as is possible behave normally.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import bluesky.plan_stubs as bps
|
|
9
|
+
from bluesky.utils import MsgGenerator
|
|
10
|
+
from ophyd_async.core import SignalR
|
|
11
|
+
|
|
12
|
+
_commissioning_signal: SignalR | None = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def read_commissioning_mode() -> MsgGenerator[bool]:
|
|
16
|
+
"""Utility method for reading the commissioning mode state from the context
|
|
17
|
+
of a bluesky plan, where a baton may or may not be present, or
|
|
18
|
+
commissioning mode is provided by some other mechanism."""
|
|
19
|
+
if _commissioning_signal:
|
|
20
|
+
return (yield from bps.rd(_commissioning_signal))
|
|
21
|
+
else:
|
|
22
|
+
return False
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def set_commissioning_signal(signal: SignalR[bool] | None):
|
|
26
|
+
"""Commissioning mode is enabled by a PV which when set enables commissioning mode.
|
|
27
|
+
This allows beamline staff to ensure that commissioning mode is disabled prior
|
|
28
|
+
to production use, via their own 'good morning' startup scripts.
|
|
29
|
+
Args:
|
|
30
|
+
signal: The signal which will be read in order to determine whether
|
|
31
|
+
commissioning mode is enabled."""
|
|
32
|
+
global _commissioning_signal
|
|
33
|
+
_commissioning_signal = signal
|
dodal/devices/baton.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Annotated as A
|
|
2
2
|
|
|
3
3
|
from ophyd_async.core import (
|
|
4
|
+
SignalR,
|
|
4
5
|
SignalRW,
|
|
5
6
|
StandardReadable,
|
|
6
7
|
)
|
|
@@ -15,3 +16,6 @@ class Baton(StandardReadable, EpicsDevice):
|
|
|
15
16
|
current_user: A[
|
|
16
17
|
SignalRW[str], PvSuffix("CURRENT_USER"), Format.HINTED_UNCACHED_SIGNAL
|
|
17
18
|
]
|
|
19
|
+
commissioning: A[
|
|
20
|
+
SignalR[bool], PvSuffix("COMMISSIONING"), Format.HINTED_UNCACHED_SIGNAL
|
|
21
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from bluesky.protocols import Movable
|
|
2
|
+
from ophyd_async.core import AsyncStatus, StandardReadable
|
|
3
|
+
from ophyd_async.epics.core import epics_signal_rw
|
|
4
|
+
|
|
5
|
+
from dodal.common.enums import InOutUpper
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BacklightPosition(StandardReadable, Movable[InOutUpper]):
|
|
9
|
+
"""Device moves backlight to the IN or OUT position since controls side manages switching the light on/off"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, prefix: str, name: str = "") -> None:
|
|
12
|
+
self.position = epics_signal_rw(InOutUpper, f"{prefix}AD1:choiceButton")
|
|
13
|
+
super().__init__(name)
|
|
14
|
+
|
|
15
|
+
@AsyncStatus.wrap
|
|
16
|
+
async def set(self, value: InOutUpper):
|
|
17
|
+
await self.position.set(value, wait=True)
|
dodal/devices/i24/beam_center.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""A small temporary device to get the beam center positions
|
|
2
|
-
eiger or pilatus detector on i24"""
|
|
1
|
+
"""A small temporary device to get the beam center positions on i24"""
|
|
3
2
|
|
|
4
3
|
from ophyd_async.core import StandardReadable
|
|
5
4
|
from ophyd_async.epics.core import epics_signal_rw
|
dodal/devices/smargon.py
CHANGED
|
@@ -3,7 +3,7 @@ from collections.abc import Collection, Generator
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from enum import Enum
|
|
5
5
|
from math import isclose
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import TypedDict, cast
|
|
7
7
|
|
|
8
8
|
from bluesky import plan_stubs as bps
|
|
9
9
|
from bluesky.protocols import Movable
|
|
@@ -12,6 +12,7 @@ from ophyd_async.core import (
|
|
|
12
12
|
AsyncStatus,
|
|
13
13
|
Device,
|
|
14
14
|
StrictEnum,
|
|
15
|
+
set_and_wait_for_value,
|
|
15
16
|
wait_for_value,
|
|
16
17
|
)
|
|
17
18
|
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
@@ -104,15 +105,15 @@ class DeferMoves(StrictEnum):
|
|
|
104
105
|
OFF = "Defer Off"
|
|
105
106
|
|
|
106
107
|
|
|
107
|
-
class CombinedMove(TypedDict):
|
|
108
|
+
class CombinedMove(TypedDict, total=False):
|
|
108
109
|
"""A move on multiple axes at once using a deferred move"""
|
|
109
110
|
|
|
110
|
-
x:
|
|
111
|
-
y:
|
|
112
|
-
z:
|
|
113
|
-
omega:
|
|
114
|
-
phi:
|
|
115
|
-
chi:
|
|
111
|
+
x: float | None
|
|
112
|
+
y: float | None
|
|
113
|
+
z: float | None
|
|
114
|
+
omega: float | None
|
|
115
|
+
phi: float | None
|
|
116
|
+
chi: float | None
|
|
116
117
|
|
|
117
118
|
|
|
118
119
|
class Smargon(XYZStage, Movable):
|
|
@@ -123,6 +124,8 @@ class Smargon(XYZStage, Movable):
|
|
|
123
124
|
Robot loading can nudge these and lead to errors.
|
|
124
125
|
"""
|
|
125
126
|
|
|
127
|
+
DEFERRED_MOVE_SET_TIMEOUT = 5
|
|
128
|
+
|
|
126
129
|
def __init__(self, prefix: str, name: str = ""):
|
|
127
130
|
with self.add_children_as_readables():
|
|
128
131
|
self.chi = Motor(prefix + "CHI")
|
|
@@ -161,15 +164,29 @@ class Smargon(XYZStage, Movable):
|
|
|
161
164
|
|
|
162
165
|
@AsyncStatus.wrap
|
|
163
166
|
async def set(self, value: CombinedMove):
|
|
167
|
+
"""This will move all motion together in a deferred move.
|
|
168
|
+
|
|
169
|
+
Once defer_move is on, sets to any axis do not immediately move the axis. Instead
|
|
170
|
+
the setpoint will go to that value. Then, when defer_move is switched off all
|
|
171
|
+
axes will move at the same time. The put callbacks on the axes themselves will
|
|
172
|
+
only come back after the motion on that axis finished.
|
|
173
|
+
"""
|
|
164
174
|
await self.defer_move.set(DeferMoves.ON)
|
|
165
175
|
try:
|
|
166
|
-
|
|
167
|
-
for
|
|
168
|
-
if
|
|
169
|
-
|
|
176
|
+
finished_moving = []
|
|
177
|
+
for motor_name, new_setpoint in value.items():
|
|
178
|
+
if new_setpoint is not None and isinstance(new_setpoint, int | float):
|
|
179
|
+
axis: Motor = getattr(self, motor_name)
|
|
180
|
+
await axis.check_motor_limit(
|
|
181
|
+
await axis.user_setpoint.get_value(), new_setpoint
|
|
182
|
+
)
|
|
183
|
+
put_completion = await set_and_wait_for_value(
|
|
184
|
+
axis.user_setpoint,
|
|
185
|
+
new_setpoint,
|
|
186
|
+
timeout=self.DEFERRED_MOVE_SET_TIMEOUT,
|
|
187
|
+
wait_for_set_completion=False,
|
|
188
|
+
)
|
|
189
|
+
finished_moving.append(put_completion)
|
|
170
190
|
finally:
|
|
171
191
|
await self.defer_move.set(DeferMoves.OFF)
|
|
172
|
-
|
|
173
|
-
# switched back off so we cannot wait for them until this point.
|
|
174
|
-
# see https://github.com/DiamondLightSource/dodal/issues/1315
|
|
175
|
-
await asyncio.gather(*tasks)
|
|
192
|
+
await asyncio.gather(*finished_moving)
|
dodal/devices/thawer.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from asyncio import Task, create_task, sleep
|
|
1
|
+
from asyncio import CancelledError, Task, create_task, sleep
|
|
2
2
|
|
|
3
3
|
from bluesky.protocols import Movable, Stoppable
|
|
4
4
|
from ophyd_async.core import (
|
|
@@ -11,6 +11,8 @@ from ophyd_async.core import (
|
|
|
11
11
|
)
|
|
12
12
|
from ophyd_async.epics.core import epics_signal_rw
|
|
13
13
|
|
|
14
|
+
from dodal.log import LOGGER
|
|
15
|
+
|
|
14
16
|
|
|
15
17
|
class ThawingException(Exception):
|
|
16
18
|
pass
|
|
@@ -24,19 +26,29 @@ class ThawingTimer(Device, Stoppable, Movable[float]):
|
|
|
24
26
|
|
|
25
27
|
@AsyncStatus.wrap
|
|
26
28
|
async def set(self, value: float):
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
if self._thawing_task:
|
|
30
|
+
LOGGER.info("Thawing task already in progress, resetting timer")
|
|
31
|
+
self._thawing_task.cancel()
|
|
32
|
+
else:
|
|
33
|
+
LOGGER.info("Thawing started")
|
|
34
|
+
await self._control_signal_ref().set(OnOff.ON)
|
|
30
35
|
self._thawing_task = create_task(sleep(value))
|
|
31
36
|
try:
|
|
32
37
|
await self._thawing_task
|
|
33
|
-
|
|
38
|
+
except CancelledError:
|
|
39
|
+
LOGGER.info("Timer task cancelled.")
|
|
40
|
+
raise
|
|
41
|
+
else:
|
|
42
|
+
LOGGER.info("Thawing completed")
|
|
34
43
|
await self._control_signal_ref().set(OnOff.OFF)
|
|
35
44
|
|
|
36
45
|
@AsyncStatus.wrap
|
|
37
46
|
async def stop(self, *args, **kwargs):
|
|
38
47
|
if self._thawing_task:
|
|
39
48
|
self._thawing_task.cancel()
|
|
49
|
+
self._thawing_task = None
|
|
50
|
+
LOGGER.info("Thawer stopped.")
|
|
51
|
+
await self._control_signal_ref().set(OnOff.OFF)
|
|
40
52
|
|
|
41
53
|
|
|
42
54
|
class Thawer(StandardReadable, Stoppable):
|
dodal/devices/undulator.py
CHANGED
|
@@ -5,6 +5,7 @@ from bluesky.protocols import Movable
|
|
|
5
5
|
from numpy import ndarray
|
|
6
6
|
from ophyd_async.core import (
|
|
7
7
|
AsyncStatus,
|
|
8
|
+
Reference,
|
|
8
9
|
StandardReadable,
|
|
9
10
|
StandardReadableFormat,
|
|
10
11
|
soft_signal_r_and_setter,
|
|
@@ -15,6 +16,7 @@ from ophyd_async.epics.motor import Motor
|
|
|
15
16
|
from dodal.common.enums import EnabledDisabledUpper
|
|
16
17
|
from dodal.log import LOGGER
|
|
17
18
|
|
|
19
|
+
from .baton import Baton
|
|
18
20
|
from .util.lookup_tables import energy_distance_table
|
|
19
21
|
|
|
20
22
|
|
|
@@ -22,11 +24,6 @@ class AccessError(Exception):
|
|
|
22
24
|
pass
|
|
23
25
|
|
|
24
26
|
|
|
25
|
-
# Enable to allow testing when the beamline is down, do not change in production!
|
|
26
|
-
TEST_MODE = False
|
|
27
|
-
# will be made more generic in https://github.com/DiamondLightSource/dodal/issues/754
|
|
28
|
-
|
|
29
|
-
|
|
30
27
|
# The acceptable difference, in mm, between the undulator gap and the DCM
|
|
31
28
|
# energy, when the latter is converted to mm using lookup tables
|
|
32
29
|
UNDULATOR_DISCREPANCY_THRESHOLD_MM = 2e-3
|
|
@@ -54,6 +51,7 @@ class Undulator(StandardReadable, Movable[float]):
|
|
|
54
51
|
name: str = "",
|
|
55
52
|
poles: int | None = None,
|
|
56
53
|
length: float | None = None,
|
|
54
|
+
baton: Baton | None = None,
|
|
57
55
|
) -> None:
|
|
58
56
|
"""Constructor
|
|
59
57
|
|
|
@@ -64,6 +62,7 @@ class Undulator(StandardReadable, Movable[float]):
|
|
|
64
62
|
name (str, optional): Name for device. Defaults to "".
|
|
65
63
|
"""
|
|
66
64
|
|
|
65
|
+
self.baton_ref = Reference(baton) if baton else None
|
|
67
66
|
self.id_gap_lookup_table_path = id_gap_lookup_table_path
|
|
68
67
|
with self.add_children_as_readables():
|
|
69
68
|
self.gap_motor = Motor(prefix + "BLGAPMTR")
|
|
@@ -105,7 +104,8 @@ class Undulator(StandardReadable, Movable[float]):
|
|
|
105
104
|
|
|
106
105
|
async def raise_if_not_enabled(self):
|
|
107
106
|
access_level = await self.gap_access.get_value()
|
|
108
|
-
|
|
107
|
+
commissioning_mode = await self._is_commissioning_mode_enabled()
|
|
108
|
+
if access_level is EnabledDisabledUpper.DISABLED and not commissioning_mode:
|
|
109
109
|
raise AccessError("Undulator gap access is disabled. Contact Control Room")
|
|
110
110
|
|
|
111
111
|
async def _set_undulator_gap(self, energy_kev: float) -> None:
|
|
@@ -124,21 +124,25 @@ class Undulator(StandardReadable, Movable[float]):
|
|
|
124
124
|
f"Undulator gap mismatch. {difference:.3f}mm is outside tolerance.\
|
|
125
125
|
Moving gap to nominal value, {target_gap:.3f}mm"
|
|
126
126
|
)
|
|
127
|
-
|
|
127
|
+
commissioning_mode = await self._is_commissioning_mode_enabled()
|
|
128
|
+
if not commissioning_mode:
|
|
128
129
|
# Only move if the gap is sufficiently different to the value from the
|
|
129
|
-
# DCM lookup table AND we're not in
|
|
130
|
+
# DCM lookup table AND we're not in commissioning mode
|
|
130
131
|
await self.gap_motor.set(
|
|
131
132
|
target_gap,
|
|
132
133
|
timeout=STATUS_TIMEOUT_S,
|
|
133
134
|
)
|
|
134
135
|
else:
|
|
135
|
-
LOGGER.
|
|
136
|
+
LOGGER.warning("In test mode, not moving ID gap")
|
|
136
137
|
else:
|
|
137
138
|
LOGGER.debug(
|
|
138
139
|
"Gap is already in the correct place for the new energy value "
|
|
139
140
|
f"{energy_kev}, no need to ask it to move"
|
|
140
141
|
)
|
|
141
142
|
|
|
143
|
+
async def _is_commissioning_mode_enabled(self):
|
|
144
|
+
return self.baton_ref and await self.baton_ref().commissioning.get_value()
|
|
145
|
+
|
|
142
146
|
async def _get_gap_to_match_energy(self, energy_kev: float) -> float:
|
|
143
147
|
"""
|
|
144
148
|
get a 2d np.array from lookup table that
|
dodal/devices/webcam.py
CHANGED
dodal/devices/xbpm_feedback.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
from bluesky.protocols import Triggerable
|
|
2
|
-
from ophyd_async.core import AsyncStatus, Device, StrictEnum, observe_value
|
|
2
|
+
from ophyd_async.core import AsyncStatus, Device, Reference, StrictEnum, observe_value
|
|
3
3
|
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
4
4
|
|
|
5
5
|
from dodal.common.device_utils import periodic_reminder
|
|
6
|
+
from dodal.devices.baton import Baton
|
|
7
|
+
from dodal.log import LOGGER
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
class Pause(StrictEnum):
|
|
@@ -14,15 +16,19 @@ class XBPMFeedback(Device, Triggerable):
|
|
|
14
16
|
"""The XBPM feedback device is an IOC that moves the DCM, HFM and VFM to automatically
|
|
15
17
|
hold the beam into place, as measured by the XBPM sensor."""
|
|
16
18
|
|
|
17
|
-
def __init__(self, prefix: str, name: str = "") -> None:
|
|
19
|
+
def __init__(self, prefix: str, name: str = "", baton: Baton | None = None) -> None:
|
|
18
20
|
self.pos_ok = epics_signal_r(float, prefix + "XBPM2POSITION_OK")
|
|
19
21
|
self.pos_stable = epics_signal_r(float, prefix + "XBPM2_STABLE")
|
|
20
22
|
self.pause_feedback = epics_signal_rw(Pause, prefix + "FB_PAUSE")
|
|
23
|
+
self.baton_ref = Reference(baton) if baton else None
|
|
21
24
|
super().__init__(name=name)
|
|
22
25
|
|
|
23
26
|
@AsyncStatus.wrap
|
|
24
27
|
async def trigger(self):
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
if self.baton_ref and await self.baton_ref().commissioning.get_value():
|
|
29
|
+
LOGGER.warning("Commissioning mode enabled, ignoring feedback")
|
|
30
|
+
else:
|
|
31
|
+
async with periodic_reminder("Waiting for XBPM"):
|
|
32
|
+
async for value in observe_value(self.pos_stable):
|
|
33
|
+
if value:
|
|
34
|
+
return
|
dodal/testing/__init__.py
CHANGED
dodal/testing/setup.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from contextlib import ExitStack
|
|
2
|
+
|
|
3
|
+
from ophyd_async.core import Device
|
|
4
|
+
from ophyd_async.epics.motor import Motor
|
|
5
|
+
from ophyd_async.testing import (
|
|
6
|
+
callback_on_mock_put,
|
|
7
|
+
set_mock_value,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def patch_motor(
|
|
12
|
+
motor: Motor,
|
|
13
|
+
initial_position: float = 0,
|
|
14
|
+
deadband: float = 0.001,
|
|
15
|
+
velocity: float = 3,
|
|
16
|
+
max_velocity: float = 5,
|
|
17
|
+
low_limit_travel: float = float("-inf"),
|
|
18
|
+
high_limit_travel: float = float("inf"),
|
|
19
|
+
):
|
|
20
|
+
"""
|
|
21
|
+
Patch a mock motor with sensible default values so that it can still be used in
|
|
22
|
+
tests and plans without running into errors as default values are zero.
|
|
23
|
+
|
|
24
|
+
Parameters:
|
|
25
|
+
motor: The mock motor to set mock values with.
|
|
26
|
+
initial_position: The default initial position of the motor to be set.
|
|
27
|
+
deadband: The tolerance between readback value and demand setpoint which the
|
|
28
|
+
motor is considered at position.
|
|
29
|
+
velocity: Requested move speed when the mock motor moves.
|
|
30
|
+
max_velocity: The maximum allowable velocity that can be set for the motor.
|
|
31
|
+
low_limit_travel: The lower limit that the motor can move to.
|
|
32
|
+
high_limit_travel: The higher limit that the motor can move to.
|
|
33
|
+
"""
|
|
34
|
+
set_mock_value(motor.user_setpoint, initial_position)
|
|
35
|
+
set_mock_value(motor.user_readback, initial_position)
|
|
36
|
+
set_mock_value(motor.deadband, deadband)
|
|
37
|
+
set_mock_value(motor.motor_done_move, 1)
|
|
38
|
+
set_mock_value(motor.velocity, velocity)
|
|
39
|
+
set_mock_value(motor.max_velocity, max_velocity)
|
|
40
|
+
set_mock_value(motor.low_limit_travel, low_limit_travel)
|
|
41
|
+
set_mock_value(motor.high_limit_travel, high_limit_travel)
|
|
42
|
+
return callback_on_mock_put(
|
|
43
|
+
motor.user_setpoint,
|
|
44
|
+
lambda pos, *args, **kwargs: set_mock_value(motor.user_readback, pos),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def patch_all_motors(parent_device: Device):
|
|
49
|
+
"""
|
|
50
|
+
Check all children of a device and patch any motors with mock values.
|
|
51
|
+
|
|
52
|
+
Parameters:
|
|
53
|
+
parent_device: The device that hold motor(s) as children.
|
|
54
|
+
"""
|
|
55
|
+
motors = []
|
|
56
|
+
|
|
57
|
+
def recursively_find_motors(device: Device):
|
|
58
|
+
for _, child_device in device.children():
|
|
59
|
+
if isinstance(child_device, Motor):
|
|
60
|
+
motors.append(child_device)
|
|
61
|
+
recursively_find_motors(child_device)
|
|
62
|
+
|
|
63
|
+
recursively_find_motors(parent_device)
|
|
64
|
+
motor_patch_stack = ExitStack()
|
|
65
|
+
for motor in motors:
|
|
66
|
+
motor_patch_stack.enter_context(patch_motor(motor))
|
|
67
|
+
return motor_patch_stack
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"""A small temporary device to set and read the filename template from the pilatus"""
|
|
2
|
-
|
|
3
|
-
import re
|
|
4
|
-
|
|
5
|
-
from ophyd_async.core import StandardReadable, derived_signal_r
|
|
6
|
-
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class PilatusMetadata(StandardReadable):
|
|
10
|
-
def __init__(self, prefix: str, name: str = "") -> None:
|
|
11
|
-
self.filename = epics_signal_rw(str, prefix + "cam1:FileName")
|
|
12
|
-
self.template = epics_signal_r(str, prefix + "cam1:FileTemplate_RBV")
|
|
13
|
-
self.filenumber = epics_signal_r(int, prefix + "cam1:FileNumber_RBV")
|
|
14
|
-
with self.add_children_as_readables():
|
|
15
|
-
self.filename_template = derived_signal_r(
|
|
16
|
-
self._get_full_filename_template,
|
|
17
|
-
filename=self.filename,
|
|
18
|
-
filename_template=self.template,
|
|
19
|
-
file_number=self.filenumber,
|
|
20
|
-
)
|
|
21
|
-
super().__init__(name)
|
|
22
|
-
|
|
23
|
-
def _get_full_filename_template(
|
|
24
|
-
self, filename: str, filename_template: str, file_number: int
|
|
25
|
-
) -> str:
|
|
26
|
-
"""
|
|
27
|
-
Get the template file path by querying the detector PVs.
|
|
28
|
-
Mirror the construction that the PPU does.
|
|
29
|
-
|
|
30
|
-
Returns: A template string, with the image numbers replaced with '#'
|
|
31
|
-
"""
|
|
32
|
-
# Exploit fact that passing negative numbers will put the - before the 0's
|
|
33
|
-
expected_filename = str(
|
|
34
|
-
filename_template % (filename, f"{file_number:05d}_", -9)
|
|
35
|
-
)
|
|
36
|
-
# Now, find the -09 part of this
|
|
37
|
-
numberpart = re.search(r"(-0+9)", expected_filename)
|
|
38
|
-
assert numberpart is not None
|
|
39
|
-
template_fill = "#" * len(numberpart.group(0))
|
|
40
|
-
return (
|
|
41
|
-
expected_filename[: numberpart.start()]
|
|
42
|
-
+ template_fill
|
|
43
|
-
+ expected_filename[numberpart.end() :]
|
|
44
|
-
)
|
dodal/devices/util/test_utils.py
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
from contextlib import ExitStack
|
|
2
|
-
|
|
3
|
-
from ophyd_async.core import Device
|
|
4
|
-
from ophyd_async.epics.motor import Motor
|
|
5
|
-
from ophyd_async.testing import (
|
|
6
|
-
callback_on_mock_put,
|
|
7
|
-
set_mock_value,
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def patch_motor(motor: Motor, initial_position=0):
|
|
12
|
-
set_mock_value(motor.user_setpoint, initial_position)
|
|
13
|
-
set_mock_value(motor.user_readback, initial_position)
|
|
14
|
-
set_mock_value(motor.deadband, 0.001)
|
|
15
|
-
set_mock_value(motor.motor_done_move, 1)
|
|
16
|
-
set_mock_value(motor.velocity, 3)
|
|
17
|
-
set_mock_value(motor.max_velocity, 5)
|
|
18
|
-
return callback_on_mock_put(
|
|
19
|
-
motor.user_setpoint,
|
|
20
|
-
lambda pos, *args, **kwargs: set_mock_value(motor.user_readback, pos),
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def patch_all_motors(parent_device: Device):
|
|
25
|
-
motors = []
|
|
26
|
-
|
|
27
|
-
def recursively_find_motors(device: Device):
|
|
28
|
-
for _, child_device in device.children():
|
|
29
|
-
if isinstance(child_device, Motor):
|
|
30
|
-
motors.append(child_device)
|
|
31
|
-
recursively_find_motors(child_device)
|
|
32
|
-
|
|
33
|
-
recursively_find_motors(parent_device)
|
|
34
|
-
motor_patch_stack = ExitStack()
|
|
35
|
-
for motor in motors:
|
|
36
|
-
motor_patch_stack.enter_context(patch_motor(motor))
|
|
37
|
-
return motor_patch_stack
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|