dls-dodal 1.56.0__py3-none-any.whl → 1.57.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.57.0.dist-info}/METADATA +2 -2
- {dls_dodal-1.56.0.dist-info → dls_dodal-1.57.0.dist-info}/RECORD +16 -16
- dodal/_version.py +2 -2
- dodal/beamlines/i17.py +37 -0
- dodal/beamlines/i22.py +3 -3
- dodal/beamlines/i24.py +2 -21
- dodal/devices/i24/beam_center.py +1 -2
- dodal/devices/smargon.py +33 -16
- dodal/devices/thawer.py +17 -5
- dodal/devices/webcam.py +1 -0
- 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.57.0.dist-info}/WHEEL +0 -0
- {dls_dodal-1.56.0.dist-info → dls_dodal-1.57.0.dist-info}/entry_points.txt +0 -0
- {dls_dodal-1.56.0.dist-info → dls_dodal-1.57.0.dist-info}/licenses/LICENSE +0 -0
- {dls_dodal-1.56.0.dist-info → dls_dodal-1.57.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.57.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.57.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=UMWpFq_XEVs_RQua2c3vn_WoxKKPZqViS9Btwn1PIkY,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
|
|
@@ -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
35
|
dodal/beamlines/i19_2.py,sha256=xSMS2Vhk_6V5WYyefVo1SWXbC4UUyaqru7JVK8VTg00,2554
|
|
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
|
|
@@ -90,15 +91,15 @@ dodal/devices/robot.py,sha256=k4Vkjpd3R-wXWf6YbYC1225sSdjvTrZS54v5v6Qy_EU,7003
|
|
|
90
91
|
dodal/devices/s4_slit_gaps.py,sha256=4KdarIQoRqX4ry3LUS1Km7fkjUFahA0VuTd2DvYEqQ8,446
|
|
91
92
|
dodal/devices/scintillator.py,sha256=JresF8SY_-t1raibzR4f0UoMXnFi-Abh3ywGm2DjhKs,3003
|
|
92
93
|
dodal/devices/slits.py,sha256=b_7ku2sHlzhMHTvWrwiRwee6ufrbxNX9JB_Z0lvk15o,1105
|
|
93
|
-
dodal/devices/smargon.py,sha256=
|
|
94
|
+
dodal/devices/smargon.py,sha256=48oOBOKlsvPhlUlK41ozXzCMUKMp3QkQx-pVqKL2Xts,6569
|
|
94
95
|
dodal/devices/status.py,sha256=hVrJS1yooQo6PRumRACoIEh-SKBUKxvBlQl-MtLFUMQ,327
|
|
95
96
|
dodal/devices/synchrotron.py,sha256=OHBrTrm4K39XE8BrE9b_Jn_ZfMRyDp9CHCwvmiV-KOc,1989
|
|
96
97
|
dodal/devices/tetramm.py,sha256=qBu2ClXRM4RFO-y4C2pXVKsp5sX4VpOelbVHOAkkUHQ,8936
|
|
97
|
-
dodal/devices/thawer.py,sha256=
|
|
98
|
+
dodal/devices/thawer.py,sha256=HexahKZ1rUxF9jBMeULruqYt6I7fsl6OgXkvcxPQY3M,1963
|
|
98
99
|
dodal/devices/turbo_slit.py,sha256=xhcnhfbdcTYSYozogw6Li4fF4ofoPsc350rEyrRdaNE,1460
|
|
99
100
|
dodal/devices/undulator.py,sha256=3IRn1iOF1PLOuIzaMpsNLVYx-rGvAnr-PG7C3YupW-w,5266
|
|
100
101
|
dodal/devices/watsonmarlow323_pump.py,sha256=xNwjoxW3NJIDkeDWHfb0A8Yj95_KKRXMD9AghvX-WLk,1337
|
|
101
|
-
dodal/devices/webcam.py,sha256=
|
|
102
|
+
dodal/devices/webcam.py,sha256=UAx2KF0mKi6I-mJJUb5z56MHY-Wd89-tqyPcFbouQFg,2491
|
|
102
103
|
dodal/devices/xbpm_feedback.py,sha256=Uv_jML9gkMT5OcpUrckzxDmsBmktEwV1lga6USxeRyY,1065
|
|
103
104
|
dodal/devices/aithre_lasershaping/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
104
105
|
dodal/devices/aithre_lasershaping/goniometer.py,sha256=-2ewYMcdzB1DqP9sMpr4L1i4KeTCrGAJfngAt9-eFWw,1005
|
|
@@ -192,12 +193,11 @@ dodal/devices/i22/fswitch.py,sha256=kpgegs4Wv_weBSzbrlXLXqXOOZdzTn3X9k5PlEN5F6c,
|
|
|
192
193
|
dodal/devices/i22/nxsas.py,sha256=093GCM2H2LESt28RF-JfxEljJ8QzRPkL1ByXI2XVhoA,6012
|
|
193
194
|
dodal/devices/i24/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
194
195
|
dodal/devices/i24/aperture.py,sha256=dlH_g7OPTBc5QRMd-ADU3_GDTKh668kkMHo4k_JxUcY,770
|
|
195
|
-
dodal/devices/i24/beam_center.py,sha256=
|
|
196
|
+
dodal/devices/i24/beam_center.py,sha256=nQyOif6JtlU_qP7kZP-8wN1ldW81MIbFUykPC1bEm70,446
|
|
196
197
|
dodal/devices/i24/beamstop.py,sha256=6tbiQLlcTlp4PCPhHJ_mlHtkv0kz5ArQ99zg9rwTnrw,1133
|
|
197
198
|
dodal/devices/i24/dcm.py,sha256=l7qbJh2JKL-5ANlMYXDeU5EBYY6mDiLxn7kp_Z9KNaM,1206
|
|
198
199
|
dodal/devices/i24/dual_backlight.py,sha256=N0R7M1mHPRmQ4fks5lGU1wrXjOvcW_ZKIXaRoC8aLDE,2084
|
|
199
200
|
dodal/devices/i24/focus_mirrors.py,sha256=DYiYLpDw8FJ1LYHxLOxE_om5qGfUo2itzskgqhmQZlg,1763
|
|
200
|
-
dodal/devices/i24/pilatus_metadata.py,sha256=I-AR8vd67qf6p0vZnRPTv4aNPN5T4KpSt2Iog4_jvn0,1781
|
|
201
201
|
dodal/devices/i24/pmac.py,sha256=-HYf2HPzaqWvszp4T8TXohdp40-xmKqQq4V0mLvVri8,7028
|
|
202
202
|
dodal/devices/i24/vgonio.py,sha256=sxSmcYZayVJPJz_D_91j9PmNor7Tbl1RGQFRrdtESlw,533
|
|
203
203
|
dodal/devices/mx_phase1/beamstop.py,sha256=GeHLqHVf3XwJSszUHuxZ2JBwQlcDiFs6jVpdHuw7snM,3127
|
|
@@ -224,7 +224,6 @@ dodal/devices/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
|
|
|
224
224
|
dodal/devices/util/adjuster_plans.py,sha256=c40PFZpXFw0YmJLh9jU4VIb8vRxHyafZlmvprTKAOhM,824
|
|
225
225
|
dodal/devices/util/epics_util.py,sha256=4useFL8ngsVF08fhOn48BlnO4oh0T4sEKqjdS6mjvG0,4687
|
|
226
226
|
dodal/devices/util/lookup_tables.py,sha256=jH9f_D8JbTSqzL-RKHUWOORLt8lEoNQL3o9HpXE98TY,3476
|
|
227
|
-
dodal/devices/util/test_utils.py,sha256=tnKKmSBaHEyx-qTQjoR3COqraRMmTdRJe9s-pWjuTPk,1176
|
|
228
227
|
dodal/devices/xspress3/xspress3.py,sha256=OerapEy-IuK7EFz13B5z0BzBmESVl6pYUlqAWHIwJck,4555
|
|
229
228
|
dodal/devices/xspress3/xspress3_channel.py,sha256=w8tAx2lz5kJ_LeJ_eb_4o--Dtt8MRijsYNgDG6oEIVg,1626
|
|
230
229
|
dodal/devices/zebra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -250,11 +249,12 @@ dodal/plans/verify_undulator_gap.py,sha256=OcDN09-eCoMzsmhKGxvzsH5EapG2zYz0yGCqU
|
|
|
250
249
|
dodal/plans/wrapped.py,sha256=BPMw__RcWvk9v5XnhMsi9_k4KsDEbmXogzD2n1ecbUg,2098
|
|
251
250
|
dodal/plans/preprocessors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
252
251
|
dodal/plans/preprocessors/verify_undulator_gap.py,sha256=cBZEGq8TW1jrXFXB00iClQVXSEaE_jP_rHMY9WTgYyY,1813
|
|
253
|
-
dodal/testing/__init__.py,sha256=
|
|
252
|
+
dodal/testing/__init__.py,sha256=AUYZKAvVOs7ZvxO1dVhL0pDTleRO34FQlO5MNe_cwgU,96
|
|
253
|
+
dodal/testing/setup.py,sha256=8cQnrzE5MQD4Etf0eqMarmtr-opsUOMQww-k1V7DzIQ,2442
|
|
254
254
|
dodal/testing/electron_analyser/__init__.py,sha256=-lc1opD2dCv0x678-J-ApOhHtvEvcslfOQ7E613U8-Y,118
|
|
255
255
|
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.
|
|
256
|
+
dls_dodal-1.57.0.dist-info/METADATA,sha256=8uZwtRMSABZLLYumDM2RDWn4zaE5IJ6N5H5zMk5Vz1w,16928
|
|
257
|
+
dls_dodal-1.57.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
258
|
+
dls_dodal-1.57.0.dist-info/entry_points.txt,sha256=bycw_EKUzup_rxfCetOwcauXV4kLln_OPpPT8jEnr-I,94
|
|
259
|
+
dls_dodal-1.57.0.dist-info/top_level.txt,sha256=xIozdmZk_wmMV4wugpq9-6eZs0vgADNUKz3j2UAwlhc,6
|
|
260
|
+
dls_dodal-1.57.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.57.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 57, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
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/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
|
-
)
|
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/webcam.py
CHANGED
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
|