dls-dodal 1.60.0__py3-none-any.whl → 1.61.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.60.0.dist-info → dls_dodal-1.61.0.dist-info}/METADATA +1 -1
- {dls_dodal-1.60.0.dist-info → dls_dodal-1.61.0.dist-info}/RECORD +36 -24
- dodal/_version.py +2 -2
- dodal/devices/apple2_undulator.py +85 -52
- dodal/devices/areadetector/__init__.py +0 -0
- dodal/devices/areadetector/plugins/__init__.py +0 -0
- dodal/devices/attenuator/__init__.py +0 -0
- dodal/devices/electron_analyser/abstract/__init__.py +2 -2
- dodal/devices/electron_analyser/abstract/base_detector.py +13 -26
- dodal/devices/electron_analyser/abstract/base_driver_io.py +5 -4
- dodal/devices/electron_analyser/abstract/base_region.py +28 -13
- dodal/devices/electron_analyser/detector.py +19 -31
- dodal/devices/electron_analyser/specs/driver_io.py +0 -1
- dodal/devices/electron_analyser/vgscienta/driver_io.py +0 -1
- dodal/devices/fast_grid_scan.py +14 -11
- dodal/devices/i04/murko_results.py +24 -12
- dodal/devices/i10/i10_apple2.py +15 -15
- dodal/devices/i10/rasor/__init__.py +0 -0
- dodal/devices/i11/__init__.py +0 -0
- dodal/devices/i15/__init__.py +0 -0
- dodal/devices/i15/focussing_mirror.py +4 -20
- dodal/devices/i15/jack.py +2 -10
- dodal/devices/i15/laue.py +1 -5
- dodal/devices/i15/multilayer_mirror.py +1 -5
- dodal/devices/i15/rail.py +1 -5
- dodal/devices/i18/__init__.py +0 -0
- dodal/devices/i22/__init__.py +0 -0
- dodal/devices/i24/commissioning_jungfrau.py +9 -1
- dodal/devices/mx_phase1/__init__.py +0 -0
- dodal/devices/oav/snapshots/__init__.py +0 -0
- dodal/devices/xspress3/__init__.py +0 -0
- dodal/parameters/__init__.py +0 -0
- {dls_dodal-1.60.0.dist-info → dls_dodal-1.61.0.dist-info}/WHEEL +0 -0
- {dls_dodal-1.60.0.dist-info → dls_dodal-1.61.0.dist-info}/entry_points.txt +0 -0
- {dls_dodal-1.60.0.dist-info → dls_dodal-1.61.0.dist-info}/licenses/LICENSE +0 -0
- {dls_dodal-1.60.0.dist-info → dls_dodal-1.61.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.61.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
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
dls_dodal-1.
|
|
1
|
+
dls_dodal-1.61.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=R0nxjIENITg3eHoaeIFi4EMDLFAHK-E5jkMwqc20ybI,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
|
|
@@ -68,7 +68,7 @@ dodal/common/beamlines/device_helpers.py,sha256=8sasAIFRDwo6ElHqLrXnpj_v7xcEg-29
|
|
|
68
68
|
dodal/devices/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
69
|
dodal/devices/aperture.py,sha256=S7AoIoQg_kFxaQk7HUMijbm1kYkOEi2csbdj76kp1ys,427
|
|
70
70
|
dodal/devices/aperturescatterguard.py,sha256=FH2oru3DU-I6BwOJOVEgHdFplLKIIknxtEBUBAXZ_WA,13946
|
|
71
|
-
dodal/devices/apple2_undulator.py,sha256
|
|
71
|
+
dodal/devices/apple2_undulator.py,sha256=LjhU4ILkSrhnccHOwOrOT9HenowKmI0NFHLfpQk14lY,23035
|
|
72
72
|
dodal/devices/backlight.py,sha256=y40kR6N3qSFVLRaGU8CjJJpwv_hq2QALf_85fLQqras,1415
|
|
73
73
|
dodal/devices/baton.py,sha256=315I_0V73_DYYVT0PBs0luVy4CMqdPo0kLvHBi12MIU,606
|
|
74
74
|
dodal/devices/bimorph_mirror.py,sha256=OGe6aCczG0gVco4OvIRLJVxn2kw5F2QG1e06uqhFLTw,4609
|
|
@@ -80,7 +80,7 @@ dodal/devices/diamond_filter.py,sha256=hySd7HnLdplpPNvBrLddLjO_3LqgD8-99Zr__Sy_G
|
|
|
80
80
|
dodal/devices/eiger.py,sha256=ZKaRXF-YnYWuMW94BIg-gmdKW7JKmtMUvehF3S5XaLY,16670
|
|
81
81
|
dodal/devices/eiger_odin.py,sha256=1JoqPppTp99IZCiFOXJZB3h62xXRYKZINxTYXdLnT8c,7480
|
|
82
82
|
dodal/devices/eurotherm.py,sha256=rdLldmWYP1PZBckoya6svPy1mDxHYaa1IfMleMPGzD4,3832
|
|
83
|
-
dodal/devices/fast_grid_scan.py,sha256=
|
|
83
|
+
dodal/devices/fast_grid_scan.py,sha256=4HHOVAPwhUf4u1nC_kNhCAUzCqYuEsJ15lqcnxfdrVg,14659
|
|
84
84
|
dodal/devices/fluorescence_detector_motion.py,sha256=hJ1M9Zs6Dlw8DDL9APh7yVePlS4tU2hnlySd16hqfwE,346
|
|
85
85
|
dodal/devices/flux.py,sha256=1CDsq9yU2-ho8MfYBl50Tl9ABZwpUBHnV486PQXKNoQ,462
|
|
86
86
|
dodal/devices/focusing_mirror.py,sha256=2UWVrY6bs6_0i-h6JJ_LAUZPX_FgMzIx04JqZafdtYU,7464
|
|
@@ -111,8 +111,11 @@ dodal/devices/xbpm_feedback.py,sha256=HKLY3k52FPe2G-EAg8ir2LSdeUuGvhRD73ibDZ4mjH
|
|
|
111
111
|
dodal/devices/aithre_lasershaping/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
112
112
|
dodal/devices/aithre_lasershaping/goniometer.py,sha256=-2ewYMcdzB1DqP9sMpr4L1i4KeTCrGAJfngAt9-eFWw,1005
|
|
113
113
|
dodal/devices/aithre_lasershaping/laser_robot.py,sha256=vy-I1ASYflFYIUYePhT2l3l7g2iekrIFzLxA0GLmKY8,717
|
|
114
|
+
dodal/devices/areadetector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
114
115
|
dodal/devices/areadetector/plugins/CAM.py,sha256=sZzJm5Ez3eWfXZi_EB67wluhZmMQm1UyOc2bJFfzd1U,964
|
|
115
116
|
dodal/devices/areadetector/plugins/MJPG.py,sha256=QTsxCoWbofNpLMGPoOR2hWoM33KyntuLepbF0YmX0KE,3031
|
|
117
|
+
dodal/devices/areadetector/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
118
|
+
dodal/devices/attenuator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
116
119
|
dodal/devices/attenuator/attenuator.py,sha256=-rJYY_bHCDl8NVn3yYPytYIANiOPsz0f-3U1zBsT5pE,6246
|
|
117
120
|
dodal/devices/attenuator/filter.py,sha256=xb_8S62ktJdqdNE03PqhsfsTsQyTsRbR9CF1ksfX06M,542
|
|
118
121
|
dodal/devices/attenuator/filter_selections.py,sha256=k77EKESAlbA_ZUf1eNBdzMa8Xs8Mmmmb7XBkhipo3lE,1900
|
|
@@ -136,24 +139,24 @@ dodal/devices/detector/det_resolution.py,sha256=aQkKp24LpRGiwzPAQM3wLVa4ANw32Hdr
|
|
|
136
139
|
dodal/devices/detector/detector.py,sha256=DqQvlgdjIdKErrZqgM9IH7drc-r6N8nhkFk7KwlgYAk,4815
|
|
137
140
|
dodal/devices/detector/detector_motion.py,sha256=Ly4nz_AsB-_EDOADMC2u2J0dunpkOMbafVN_dgh3T-E,1389
|
|
138
141
|
dodal/devices/electron_analyser/__init__.py,sha256=mpC48s2fK58aEKI-Fl3CiYBb4tXgcaa4Msj8_jLpH8g,956
|
|
139
|
-
dodal/devices/electron_analyser/detector.py,sha256=
|
|
142
|
+
dodal/devices/electron_analyser/detector.py,sha256=FE8Qh7H01tej5GqWLXtCbiWo4n7OGm6q-QVViv-dqZ8,4749
|
|
140
143
|
dodal/devices/electron_analyser/energy_sources.py,sha256=NO3oxaVgmXnm6QuvyPBaeFbTjl3KwXzXY7EsdOhjATM,3152
|
|
141
144
|
dodal/devices/electron_analyser/enums.py,sha256=ruSH7LNRhtqMflv7gYxKeAu0uLzZIaoCai7sSTzpvkg,204
|
|
142
145
|
dodal/devices/electron_analyser/types.py,sha256=_kmdSp4E98fsusg5Wg-Hyo25zHYA_pMe_hFW8lKe3tE,1869
|
|
143
146
|
dodal/devices/electron_analyser/util.py,sha256=ZFQJxxwDPIr43859DPIS9lBuq54phUT3R2f_Rbn-FbU,1235
|
|
144
|
-
dodal/devices/electron_analyser/abstract/__init__.py,sha256=
|
|
145
|
-
dodal/devices/electron_analyser/abstract/base_detector.py,sha256=
|
|
146
|
-
dodal/devices/electron_analyser/abstract/base_driver_io.py,sha256=
|
|
147
|
-
dodal/devices/electron_analyser/abstract/base_region.py,sha256=
|
|
147
|
+
dodal/devices/electron_analyser/abstract/__init__.py,sha256=OE5iU5L_7wQudl3cddtMk6eRNbXzZxqiVIzaOAZmuxc,612
|
|
148
|
+
dodal/devices/electron_analyser/abstract/base_detector.py,sha256=alBDZgJxNYLAHDrUa_C5tRUSlujxwWdBebFHDQ8jOv0,2055
|
|
149
|
+
dodal/devices/electron_analyser/abstract/base_driver_io.py,sha256=1j_bCS1k4LqyOBvlt34ijGOLbgX3vboxOUD4j-zv-MU,9963
|
|
150
|
+
dodal/devices/electron_analyser/abstract/base_region.py,sha256=DY5wNs-BMYimkH5tpBEqXGq4n0YhHpk81kuHASveBpw,5702
|
|
148
151
|
dodal/devices/electron_analyser/abstract/types.py,sha256=eoeO7sqlv5RE7AEnyzsxHyuBXlUzOIYdRLWp0EnLyAU,596
|
|
149
152
|
dodal/devices/electron_analyser/specs/__init__.py,sha256=qN57kY6ERUGdrAWhU5m8CBrc0KaqiOGwPL6h2BNm3i0,291
|
|
150
153
|
dodal/devices/electron_analyser/specs/detector.py,sha256=RaNkSmQ_Jb9AuwQqVqo3vv5Q6DcTtpoVqqRAQvgoeEs,1139
|
|
151
|
-
dodal/devices/electron_analyser/specs/driver_io.py,sha256=
|
|
154
|
+
dodal/devices/electron_analyser/specs/driver_io.py,sha256=_6FG5zXGw8vzKc8JzyxdqqQAcU5mBoDjrF_ehfG9h8w,4500
|
|
152
155
|
dodal/devices/electron_analyser/specs/enums.py,sha256=cXPcbIGEN5ZJJt1KeiNJEtZkkcjQ-fz7dBfsU283zYQ,235
|
|
153
156
|
dodal/devices/electron_analyser/specs/region.py,sha256=P7rwbY72-QGKzC6TeldmP8sTmardpB_-rYx7gPVCMqo,1213
|
|
154
157
|
dodal/devices/electron_analyser/vgscienta/__init__.py,sha256=5ZUJcUkJJ9ruwE0PzCFdA0HyWKrfjxaUBeGAMCC9JH4,357
|
|
155
158
|
dodal/devices/electron_analyser/vgscienta/detector.py,sha256=JkO8E5N8tQjYfaHMXoDV6r3oEyzTC0oQI5IqWbOmvxw,1446
|
|
156
|
-
dodal/devices/electron_analyser/vgscienta/driver_io.py,sha256=
|
|
159
|
+
dodal/devices/electron_analyser/vgscienta/driver_io.py,sha256=c1v3AOSGKp6DlVmE82rvuN5aYElWsHeWPtYHPLwIM-s,3510
|
|
157
160
|
dodal/devices/electron_analyser/vgscienta/enums.py,sha256=3vmX67ExATU8clueVp_mCzw3OUQx799oZMc8gyHtMJE,205
|
|
158
161
|
dodal/devices/electron_analyser/vgscienta/region.py,sha256=6k6Eah6_I74Pi2_a0KfyMYFfwHwJbh1ndqy0fuq5o14,2184
|
|
159
162
|
dodal/devices/i02_1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -164,7 +167,7 @@ dodal/devices/i03/dcm.py,sha256=zDcgxOdMRVOQZBGDsLaIlr7o4UJIK2vehPWHxAxt6VA,2268
|
|
|
164
167
|
dodal/devices/i03/undulator_dcm.py,sha256=L7dr1QcwJ1SiQWkHm0a4yQVJFtPiAJQyDLEXok64Ab8,2857
|
|
165
168
|
dodal/devices/i04/__init__.py,sha256=Kvukapy4a5lUQ20qaCqYCJzKNaqJn2DfXP5nKZ_Pec8,118
|
|
166
169
|
dodal/devices/i04/constants.py,sha256=_Dw28NeXldwRYH-h6YP6OHnyj7h0z4NQs_-RysNby5Q,281
|
|
167
|
-
dodal/devices/i04/murko_results.py,sha256=
|
|
170
|
+
dodal/devices/i04/murko_results.py,sha256=Lool7IqYrYoUojexKpoVK8C4ztk9-sNFDg5lcPHBFSw,8949
|
|
168
171
|
dodal/devices/i04/transfocator.py,sha256=sVI4Bgv-2-DH4-F1nIXMp5Aktevrm3agZnCA-WgjmW8,3780
|
|
169
172
|
dodal/devices/i05/__init__.py,sha256=v0Axsf-vMyLyxcbqS8lljJc0BQ5Tw8yVBTWcO3tG_4g,67
|
|
170
173
|
dodal/devices/i05/enums.py,sha256=9FHBIexkSfZSTHxUnGupravfG9sVriHcrB15jemkQOQ,191
|
|
@@ -175,13 +178,15 @@ dodal/devices/i09_1/__init__.py,sha256=dTazun87AkMDXh7J8gIZYJxJth0XUs72qahJ-VvhR
|
|
|
175
178
|
dodal/devices/i09_1/enums.py,sha256=FwhsvKnEcm9M22U4gcAJi6FE2RaUBZH0jRjNgJUKRqc,1319
|
|
176
179
|
dodal/devices/i10/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
177
180
|
dodal/devices/i10/diagnostics.py,sha256=iEPScPnjhLX20dD313hBekqM2OmL_WYQN-4yKAMOFWU,5440
|
|
178
|
-
dodal/devices/i10/i10_apple2.py,sha256=
|
|
181
|
+
dodal/devices/i10/i10_apple2.py,sha256=Rqk_xaBdIqpimjosFvM4_z5r-PkY0pPEoR2xjyqgWKI,19480
|
|
179
182
|
dodal/devices/i10/i10_setting_data.py,sha256=69XWgE-YNTiW7C3t67MNcTL5JDDhOo7h-X7DCTpFE5g,164
|
|
180
183
|
dodal/devices/i10/mirrors.py,sha256=Zofd0g2f3YvFi_KIHQE_w4dFZNglhmh--65tRnWLuyY,504
|
|
181
184
|
dodal/devices/i10/slits.py,sha256=jI4wJPVT2vtl4bvabrU9u_v-SdGjOfDLBm0S9GMZC7w,4157
|
|
185
|
+
dodal/devices/i10/rasor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
182
186
|
dodal/devices/i10/rasor/rasor_current_amp.py,sha256=hImaPI3veKiS5YVfYwv-qrQ1AYNBjFVxG_MwTQqtkcc,2368
|
|
183
187
|
dodal/devices/i10/rasor/rasor_motors.py,sha256=yWBxsiVhbdkQzhaK1S-nUq_wVntwHgdf6T8c8f7wHUE,1327
|
|
184
188
|
dodal/devices/i10/rasor/rasor_scaler_cards.py,sha256=sfWJKNx6pq342PEAlmg_Yt_Tijq7mO1XFjcCDtToQiU,467
|
|
189
|
+
dodal/devices/i11/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
185
190
|
dodal/devices/i11/cyberstar_blower.py,sha256=YngbNzNkWVj_LUGEIqo9JRxRQ0PT7zjouj2VljdDlOk,1033
|
|
186
191
|
dodal/devices/i11/diff_stages.py,sha256=3kcBRUvIwaqmoVf9MxY0CvU8LBbX_qaGhqbbYEmOri4,1713
|
|
187
192
|
dodal/devices/i11/mythen.py,sha256=_fi7SAoWfJ34RyfSNXEyG0gwP0ox6_l9RUN9BF6OBUI,5221
|
|
@@ -190,14 +195,16 @@ dodal/devices/i11/spinner.py,sha256=PjumM7QRB7iFUtN4b6xCvxKItYUNX2XLLWDupy5LI_M,
|
|
|
190
195
|
dodal/devices/i13_1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
191
196
|
dodal/devices/i13_1/merlin.py,sha256=mgTFSMJftRzLL-HXAUuJkOYxtyA3Rp8YX0L46JCb30Y,1019
|
|
192
197
|
dodal/devices/i13_1/merlin_controller.py,sha256=myfmByOEXyMrlJZfsjOxDHeGQVwZGfsRtzrfSy2001o,1495
|
|
198
|
+
dodal/devices/i15/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
193
199
|
dodal/devices/i15/dcm.py,sha256=QLqnKhNbkcVuCFEy9yB-2Ga4fAR0EOGZQshfSoVN8-w,3113
|
|
194
|
-
dodal/devices/i15/focussing_mirror.py,sha256=
|
|
195
|
-
dodal/devices/i15/jack.py,sha256=
|
|
196
|
-
dodal/devices/i15/laue.py,sha256=
|
|
200
|
+
dodal/devices/i15/focussing_mirror.py,sha256=E6T_c7M2osgHLa7u8eUfQJlXlJbZHtOp95FhP3qZ4gY,1739
|
|
201
|
+
dodal/devices/i15/jack.py,sha256=VafCNx-uqkIy0LxbBAhSm_tuC8_SbGCrnTbvQCExAzA,962
|
|
202
|
+
dodal/devices/i15/laue.py,sha256=H0nLPH8gqJejBZtZeY0lv84EaE2lqdL3CmXvT9iHhpk,496
|
|
197
203
|
dodal/devices/i15/motors.py,sha256=-kGHisSWc_zuV9m2L0mGgmiSiIZ7puLsimddk28h_7s,831
|
|
198
|
-
dodal/devices/i15/multilayer_mirror.py,sha256=
|
|
199
|
-
dodal/devices/i15/rail.py,sha256=
|
|
204
|
+
dodal/devices/i15/multilayer_mirror.py,sha256=qdxnn6PBAxK0MgeVUpM8Ukkq4tdX3jhjlmyU-AzzH4M,741
|
|
205
|
+
dodal/devices/i15/rail.py,sha256=9cRTRKy6uZBASMhK1wC8K_k_5FfLgHnoh9VblSOTkpQ,428
|
|
200
206
|
dodal/devices/i18/KBMirror.py,sha256=W4R3TeulSjosUqAFIIznyWzje_Y2AoEf9f8N-NkisYM,710
|
|
207
|
+
dodal/devices/i18/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
201
208
|
dodal/devices/i18/diode.py,sha256=nk5kvn4LsbhczRpCwHOO0_jJTYOz7MP9qm_uvBWuv7c,1468
|
|
202
209
|
dodal/devices/i19/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
203
210
|
dodal/devices/i19/backlight.py,sha256=c3F8RTessUJmJHlCWATSj-W25qlkAttb-c95eS28lKs,662
|
|
@@ -209,6 +216,7 @@ dodal/devices/i19/shutter.py,sha256=B4KP0Ruc8Ex47OfCskbjYSSu81jz4tK9GC_7pxMIkgI,
|
|
|
209
216
|
dodal/devices/i20_1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
210
217
|
dodal/devices/i21/__init__.py,sha256=1H0Ov9s8K7nu6e20WtQDH39wgSKWz2ChRVAUzytIyzQ,67
|
|
211
218
|
dodal/devices/i21/enums.py,sha256=asy90S84fBBydYwz89jNeocz04JXpbHn8ynaPzW353c,141
|
|
219
|
+
dodal/devices/i22/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
212
220
|
dodal/devices/i22/dcm.py,sha256=s3RU6NxsQxOc_YgMBwR8lhboStI1gCDKbWc5pk22O0M,4489
|
|
213
221
|
dodal/devices/i22/fswitch.py,sha256=kpgegs4Wv_weBSzbrlXLXqXOOZdzTn3X9k5PlEN5F6c,2881
|
|
214
222
|
dodal/devices/i22/nxsas.py,sha256=M6hhiPmHO4WDBsFoSOhKAG_yPF6vTpLRPbB2UW3-aMs,6122
|
|
@@ -216,12 +224,13 @@ dodal/devices/i24/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
216
224
|
dodal/devices/i24/aperture.py,sha256=dlH_g7OPTBc5QRMd-ADU3_GDTKh668kkMHo4k_JxUcY,770
|
|
217
225
|
dodal/devices/i24/beam_center.py,sha256=nQyOif6JtlU_qP7kZP-8wN1ldW81MIbFUykPC1bEm70,446
|
|
218
226
|
dodal/devices/i24/beamstop.py,sha256=6tbiQLlcTlp4PCPhHJ_mlHtkv0kz5ArQ99zg9rwTnrw,1133
|
|
219
|
-
dodal/devices/i24/commissioning_jungfrau.py,sha256=
|
|
227
|
+
dodal/devices/i24/commissioning_jungfrau.py,sha256=i-B6Sy2braKSGYF2G7QrluPkThXHY-YiULUJRqClFok,4532
|
|
220
228
|
dodal/devices/i24/dcm.py,sha256=l7qbJh2JKL-5ANlMYXDeU5EBYY6mDiLxn7kp_Z9KNaM,1206
|
|
221
229
|
dodal/devices/i24/dual_backlight.py,sha256=N0R7M1mHPRmQ4fks5lGU1wrXjOvcW_ZKIXaRoC8aLDE,2084
|
|
222
230
|
dodal/devices/i24/focus_mirrors.py,sha256=DYiYLpDw8FJ1LYHxLOxE_om5qGfUo2itzskgqhmQZlg,1763
|
|
223
231
|
dodal/devices/i24/pmac.py,sha256=-HYf2HPzaqWvszp4T8TXohdp40-xmKqQq4V0mLvVri8,7028
|
|
224
232
|
dodal/devices/i24/vgonio.py,sha256=sxSmcYZayVJPJz_D_91j9PmNor7Tbl1RGQFRrdtESlw,533
|
|
233
|
+
dodal/devices/mx_phase1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
225
234
|
dodal/devices/mx_phase1/beamstop.py,sha256=GeHLqHVf3XwJSszUHuxZ2JBwQlcDiFs6jVpdHuw7snM,3127
|
|
226
235
|
dodal/devices/oav/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
227
236
|
dodal/devices/oav/oav_calculations.py,sha256=qoaNz4MAdbpu0XHAkWTQ3rebFwsWfa8JA1eerUgISjA,2367
|
|
@@ -232,6 +241,7 @@ dodal/devices/oav/utils.py,sha256=T-xg7J38ritzXwRrKjsWZ7daC_qR7aNhlbkXx75nJ8Q,31
|
|
|
232
241
|
dodal/devices/oav/pin_image_recognition/__init__.py,sha256=ZDqvAk-Nvw_WM00efxfx2aDEoK1T5QydIciqqCCpp7Q,6302
|
|
233
242
|
dodal/devices/oav/pin_image_recognition/manual_test.py,sha256=h1Rto6ZDCB3jWhjSy9N8ECxRN583iYDJr9LxrTJ8kfE,903
|
|
234
243
|
dodal/devices/oav/pin_image_recognition/utils.py,sha256=L9ypluYqeOFoS7gQuws-vTNc8LqaKl2ZIDNeQ2JaNpg,8592
|
|
244
|
+
dodal/devices/oav/snapshots/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
235
245
|
dodal/devices/oav/snapshots/grid_overlay.py,sha256=CdvCdTKMCiwMwxm2lV28KpcIUSXlscZmWxb73_KKmiI,3694
|
|
236
246
|
dodal/devices/oav/snapshots/snapshot.py,sha256=VDHYxko97sATMKvD5wClgvN7WQUtUAjcXXSyoQAL8q8,499
|
|
237
247
|
dodal/devices/oav/snapshots/snapshot_image_processing.py,sha256=wDxH9WPmB0nsotr49PUpw2Ke4l4RFxirrbpPzOUF9s4,2318
|
|
@@ -250,6 +260,7 @@ dodal/devices/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
|
|
|
250
260
|
dodal/devices/util/adjuster_plans.py,sha256=c40PFZpXFw0YmJLh9jU4VIb8vRxHyafZlmvprTKAOhM,824
|
|
251
261
|
dodal/devices/util/epics_util.py,sha256=4useFL8ngsVF08fhOn48BlnO4oh0T4sEKqjdS6mjvG0,4687
|
|
252
262
|
dodal/devices/util/lookup_tables.py,sha256=jH9f_D8JbTSqzL-RKHUWOORLt8lEoNQL3o9HpXE98TY,3476
|
|
263
|
+
dodal/devices/xspress3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
253
264
|
dodal/devices/xspress3/xspress3.py,sha256=OerapEy-IuK7EFz13B5z0BzBmESVl6pYUlqAWHIwJck,4555
|
|
254
265
|
dodal/devices/xspress3/xspress3_channel.py,sha256=w8tAx2lz5kJ_LeJ_eb_4o--Dtt8MRijsYNgDG6oEIVg,1626
|
|
255
266
|
dodal/devices/zebra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -260,6 +271,7 @@ dodal/devices/zocalo/__init__.py,sha256=W3R09eHAmybP4BcM_gHy6gVAW5_gVSnFq2o3z2iT
|
|
|
260
271
|
dodal/devices/zocalo/zocalo_constants.py,sha256=vu7Xjz7UNEpBUWEEBxDvP4bVFkZIN6NLGfQDpWbCjH8,98
|
|
261
272
|
dodal/devices/zocalo/zocalo_interaction.py,sha256=GFukU9xqagQtVSDg5BrL23jxl1w8wjs4b4NLLqdFfpk,3584
|
|
262
273
|
dodal/devices/zocalo/zocalo_results.py,sha256=8ZYkNB-By47Ag_p68iOq7jK8_P-LAsWPNs0m_DhnVEQ,12639
|
|
274
|
+
dodal/parameters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
263
275
|
dodal/parameters/experiment_parameter_base.py,sha256=vONep-llSqhM0OpVj3zFUxdnzRQpu9y9mPhh2HauEJE,226
|
|
264
276
|
dodal/plan_stubs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
265
277
|
dodal/plan_stubs/check_topup.py,sha256=3gyLHfHNQBCgEWuAg4QE-ONx7y2Do1vVv5HP8ss0Z1I,5371
|
|
@@ -279,8 +291,8 @@ dodal/testing/__init__.py,sha256=AUYZKAvVOs7ZvxO1dVhL0pDTleRO34FQlO5MNe_cwgU,96
|
|
|
279
291
|
dodal/testing/setup.py,sha256=8cQnrzE5MQD4Etf0eqMarmtr-opsUOMQww-k1V7DzIQ,2442
|
|
280
292
|
dodal/testing/electron_analyser/__init__.py,sha256=-lc1opD2dCv0x678-J-ApOhHtvEvcslfOQ7E613U8-Y,118
|
|
281
293
|
dodal/testing/electron_analyser/device_factory.py,sha256=tkMY6fW3iI02DTD1XXHi4lH6sjo8RHHZBGDHSuTdmNU,2243
|
|
282
|
-
dls_dodal-1.
|
|
283
|
-
dls_dodal-1.
|
|
284
|
-
dls_dodal-1.
|
|
285
|
-
dls_dodal-1.
|
|
286
|
-
dls_dodal-1.
|
|
294
|
+
dls_dodal-1.61.0.dist-info/METADATA,sha256=CzbkDC58MYPwQdjxT6ArCdVqQWB9qWGQSHRUC8iWB7A,16941
|
|
295
|
+
dls_dodal-1.61.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
296
|
+
dls_dodal-1.61.0.dist-info/entry_points.txt,sha256=bycw_EKUzup_rxfCetOwcauXV4kLln_OPpPT8jEnr-I,94
|
|
297
|
+
dls_dodal-1.61.0.dist-info/top_level.txt,sha256=xIozdmZk_wmMV4wugpq9-6eZs0vgADNUKz3j2UAwlhc,6
|
|
298
|
+
dls_dodal-1.61.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.61.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 61, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -301,9 +301,68 @@ class UndulatorJawPhase(SafeUndulatorMover[float]):
|
|
|
301
301
|
)
|
|
302
302
|
|
|
303
303
|
|
|
304
|
+
class Apple2Motors(StandardReadable, Movable):
|
|
305
|
+
"""
|
|
306
|
+
Device representing the combined motor controls for an Apple2 undulator.
|
|
307
|
+
|
|
308
|
+
Attributes
|
|
309
|
+
----------
|
|
310
|
+
gap : UndulatorGap
|
|
311
|
+
The undulator gap motor device.
|
|
312
|
+
phase : UndulatorPhaseAxes
|
|
313
|
+
The undulator phase axes device, consisting of four phase motors.
|
|
314
|
+
"""
|
|
315
|
+
|
|
316
|
+
def __init__(self, id_gap: UndulatorGap, id_phase: UndulatorPhaseAxes, name=""):
|
|
317
|
+
"""
|
|
318
|
+
Parameters
|
|
319
|
+
----------
|
|
320
|
+
|
|
321
|
+
id_gap: UndulatorGap
|
|
322
|
+
An UndulatorGap device.
|
|
323
|
+
id_phase: UndulatorPhaseAxes
|
|
324
|
+
An UndulatorPhaseAxes device.
|
|
325
|
+
name: str
|
|
326
|
+
Name of the device.
|
|
327
|
+
"""
|
|
328
|
+
with self.add_children_as_readables():
|
|
329
|
+
self.gap = id_gap
|
|
330
|
+
self.phase = id_phase
|
|
331
|
+
super().__init__(name=name)
|
|
332
|
+
|
|
333
|
+
@AsyncStatus.wrap
|
|
334
|
+
async def set(self, id_motor_values: Apple2Val) -> None:
|
|
335
|
+
"""
|
|
336
|
+
Check ID is in a movable state and set all the demand value before moving them
|
|
337
|
+
all at the same time. This should be modified by the beamline specific ID
|
|
338
|
+
class, if the ID motors has to move in a specific order.
|
|
339
|
+
"""
|
|
340
|
+
|
|
341
|
+
# Only need to check gap as the phase motors share both fault and gate with gap.
|
|
342
|
+
await self.gap.raise_if_cannot_move()
|
|
343
|
+
await asyncio.gather(
|
|
344
|
+
self.phase.top_outer.user_setpoint.set(value=id_motor_values.top_outer),
|
|
345
|
+
self.phase.top_inner.user_setpoint.set(value=id_motor_values.top_inner),
|
|
346
|
+
self.phase.btm_inner.user_setpoint.set(value=id_motor_values.btm_inner),
|
|
347
|
+
self.phase.btm_outer.user_setpoint.set(value=id_motor_values.btm_outer),
|
|
348
|
+
self.gap.user_setpoint.set(value=id_motor_values.gap),
|
|
349
|
+
)
|
|
350
|
+
timeout = np.max(
|
|
351
|
+
await asyncio.gather(self.gap.get_timeout(), self.phase.get_timeout())
|
|
352
|
+
)
|
|
353
|
+
LOGGER.info(
|
|
354
|
+
f"Moving f{self.name} apple2 motors to {id_motor_values}, timeout = {timeout}"
|
|
355
|
+
)
|
|
356
|
+
await asyncio.gather(
|
|
357
|
+
self.gap.set_move.set(value=1, wait=False, timeout=timeout),
|
|
358
|
+
self.phase.set_move.set(value=1, wait=False, timeout=timeout),
|
|
359
|
+
)
|
|
360
|
+
await wait_for_value(self.gap.gate, UndulatorGateStatus.CLOSE, timeout=timeout)
|
|
361
|
+
|
|
362
|
+
|
|
304
363
|
class EnergyMotorConvertor(Protocol):
|
|
305
364
|
def __call__(self, energy: float, pol: Pol) -> tuple[float, float]:
|
|
306
|
-
"""Protocol to provide energy to motor position
|
|
365
|
+
"""Protocol to provide energy to motor position conversion"""
|
|
307
366
|
...
|
|
308
367
|
|
|
309
368
|
|
|
@@ -318,15 +377,13 @@ class Apple2(abc.ABC, StandardReadable, Movable):
|
|
|
318
377
|
The class is designed to manage the undulator's gap, phase motors, and polarisation settings, while
|
|
319
378
|
abstracting hardware interactions and providing a high-level interface for beamline operations.
|
|
320
379
|
|
|
321
|
-
The class is abstract and requires beamline-specific implementations for
|
|
380
|
+
The class is abstract and requires beamline-specific implementations for _set motor
|
|
322
381
|
positions based on energy and polarisation.
|
|
323
382
|
|
|
324
383
|
Attributes
|
|
325
384
|
----------
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
phase : UndulatorPhaseAxes
|
|
329
|
-
The phase control device, consisting of four phase motors.
|
|
385
|
+
apple2_motors : Apple2Motors
|
|
386
|
+
A collection of gap and phase motor devices.
|
|
330
387
|
energy : SignalR
|
|
331
388
|
A soft signal for the current energy readback.
|
|
332
389
|
polarisation_setpoint : SignalR
|
|
@@ -340,7 +397,7 @@ class Apple2(abc.ABC, StandardReadable, Movable):
|
|
|
340
397
|
|
|
341
398
|
Abstract Methods
|
|
342
399
|
----------------
|
|
343
|
-
|
|
400
|
+
_set(value: float) -> None
|
|
344
401
|
Abstract method to set motor positions for a given energy and polarisation.
|
|
345
402
|
|
|
346
403
|
Methods
|
|
@@ -363,8 +420,7 @@ class Apple2(abc.ABC, StandardReadable, Movable):
|
|
|
363
420
|
|
|
364
421
|
def __init__(
|
|
365
422
|
self,
|
|
366
|
-
|
|
367
|
-
id_phase: UndulatorPhaseAxes,
|
|
423
|
+
apple2_motors: Apple2Motors,
|
|
368
424
|
energy_motor_convertor: EnergyMotorConvertor,
|
|
369
425
|
name: str = "",
|
|
370
426
|
) -> None:
|
|
@@ -378,8 +434,7 @@ class Apple2(abc.ABC, StandardReadable, Movable):
|
|
|
378
434
|
name: Name of the device.
|
|
379
435
|
"""
|
|
380
436
|
|
|
381
|
-
self.
|
|
382
|
-
self.phase = id_phase
|
|
437
|
+
self.motors = apple2_motors
|
|
383
438
|
self.energy_to_motor = energy_motor_convertor
|
|
384
439
|
with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
|
|
385
440
|
# Store the set energy for readback.
|
|
@@ -398,11 +453,11 @@ class Apple2(abc.ABC, StandardReadable, Movable):
|
|
|
398
453
|
raw_to_derived=self._read_pol,
|
|
399
454
|
set_derived=self._set_pol,
|
|
400
455
|
pol=self.polarisation_setpoint,
|
|
401
|
-
top_outer=self.phase.top_outer.user_readback,
|
|
402
|
-
top_inner=self.phase.top_inner.user_readback,
|
|
403
|
-
btm_inner=self.phase.btm_inner.user_readback,
|
|
404
|
-
btm_outer=self.phase.btm_outer.user_readback,
|
|
405
|
-
gap=
|
|
456
|
+
top_outer=self.motors.phase.top_outer.user_readback,
|
|
457
|
+
top_inner=self.motors.phase.top_inner.user_readback,
|
|
458
|
+
btm_inner=self.motors.phase.btm_inner.user_readback,
|
|
459
|
+
btm_outer=self.motors.phase.btm_outer.user_readback,
|
|
460
|
+
gap=self.motors.gap.user_readback,
|
|
406
461
|
)
|
|
407
462
|
super().__init__(name)
|
|
408
463
|
|
|
@@ -420,24 +475,32 @@ class Apple2(abc.ABC, StandardReadable, Movable):
|
|
|
420
475
|
self._set_pol_setpoint(value)
|
|
421
476
|
await self.set(await self.energy.get_value())
|
|
422
477
|
|
|
423
|
-
@abc.abstractmethod
|
|
424
478
|
@AsyncStatus.wrap
|
|
425
479
|
async def set(self, value: float) -> None:
|
|
426
480
|
"""
|
|
427
481
|
Set should be in energy units, this will set the energy of the ID by setting the
|
|
428
482
|
gap and phase motors to the correct position for the given energy
|
|
429
483
|
and polarisation.
|
|
430
|
-
|
|
431
|
-
motor positions will be different for each beamline depending on the
|
|
432
|
-
undulator design and the lookup table used.
|
|
433
|
-
_set can be used to set the motor positions for the given energy and
|
|
434
|
-
polarisation provided that all motors can be moved at the same time.
|
|
484
|
+
|
|
435
485
|
|
|
436
486
|
Examples
|
|
437
487
|
--------
|
|
438
488
|
RE( id.set(888.0)) # This will set the ID to 888 eV
|
|
439
489
|
RE(scan([detector], id,600,700,100)) # This will scan the ID from 600 to 700 eV in 100 steps.
|
|
440
490
|
"""
|
|
491
|
+
await self._set(value)
|
|
492
|
+
self._set_energy_rbv(value) # Update energy after move for readback.
|
|
493
|
+
LOGGER.info(f"Energy set to {value} eV successfully.")
|
|
494
|
+
|
|
495
|
+
@abc.abstractmethod
|
|
496
|
+
async def _set(self, value: float) -> None:
|
|
497
|
+
"""
|
|
498
|
+
This method should be implemented by the beamline specific ID class as the
|
|
499
|
+
motor positions will be different for each beamline depending on the
|
|
500
|
+
undulator design and the lookup table used. The set method can be
|
|
501
|
+
used to set the motor positions for the given energy and polarisation
|
|
502
|
+
provided that all motors can be moved at the same time.
|
|
503
|
+
"""
|
|
441
504
|
|
|
442
505
|
def _read_pol(
|
|
443
506
|
self,
|
|
@@ -468,36 +531,6 @@ class Apple2(abc.ABC, StandardReadable, Movable):
|
|
|
468
531
|
|
|
469
532
|
return read_pol
|
|
470
533
|
|
|
471
|
-
async def _set(self, value: Apple2Val, energy: float) -> None:
|
|
472
|
-
"""
|
|
473
|
-
Check ID is in a movable state and set all the demand value before moving them
|
|
474
|
-
all at the same time. This should be modified by the beamline specific ID class
|
|
475
|
-
, if the ID motors has to move in a specific order.
|
|
476
|
-
"""
|
|
477
|
-
|
|
478
|
-
# Only need to check gap as the phase motors share both fault and gate with gap.
|
|
479
|
-
await self.gap.raise_if_cannot_move()
|
|
480
|
-
await asyncio.gather(
|
|
481
|
-
self.phase.top_outer.user_setpoint.set(value=value.top_outer),
|
|
482
|
-
self.phase.top_inner.user_setpoint.set(value=value.top_inner),
|
|
483
|
-
self.phase.btm_inner.user_setpoint.set(value=value.btm_inner),
|
|
484
|
-
self.phase.btm_outer.user_setpoint.set(value=value.btm_outer),
|
|
485
|
-
self.gap.user_setpoint.set(value=value.gap),
|
|
486
|
-
)
|
|
487
|
-
timeout = np.max(
|
|
488
|
-
await asyncio.gather(self.gap.get_timeout(), self.phase.get_timeout())
|
|
489
|
-
)
|
|
490
|
-
LOGGER.info(
|
|
491
|
-
f"Moving f{self.name} energy and polorisation to {energy}, {await self.polarisation.get_value()}"
|
|
492
|
-
+ f"with motor position {value}, timeout = {timeout}"
|
|
493
|
-
)
|
|
494
|
-
await asyncio.gather(
|
|
495
|
-
self.gap.set_move.set(value=1, wait=False, timeout=timeout),
|
|
496
|
-
self.phase.set_move.set(value=1, wait=False, timeout=timeout),
|
|
497
|
-
)
|
|
498
|
-
await wait_for_value(self.gap.gate, UndulatorGateStatus.CLOSE, timeout=timeout)
|
|
499
|
-
self._set_energy_rbv(energy) # Update energy after move for readback.
|
|
500
|
-
|
|
501
534
|
def determine_phase_from_hardware(
|
|
502
535
|
self,
|
|
503
536
|
top_outer: float,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from .base_detector import (
|
|
2
|
-
|
|
2
|
+
BaseElectronAnalyserDetector,
|
|
3
3
|
)
|
|
4
4
|
from .base_driver_io import AbstractAnalyserDriverIO, TAbstractAnalyserDriverIO
|
|
5
5
|
from .base_region import (
|
|
@@ -19,7 +19,7 @@ __all__ = [
|
|
|
19
19
|
"TAcquisitionMode",
|
|
20
20
|
"TLensMode",
|
|
21
21
|
"AbstractAnalyserDriverIO",
|
|
22
|
-
"
|
|
22
|
+
"BaseElectronAnalyserDetector",
|
|
23
23
|
"AbstractAnalyserDriverIO",
|
|
24
24
|
"TAbstractAnalyserDriverIO",
|
|
25
25
|
]
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from abc import abstractmethod
|
|
2
1
|
from typing import Generic
|
|
3
2
|
|
|
4
3
|
from bluesky.protocols import Reading, Triggerable
|
|
@@ -9,14 +8,14 @@ from ophyd_async.core import (
|
|
|
9
8
|
AsyncStatus,
|
|
10
9
|
Device,
|
|
11
10
|
)
|
|
11
|
+
from ophyd_async.epics.adcore import ADBaseController
|
|
12
12
|
|
|
13
|
-
from dodal.devices.controllers import ConstantDeadTimeController
|
|
14
13
|
from dodal.devices.electron_analyser.abstract.base_driver_io import (
|
|
15
14
|
TAbstractAnalyserDriverIO,
|
|
16
15
|
)
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
class
|
|
18
|
+
class BaseElectronAnalyserDetector(
|
|
20
19
|
Device,
|
|
21
20
|
Triggerable,
|
|
22
21
|
AsyncReadable,
|
|
@@ -34,43 +33,31 @@ class AbstractElectronAnalyserDetector(
|
|
|
34
33
|
|
|
35
34
|
def __init__(
|
|
36
35
|
self,
|
|
37
|
-
|
|
36
|
+
controller: ADBaseController[TAbstractAnalyserDriverIO],
|
|
38
37
|
name: str = "",
|
|
39
38
|
):
|
|
40
|
-
self.
|
|
39
|
+
self._controller = controller
|
|
41
40
|
super().__init__(name)
|
|
42
41
|
|
|
43
42
|
@AsyncStatus.wrap
|
|
44
43
|
async def trigger(self) -> None:
|
|
45
|
-
await self.
|
|
46
|
-
await self.
|
|
44
|
+
await self._controller.arm()
|
|
45
|
+
await self._controller.wait_for_idle()
|
|
47
46
|
|
|
48
47
|
async def read(self) -> dict[str, Reading]:
|
|
49
|
-
return await self.driver.read()
|
|
48
|
+
return await self._controller.driver.read()
|
|
50
49
|
|
|
51
50
|
async def describe(self) -> dict[str, DataKey]:
|
|
52
|
-
data = await self.driver.describe()
|
|
51
|
+
data = await self._controller.driver.describe()
|
|
53
52
|
# Correct the shape for image
|
|
54
|
-
prefix = self.driver.name + "-"
|
|
55
|
-
energy_size = len(await self.driver.energy_axis.get_value())
|
|
56
|
-
angle_size = len(await self.driver.angle_axis.get_value())
|
|
53
|
+
prefix = self._controller.driver.name + "-"
|
|
54
|
+
energy_size = len(await self._controller.driver.energy_axis.get_value())
|
|
55
|
+
angle_size = len(await self._controller.driver.angle_axis.get_value())
|
|
57
56
|
data[prefix + "image"]["shape"] = [angle_size, energy_size]
|
|
58
57
|
return data
|
|
59
58
|
|
|
60
59
|
async def read_configuration(self) -> dict[str, Reading]:
|
|
61
|
-
return await self.driver.read_configuration()
|
|
60
|
+
return await self._controller.driver.read_configuration()
|
|
62
61
|
|
|
63
62
|
async def describe_configuration(self) -> dict[str, DataKey]:
|
|
64
|
-
return await self.driver.describe_configuration()
|
|
65
|
-
|
|
66
|
-
@property
|
|
67
|
-
@abstractmethod
|
|
68
|
-
def driver(self) -> TAbstractAnalyserDriverIO:
|
|
69
|
-
"""
|
|
70
|
-
Define common property for all implementations to access the driver. Some
|
|
71
|
-
implementations will store this as a reference so it doesn't have conflicting
|
|
72
|
-
parents.
|
|
73
|
-
|
|
74
|
-
Returns:
|
|
75
|
-
instance of the driver.
|
|
76
|
-
"""
|
|
63
|
+
return await self._controller.driver.describe_configuration()
|
|
@@ -153,11 +153,12 @@ class AbstractAnalyserDriverIO(
|
|
|
153
153
|
self.energy_source.selected_source.set(region.excitation_energy_source)
|
|
154
154
|
excitation_energy = await self.energy_source.energy.get_value()
|
|
155
155
|
|
|
156
|
-
#
|
|
157
|
-
ke_region = region.
|
|
158
|
-
ke_region.switch_energy_mode(EnergyMode.KINETIC, excitation_energy)
|
|
159
|
-
|
|
156
|
+
# Switch to kinetic energy as epics doesn't support BINDING.
|
|
157
|
+
ke_region = region.switch_energy_mode(EnergyMode.KINETIC, excitation_energy)
|
|
160
158
|
await self._set_region(ke_region)
|
|
159
|
+
# Set the true energy mode from original region so binding_energy_axis can be
|
|
160
|
+
# calculated correctly.
|
|
161
|
+
await self.energy_mode.set(region.energy_mode)
|
|
161
162
|
|
|
162
163
|
@abstractmethod
|
|
163
164
|
async def _set_region(self, ke_region: TAbstractBaseRegion):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from abc import ABC
|
|
3
3
|
from collections.abc import Callable
|
|
4
|
-
from typing import Generic, TypeVar
|
|
4
|
+
from typing import Generic, Self, TypeVar
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel, Field, model_validator
|
|
7
7
|
|
|
@@ -88,28 +88,43 @@ class AbstractBaseRegion(
|
|
|
88
88
|
return self.energy_mode == EnergyMode.KINETIC
|
|
89
89
|
|
|
90
90
|
def switch_energy_mode(
|
|
91
|
-
self, energy_mode: EnergyMode, excitation_energy: float
|
|
92
|
-
) ->
|
|
91
|
+
self, energy_mode: EnergyMode, excitation_energy: float, copy: bool = True
|
|
92
|
+
) -> Self:
|
|
93
93
|
"""
|
|
94
|
-
Switch region to new energy mode: Kinetic or Binding.
|
|
95
|
-
|
|
94
|
+
Switch region with to a new energy mode with a new energy mode: Kinetic or Binding.
|
|
95
|
+
It caculates new values for low_energy, centre_energy, high_energy, via the
|
|
96
|
+
excitation enerrgy. It doesn't calculate anything if the region is already of
|
|
97
|
+
the same energy mode.
|
|
96
98
|
|
|
97
99
|
Parameters:
|
|
98
|
-
energy_mode:
|
|
99
|
-
excitation_energy:
|
|
100
|
-
|
|
100
|
+
energy_mode: Mode you want to switch the region to.
|
|
101
|
+
excitation_energy: Energy conversion for low_energy, centre_energy, and
|
|
102
|
+
high_energy for new energy mode.
|
|
103
|
+
copy: Defaults to True. If true, create a copy of this region for the new
|
|
104
|
+
energy_mode and return it. If False, alter this region for the
|
|
105
|
+
energy_mode and return it self.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Region with selected energy mode and new calculated energy values.
|
|
101
109
|
"""
|
|
110
|
+
switched_r = self.model_copy() if copy else self
|
|
102
111
|
conv = (
|
|
103
112
|
to_binding_energy
|
|
104
113
|
if energy_mode == EnergyMode.BINDING
|
|
105
114
|
else to_kinetic_energy
|
|
106
115
|
)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
self.centre_energy, self.energy_mode, excitation_energy
|
|
116
|
+
switched_r.low_energy = conv(
|
|
117
|
+
switched_r.low_energy, switched_r.energy_mode, excitation_energy
|
|
110
118
|
)
|
|
111
|
-
|
|
112
|
-
|
|
119
|
+
switched_r.centre_energy = conv(
|
|
120
|
+
switched_r.centre_energy, switched_r.energy_mode, excitation_energy
|
|
121
|
+
)
|
|
122
|
+
switched_r.high_energy = conv(
|
|
123
|
+
switched_r.high_energy, switched_r.energy_mode, excitation_energy
|
|
124
|
+
)
|
|
125
|
+
switched_r.energy_mode = energy_mode
|
|
126
|
+
|
|
127
|
+
return switched_r
|
|
113
128
|
|
|
114
129
|
@model_validator(mode="before")
|
|
115
130
|
@classmethod
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
from typing import Generic, TypeVar
|
|
2
2
|
|
|
3
3
|
from bluesky.protocols import Stageable
|
|
4
|
-
from ophyd_async.core import
|
|
5
|
-
|
|
6
|
-
Reference,
|
|
7
|
-
)
|
|
4
|
+
from ophyd_async.core import AsyncStatus
|
|
5
|
+
from ophyd_async.epics.adcore import ADBaseController
|
|
8
6
|
|
|
9
7
|
from dodal.common.data_util import load_json_file_to_class
|
|
8
|
+
from dodal.devices.controllers import ConstantDeadTimeController
|
|
10
9
|
from dodal.devices.electron_analyser.abstract.base_detector import (
|
|
11
|
-
|
|
10
|
+
BaseElectronAnalyserDetector,
|
|
12
11
|
)
|
|
13
12
|
from dodal.devices.electron_analyser.abstract.base_driver_io import (
|
|
14
13
|
TAbstractAnalyserDriverIO,
|
|
@@ -20,35 +19,27 @@ from dodal.devices.electron_analyser.abstract.base_region import (
|
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
class ElectronAnalyserRegionDetector(
|
|
23
|
-
|
|
22
|
+
BaseElectronAnalyserDetector[TAbstractAnalyserDriverIO],
|
|
24
23
|
Generic[TAbstractAnalyserDriverIO, TAbstractBaseRegion],
|
|
25
24
|
):
|
|
26
25
|
"""
|
|
27
26
|
Extends electron analyser detector to configure specific region settings before data
|
|
28
|
-
|
|
29
|
-
is designed to only exist inside a plan.
|
|
27
|
+
acquisition. It is designed to only exist inside a plan.
|
|
30
28
|
"""
|
|
31
29
|
|
|
32
30
|
def __init__(
|
|
33
31
|
self,
|
|
34
|
-
|
|
32
|
+
controller: ADBaseController[TAbstractAnalyserDriverIO],
|
|
35
33
|
region: TAbstractBaseRegion,
|
|
36
34
|
name: str = "",
|
|
37
35
|
):
|
|
38
|
-
self._driver_ref = Reference(driver)
|
|
39
36
|
self.region = region
|
|
40
|
-
super().__init__(
|
|
41
|
-
|
|
42
|
-
@property
|
|
43
|
-
def driver(self) -> TAbstractAnalyserDriverIO:
|
|
44
|
-
# Store as a reference, this implementation will be given a driver so needs to
|
|
45
|
-
# make sure we don't get conflicting parents.
|
|
46
|
-
return self._driver_ref()
|
|
37
|
+
super().__init__(controller, name)
|
|
47
38
|
|
|
48
39
|
@AsyncStatus.wrap
|
|
49
40
|
async def trigger(self) -> None:
|
|
50
41
|
# Configure region parameters on the driver first before data collection.
|
|
51
|
-
await self.driver.set(self.region)
|
|
42
|
+
await self._controller.driver.set(self.region)
|
|
52
43
|
await super().trigger()
|
|
53
44
|
|
|
54
45
|
|
|
@@ -59,7 +50,7 @@ TElectronAnalyserRegionDetector = TypeVar(
|
|
|
59
50
|
|
|
60
51
|
|
|
61
52
|
class ElectronAnalyserDetector(
|
|
62
|
-
|
|
53
|
+
BaseElectronAnalyserDetector[TAbstractAnalyserDriverIO],
|
|
63
54
|
Stageable,
|
|
64
55
|
Generic[
|
|
65
56
|
TAbstractAnalyserDriverIO,
|
|
@@ -79,16 +70,11 @@ class ElectronAnalyserDetector(
|
|
|
79
70
|
driver: TAbstractAnalyserDriverIO,
|
|
80
71
|
name: str = "",
|
|
81
72
|
):
|
|
82
|
-
#
|
|
83
|
-
self.
|
|
73
|
+
# Save driver as direct child so participates with connect()
|
|
74
|
+
self.driver = driver
|
|
84
75
|
self._sequence_class = sequence_class
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
@property
|
|
88
|
-
def driver(self) -> TAbstractAnalyserDriverIO:
|
|
89
|
-
# This implementation creates the driver and wants this to be the parent so it
|
|
90
|
-
# can be used with connect() method.
|
|
91
|
-
return self._driver
|
|
76
|
+
controller = ConstantDeadTimeController[TAbstractAnalyserDriverIO](driver, 0)
|
|
77
|
+
super().__init__(controller, name)
|
|
92
78
|
|
|
93
79
|
@AsyncStatus.wrap
|
|
94
80
|
async def stage(self) -> None:
|
|
@@ -103,13 +89,13 @@ class ElectronAnalyserDetector(
|
|
|
103
89
|
Raises:
|
|
104
90
|
Any exceptions raised by the driver's stage or controller's disarm methods.
|
|
105
91
|
"""
|
|
106
|
-
await self.
|
|
92
|
+
await self._controller.disarm()
|
|
107
93
|
await self.driver.stage()
|
|
108
94
|
|
|
109
95
|
@AsyncStatus.wrap
|
|
110
96
|
async def unstage(self) -> None:
|
|
111
97
|
"""Disarm the detector."""
|
|
112
|
-
await self.
|
|
98
|
+
await self._controller.disarm()
|
|
113
99
|
await self.driver.unstage()
|
|
114
100
|
|
|
115
101
|
def load_sequence(self, filename: str) -> TAbstractBaseSequence:
|
|
@@ -144,7 +130,9 @@ class ElectronAnalyserDetector(
|
|
|
144
130
|
seq = self.load_sequence(filename)
|
|
145
131
|
regions = seq.get_enabled_regions() if enabled_only else seq.regions
|
|
146
132
|
return [
|
|
147
|
-
ElectronAnalyserRegionDetector(
|
|
133
|
+
ElectronAnalyserRegionDetector(
|
|
134
|
+
self._controller, r, self.name + "_" + r.name
|
|
135
|
+
)
|
|
148
136
|
for r in regions
|
|
149
137
|
]
|
|
150
138
|
|
|
@@ -66,7 +66,6 @@ class SpecsAnalyserDriverIO(
|
|
|
66
66
|
async def _set_region(self, ke_region: SpecsRegion[TLensMode, TPsuMode]):
|
|
67
67
|
await asyncio.gather(
|
|
68
68
|
self.region_name.set(ke_region.name),
|
|
69
|
-
self.energy_mode.set(ke_region.energy_mode),
|
|
70
69
|
self.low_energy.set(ke_region.low_energy),
|
|
71
70
|
self.high_energy.set(ke_region.high_energy),
|
|
72
71
|
self.slices.set(ke_region.slices),
|
|
@@ -74,7 +74,6 @@ class VGScientaAnalyserDriverIO(
|
|
|
74
74
|
async def _set_region(self, ke_region: VGScientaRegion[TLensMode, TPassEnergyEnum]):
|
|
75
75
|
await asyncio.gather(
|
|
76
76
|
self.region_name.set(ke_region.name),
|
|
77
|
-
self.energy_mode.set(ke_region.energy_mode),
|
|
78
77
|
self.low_energy.set(ke_region.low_energy),
|
|
79
78
|
self.centre_energy.set(ke_region.centre_energy),
|
|
80
79
|
self.high_energy.set(ke_region.high_energy),
|
dodal/devices/fast_grid_scan.py
CHANGED
|
@@ -296,15 +296,15 @@ class FastGridScanThreeD(FastGridScanCommon[ParamType]):
|
|
|
296
296
|
Subclasses must implement _create_position_counter.
|
|
297
297
|
"""
|
|
298
298
|
|
|
299
|
-
def __init__(self, prefix: str, name: str = "") -> None:
|
|
300
|
-
full_prefix = prefix +
|
|
299
|
+
def __init__(self, prefix: str, infix: str, name: str = "") -> None:
|
|
300
|
+
full_prefix = prefix + infix
|
|
301
301
|
|
|
302
302
|
# Number of vertical steps during the second grid scan, after the rotation in omega
|
|
303
|
-
self.z_steps = epics_signal_rw_rbv(int, f"{
|
|
304
|
-
self.z_step_size = epics_signal_rw_rbv(float, f"{
|
|
305
|
-
self.z2_start = epics_signal_rw_rbv(float, f"{
|
|
306
|
-
self.y2_start = epics_signal_rw_rbv(float, f"{
|
|
307
|
-
|
|
303
|
+
self.z_steps = epics_signal_rw_rbv(int, f"{full_prefix}Z_NUM_STEPS")
|
|
304
|
+
self.z_step_size = epics_signal_rw_rbv(float, f"{full_prefix}Z_STEP_SIZE")
|
|
305
|
+
self.z2_start = epics_signal_rw_rbv(float, f"{full_prefix}Z2_START")
|
|
306
|
+
self.y2_start = epics_signal_rw_rbv(float, f"{full_prefix}Y2_START")
|
|
307
|
+
# panda does not have x counter
|
|
308
308
|
self.y_counter = epics_signal_r(int, f"{full_prefix}Y_COUNTER")
|
|
309
309
|
|
|
310
310
|
super().__init__(full_prefix, prefix, name)
|
|
@@ -343,10 +343,12 @@ class ZebraFastGridScanThreeD(FastGridScanThreeD[ZebraGridScanParamsThreeD]):
|
|
|
343
343
|
"""
|
|
344
344
|
|
|
345
345
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
346
|
-
|
|
346
|
+
infix = "FGS:"
|
|
347
|
+
full_prefix = prefix + infix
|
|
347
348
|
# Time taken to travel between X steps
|
|
348
349
|
self.dwell_time_ms = epics_signal_rw_rbv(float, f"{full_prefix}DWELL_TIME")
|
|
349
|
-
|
|
350
|
+
self.x_counter = epics_signal_r(int, f"{full_prefix}X_COUNTER")
|
|
351
|
+
super().__init__(prefix, infix, name)
|
|
350
352
|
self.movable_params["dwell_time_ms"] = self.dwell_time_ms
|
|
351
353
|
|
|
352
354
|
def _create_position_counter(self, prefix: str):
|
|
@@ -363,7 +365,8 @@ class PandAFastGridScan(FastGridScanThreeD[PandAGridScanParams]):
|
|
|
363
365
|
"""
|
|
364
366
|
|
|
365
367
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
366
|
-
|
|
368
|
+
infix = "PGS:"
|
|
369
|
+
full_prefix = prefix + infix
|
|
367
370
|
self.time_between_x_steps_ms = (
|
|
368
371
|
epics_signal_rw_rbv( # Used by motion controller to set goniometer velocity
|
|
369
372
|
float, f"{full_prefix}TIME_BETWEEN_X_STEPS"
|
|
@@ -375,7 +378,7 @@ class PandAFastGridScan(FastGridScanThreeD[PandAGridScanParams]):
|
|
|
375
378
|
self.run_up_distance_mm = epics_signal_rw_rbv(
|
|
376
379
|
float, f"{full_prefix}RUNUP_DISTANCE"
|
|
377
380
|
)
|
|
378
|
-
super().__init__(prefix, name)
|
|
381
|
+
super().__init__(prefix, infix, name)
|
|
379
382
|
|
|
380
383
|
self.movable_params["run_up_distance_mm"] = self.run_up_distance_mm
|
|
381
384
|
|
|
@@ -32,6 +32,7 @@ class MurkoMetadata(TypedDict):
|
|
|
32
32
|
sample_id: str
|
|
33
33
|
omega_angle: float
|
|
34
34
|
uuid: str
|
|
35
|
+
used_for_centring: bool | None
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
class Coord(Enum):
|
|
@@ -47,6 +48,7 @@ class MurkoResult:
|
|
|
47
48
|
y_dist_mm: float
|
|
48
49
|
omega: float
|
|
49
50
|
uuid: str
|
|
51
|
+
metadata: MurkoMetadata
|
|
50
52
|
|
|
51
53
|
|
|
52
54
|
class NoResultsFound(ValueError):
|
|
@@ -101,7 +103,7 @@ class MurkoResultsDevice(StandardReadable, Triggerable, Stageable):
|
|
|
101
103
|
|
|
102
104
|
def _reset(self):
|
|
103
105
|
self._last_omega = 0
|
|
104
|
-
self.
|
|
106
|
+
self._results: list[MurkoResult] = []
|
|
105
107
|
|
|
106
108
|
@AsyncStatus.wrap
|
|
107
109
|
async def stage(self):
|
|
@@ -126,17 +128,17 @@ class MurkoResultsDevice(StandardReadable, Triggerable, Stageable):
|
|
|
126
128
|
continue
|
|
127
129
|
await self.process_batch(message, sample_id)
|
|
128
130
|
|
|
129
|
-
if not self.
|
|
131
|
+
if not self._results:
|
|
130
132
|
raise NoResultsFound("No results retrieved from Murko")
|
|
131
133
|
|
|
132
|
-
for result in self.
|
|
134
|
+
for result in self._results:
|
|
133
135
|
LOGGER.debug(result)
|
|
134
136
|
|
|
135
|
-
self.filter_outliers()
|
|
137
|
+
filtered_results = self.filter_outliers()
|
|
136
138
|
|
|
137
|
-
x_dists_mm = [result.x_dist_mm for result in
|
|
138
|
-
y_dists_mm = [result.y_dist_mm for result in
|
|
139
|
-
omegas = [result.omega for result in
|
|
139
|
+
x_dists_mm = [result.x_dist_mm for result in filtered_results]
|
|
140
|
+
y_dists_mm = [result.y_dist_mm for result in filtered_results]
|
|
141
|
+
omegas = [result.omega for result in filtered_results]
|
|
140
142
|
|
|
141
143
|
LOGGER.info(f"Using average of x beam distances: {x_dists_mm}")
|
|
142
144
|
avg_x = float(np.mean(x_dists_mm))
|
|
@@ -147,6 +149,11 @@ class MurkoResultsDevice(StandardReadable, Triggerable, Stageable):
|
|
|
147
149
|
self._y_mm_setter(-best_y)
|
|
148
150
|
self._z_mm_setter(-best_z)
|
|
149
151
|
|
|
152
|
+
for result in self._results:
|
|
153
|
+
await self.redis_client.hset( # type: ignore
|
|
154
|
+
f"murko:{sample_id}:metadata", result.uuid, json.dumps(result.metadata)
|
|
155
|
+
)
|
|
156
|
+
|
|
150
157
|
async def process_batch(self, message: dict | None, sample_id: str):
|
|
151
158
|
if message and message["type"] == "message":
|
|
152
159
|
batch_results: list[dict] = pickle.loads(message["data"])
|
|
@@ -186,13 +193,14 @@ class MurkoResultsDevice(StandardReadable, Triggerable, Stageable):
|
|
|
186
193
|
centre_px[0],
|
|
187
194
|
centre_px[1],
|
|
188
195
|
)
|
|
189
|
-
self.
|
|
196
|
+
self._results.append(
|
|
190
197
|
MurkoResult(
|
|
191
198
|
centre_px=centre_px,
|
|
192
199
|
x_dist_mm=beam_dist_px[0] * metadata["microns_per_x_pixel"] / 1000,
|
|
193
200
|
y_dist_mm=beam_dist_px[1] * metadata["microns_per_y_pixel"] / 1000,
|
|
194
201
|
omega=omega,
|
|
195
202
|
uuid=metadata["uuid"],
|
|
203
|
+
metadata=metadata,
|
|
196
204
|
)
|
|
197
205
|
)
|
|
198
206
|
self._last_omega = omega
|
|
@@ -203,8 +211,8 @@ class MurkoResultsDevice(StandardReadable, Triggerable, Stageable):
|
|
|
203
211
|
meaning that by keeping only a percentage of the results with the smallest X we
|
|
204
212
|
remove many of the outliers.
|
|
205
213
|
"""
|
|
206
|
-
LOGGER.info(f"Number of results before filtering: {len(self.
|
|
207
|
-
sorted_results = sorted(self.
|
|
214
|
+
LOGGER.info(f"Number of results before filtering: {len(self._results)}")
|
|
215
|
+
sorted_results = sorted(self._results, key=lambda item: item.centre_px[0])
|
|
208
216
|
|
|
209
217
|
worst_results = [
|
|
210
218
|
r.uuid for r in sorted_results[-self.NUMBER_OF_WRONG_RESULTS_TO_LOG :]
|
|
@@ -214,9 +222,13 @@ class MurkoResultsDevice(StandardReadable, Triggerable, Stageable):
|
|
|
214
222
|
f"Worst {self.NUMBER_OF_WRONG_RESULTS_TO_LOG} murko results were {worst_results}"
|
|
215
223
|
)
|
|
216
224
|
cutoff = max(1, int(len(sorted_results) * self.PERCENTAGE_TO_USE / 100))
|
|
225
|
+
for i, result in enumerate(sorted_results):
|
|
226
|
+
result.metadata["used_for_centring"] = i < cutoff
|
|
227
|
+
|
|
217
228
|
smallest_x = sorted_results[:cutoff]
|
|
218
|
-
|
|
219
|
-
LOGGER.info(f"Number of results after filtering: {len(
|
|
229
|
+
|
|
230
|
+
LOGGER.info(f"Number of results after filtering: {len(smallest_x)}")
|
|
231
|
+
return smallest_x
|
|
220
232
|
|
|
221
233
|
|
|
222
234
|
def get_yz_least_squares(vertical_dists: list, omegas: list) -> tuple[float, float]:
|
dodal/devices/i10/i10_apple2.py
CHANGED
|
@@ -19,10 +19,9 @@ from ophyd_async.core import (
|
|
|
19
19
|
)
|
|
20
20
|
from pydantic import BaseModel, ConfigDict, RootModel
|
|
21
21
|
|
|
22
|
-
from dodal.
|
|
23
|
-
|
|
24
|
-
from ..apple2_undulator import (
|
|
22
|
+
from dodal.devices.apple2_undulator import (
|
|
25
23
|
Apple2,
|
|
24
|
+
Apple2Motors,
|
|
26
25
|
Apple2Val,
|
|
27
26
|
EnergyMotorConvertor,
|
|
28
27
|
Pol,
|
|
@@ -30,6 +29,8 @@ from ..apple2_undulator import (
|
|
|
30
29
|
UndulatorJawPhase,
|
|
31
30
|
UndulatorPhaseAxes,
|
|
32
31
|
)
|
|
32
|
+
from dodal.log import LOGGER
|
|
33
|
+
|
|
33
34
|
from ..pgm import PGM
|
|
34
35
|
|
|
35
36
|
ROW_PHASE_MOTOR_TOLERANCE = 0.004
|
|
@@ -359,14 +360,15 @@ class I10Apple2(Apple2):
|
|
|
359
360
|
|
|
360
361
|
with self.add_children_as_readables():
|
|
361
362
|
super().__init__(
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
363
|
+
apple2_motors=Apple2Motors(
|
|
364
|
+
id_gap=UndulatorGap(prefix=prefix),
|
|
365
|
+
id_phase=UndulatorPhaseAxes(
|
|
366
|
+
prefix=prefix,
|
|
367
|
+
top_outer="RPQ1",
|
|
368
|
+
top_inner="RPQ2",
|
|
369
|
+
btm_inner="RPQ3",
|
|
370
|
+
btm_outer="RPQ4",
|
|
371
|
+
),
|
|
370
372
|
),
|
|
371
373
|
energy_motor_convertor=energy_motor_convertor,
|
|
372
374
|
name=name,
|
|
@@ -376,8 +378,7 @@ class I10Apple2(Apple2):
|
|
|
376
378
|
move_pv="RPQ1",
|
|
377
379
|
)
|
|
378
380
|
|
|
379
|
-
|
|
380
|
-
async def set(self, value: float) -> None:
|
|
381
|
+
async def _set(self, value: float) -> None:
|
|
381
382
|
"""
|
|
382
383
|
Check polarisation state and use it together with the energy(value)
|
|
383
384
|
to calculate the required gap and phases before setting it.
|
|
@@ -408,11 +409,10 @@ class I10Apple2(Apple2):
|
|
|
408
409
|
)
|
|
409
410
|
|
|
410
411
|
LOGGER.info(f"Setting polarisation to {pol}, with values: {id_set_val}")
|
|
411
|
-
await self.
|
|
412
|
+
await self.motors.set(id_motor_values=id_set_val)
|
|
412
413
|
if pol != Pol.LA:
|
|
413
414
|
await self.id_jaw_phase.set(0)
|
|
414
415
|
await self.id_jaw_phase.set_move.set(1)
|
|
415
|
-
LOGGER.info(f"Energy set to {value} eV successfully.")
|
|
416
416
|
|
|
417
417
|
|
|
418
418
|
class EnergySetter(StandardReadable, Movable[float]):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -5,11 +5,7 @@ from ophyd_async.epics.motor import Motor
|
|
|
5
5
|
class FocusingMirrorBase(StandardReadable):
|
|
6
6
|
"""Focusing Mirror with curve, ellip & pitch"""
|
|
7
7
|
|
|
8
|
-
def __init__(
|
|
9
|
-
self,
|
|
10
|
-
prefix: str,
|
|
11
|
-
name: str = "",
|
|
12
|
-
):
|
|
8
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
13
9
|
with self.add_children_as_readables():
|
|
14
10
|
self.curve = Motor(prefix + "CURVE")
|
|
15
11
|
self.ellipticity = Motor(prefix + "ELLIP")
|
|
@@ -21,11 +17,7 @@ class FocusingMirrorBase(StandardReadable):
|
|
|
21
17
|
class FocusingMirrorHorizontal(FocusingMirrorBase):
|
|
22
18
|
"""Focusing Mirror with curve, ellip, pitch & X"""
|
|
23
19
|
|
|
24
|
-
def __init__(
|
|
25
|
-
self,
|
|
26
|
-
prefix: str,
|
|
27
|
-
name: str = "",
|
|
28
|
-
):
|
|
20
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
29
21
|
with self.add_children_as_readables():
|
|
30
22
|
self.x = Motor(prefix + "X")
|
|
31
23
|
|
|
@@ -35,11 +27,7 @@ class FocusingMirrorHorizontal(FocusingMirrorBase):
|
|
|
35
27
|
class FocusingMirrorVertical(FocusingMirrorBase):
|
|
36
28
|
"""Focusing Mirror with curve, ellip, pitch & Y"""
|
|
37
29
|
|
|
38
|
-
def __init__(
|
|
39
|
-
self,
|
|
40
|
-
prefix: str,
|
|
41
|
-
name: str = "",
|
|
42
|
-
):
|
|
30
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
43
31
|
with self.add_children_as_readables():
|
|
44
32
|
self.y = Motor(prefix + "Y")
|
|
45
33
|
|
|
@@ -49,11 +37,7 @@ class FocusingMirrorVertical(FocusingMirrorBase):
|
|
|
49
37
|
class FocusingMirror(FocusingMirrorBase):
|
|
50
38
|
"""Focusing Mirror with curve, ellip, pitch, yaw, X & Y"""
|
|
51
39
|
|
|
52
|
-
def __init__(
|
|
53
|
-
self,
|
|
54
|
-
prefix: str,
|
|
55
|
-
name: str = "",
|
|
56
|
-
):
|
|
40
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
57
41
|
with self.add_children_as_readables():
|
|
58
42
|
self.yaw = Motor(prefix + "YAW")
|
|
59
43
|
self.x = Motor(prefix + "X")
|
dodal/devices/i15/jack.py
CHANGED
|
@@ -5,11 +5,7 @@ from ophyd_async.epics.motor import Motor
|
|
|
5
5
|
class JackX(StandardReadable):
|
|
6
6
|
"""Focusing Mirror"""
|
|
7
7
|
|
|
8
|
-
def __init__(
|
|
9
|
-
self,
|
|
10
|
-
prefix: str,
|
|
11
|
-
name: str = "",
|
|
12
|
-
):
|
|
8
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
13
9
|
with self.add_children_as_readables():
|
|
14
10
|
self.rotation = Motor(prefix + "Ry")
|
|
15
11
|
self.transx = Motor(prefix + "X")
|
|
@@ -23,11 +19,7 @@ class JackX(StandardReadable):
|
|
|
23
19
|
class JackY(StandardReadable):
|
|
24
20
|
"""Focusing Mirror"""
|
|
25
21
|
|
|
26
|
-
def __init__(
|
|
27
|
-
self,
|
|
28
|
-
prefix: str,
|
|
29
|
-
name: str = "",
|
|
30
|
-
):
|
|
22
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
31
23
|
with self.add_children_as_readables():
|
|
32
24
|
self.j1 = Motor(prefix + "J1")
|
|
33
25
|
self.j2 = Motor(prefix + "J2")
|
dodal/devices/i15/laue.py
CHANGED
|
@@ -3,11 +3,7 @@ from ophyd_async.epics.motor import Motor
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class LaueMonochrometer(StandardReadable):
|
|
6
|
-
def __init__(
|
|
7
|
-
self,
|
|
8
|
-
prefix: str,
|
|
9
|
-
name: str = "",
|
|
10
|
-
):
|
|
6
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
11
7
|
with self.add_children_as_readables():
|
|
12
8
|
self.bend = Motor(prefix + "BENDER")
|
|
13
9
|
self.bragg = Motor(prefix + "PITCH")
|
|
@@ -5,11 +5,7 @@ from ophyd_async.epics.motor import Motor
|
|
|
5
5
|
class MultiLayerMirror(StandardReadable):
|
|
6
6
|
"""Multilayer Mirror"""
|
|
7
7
|
|
|
8
|
-
def __init__(
|
|
9
|
-
self,
|
|
10
|
-
prefix: str,
|
|
11
|
-
name: str = "",
|
|
12
|
-
):
|
|
8
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
13
9
|
with self.add_children_as_readables():
|
|
14
10
|
self.ds_x = Motor(prefix + "X2")
|
|
15
11
|
self.ds_y = Motor(prefix + "J3")
|
dodal/devices/i15/rail.py
CHANGED
|
@@ -3,11 +3,7 @@ from ophyd_async.epics.motor import Motor
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class Rail(StandardReadable):
|
|
6
|
-
def __init__(
|
|
7
|
-
self,
|
|
8
|
-
prefix: str,
|
|
9
|
-
name: str = "",
|
|
10
|
-
):
|
|
6
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
11
7
|
with self.add_children_as_readables():
|
|
12
8
|
self.pitch = Motor(prefix + "PITCH")
|
|
13
9
|
self.y = Motor(prefix + "Y")
|
|
File without changes
|
|
File without changes
|
|
@@ -5,11 +5,13 @@ from pathlib import Path
|
|
|
5
5
|
from bluesky.protocols import StreamAsset
|
|
6
6
|
from event_model import DataKey # type: ignore
|
|
7
7
|
from ophyd_async.core import (
|
|
8
|
+
AsyncStatus,
|
|
8
9
|
AutoIncrementingPathProvider,
|
|
9
10
|
DetectorWriter,
|
|
10
11
|
StandardDetector,
|
|
11
12
|
StandardReadable,
|
|
12
13
|
StaticPathProvider,
|
|
14
|
+
TriggerInfo,
|
|
13
15
|
observe_value,
|
|
14
16
|
wait_for_value,
|
|
15
17
|
)
|
|
@@ -40,6 +42,7 @@ class JunfrauCommissioningWriter(DetectorWriter, StandardReadable):
|
|
|
40
42
|
self.file_name = epics_signal_rw_rbv(str, f"{prefix}FileName")
|
|
41
43
|
self.file_path = epics_signal_rw_rbv(str, f"{prefix}FilePath")
|
|
42
44
|
self.writer_ready = epics_signal_r(int, f"{prefix}Ready_RBV")
|
|
45
|
+
self.expected_frames = epics_signal_rw(int, f"{prefix}NumCapture")
|
|
43
46
|
super().__init__(name)
|
|
44
47
|
|
|
45
48
|
async def open(self, name: str, exposures_per_event: int = 1) -> dict[str, DataKey]:
|
|
@@ -80,7 +83,7 @@ class JunfrauCommissioningWriter(DetectorWriter, StandardReadable):
|
|
|
80
83
|
async def observe_indices_written(
|
|
81
84
|
self, timeout: float
|
|
82
85
|
) -> AsyncGenerator[int, None]:
|
|
83
|
-
timeout = timeout *
|
|
86
|
+
timeout = timeout * 4 # This filewriter is very slow
|
|
84
87
|
async for num_captured in observe_value(self.frame_counter, timeout):
|
|
85
88
|
yield num_captured // (self._exposures_per_event)
|
|
86
89
|
|
|
@@ -112,3 +115,8 @@ class CommissioningJungfrau(
|
|
|
112
115
|
writer = JunfrauCommissioningWriter(writer_prefix, path_provider)
|
|
113
116
|
controller = JungfrauController(self.drv)
|
|
114
117
|
super().__init__(controller, writer, name=name)
|
|
118
|
+
|
|
119
|
+
@AsyncStatus.wrap
|
|
120
|
+
async def prepare(self, value: TriggerInfo) -> None:
|
|
121
|
+
await super().prepare(value)
|
|
122
|
+
await self._writer.expected_frames.set(value.total_number_of_exposures)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|