dls-dodal 1.28.0__py3-none-any.whl → 1.29.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dls-dodal
3
- Version: 1.28.0
3
+ Version: 1.29.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>
6
6
  License: Apache License
@@ -215,7 +215,7 @@ Description-Content-Type: text/x-rst
215
215
  License-File: LICENSE
216
216
  Requires-Dist: click
217
217
  Requires-Dist: ophyd
218
- Requires-Dist: ophyd-async >=0.3a5
218
+ Requires-Dist: ophyd-async >=0.3.1
219
219
  Requires-Dist: bluesky
220
220
  Requires-Dist: pyepics
221
221
  Requires-Dist: dataclasses-json
@@ -227,7 +227,7 @@ Requires-Dist: pydantic
227
227
  Requires-Dist: opencv-python-headless
228
228
  Requires-Dist: aioca
229
229
  Requires-Dist: p4p
230
- Requires-Dist: numpy
230
+ Requires-Dist: numpy <2.0
231
231
  Requires-Dist: aiofiles
232
232
  Requires-Dist: aiohttp
233
233
  Provides-Extra: dev
@@ -1,6 +1,6 @@
1
1
  dodal/__init__.py,sha256=y-VRpfiX-Lm5nchB9N0VfMy_6dwFqVxpSn5SiAQql9I,114
2
2
  dodal/__main__.py,sha256=kP2S2RPitnOWpNGokjZ1Yq-1umOtp5sNOZk2B3tBPLM,111
3
- dodal/_version.py,sha256=RW6USZoeFR_9ttdXBH9tb0lK1erQEYot3NzmBpWXDMs,413
3
+ dodal/_version.py,sha256=IpRR4M6LqazbEQMvyYdrRT7AijfNAsCfLKuNjjsDX4s,413
4
4
  dodal/adsim.py,sha256=OW2dcS7ciD4Yq9WFw4PN_c5Bwccrmu7R-zr-u6ZCbQM,497
5
5
  dodal/cli.py,sha256=z0UBESrNrq6Kq4rttp4uHcwS1fnOnRkKBRDHSriPpGY,2058
6
6
  dodal/log.py,sha256=grK5-c-V6UjMERwDqYPdKbc_BpycrNb8hP0uteLOVCY,8296
@@ -9,11 +9,11 @@ dodal/beamline_specific_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
9
9
  dodal/beamline_specific_utils/i03.py,sha256=Ixe1anFQl-kwRJubmQx28TIW4Zw8qDxpElNNNapWQHI,396
10
10
  dodal/beamlines/README.md,sha256=K9MkL_GomxlsoTB7Mz-_dJA5NNSbmCfMiutchGg3C8o,404
11
11
  dodal/beamlines/__init__.py,sha256=U0dQYFEUloCdQOs24zyfpPTncJXOO4cDcfHSevVOAw4,2890
12
- dodal/beamlines/i03.py,sha256=LcE9Vir0cCjt9pxO2wcevlM0NTP6NBCxp6DNtShPV0E,16914
12
+ dodal/beamlines/i03.py,sha256=J-4GawTxAhrYDQZh87n11L9ehTgObEQ1Lz2PueXCWbc,16892
13
13
  dodal/beamlines/i04.py,sha256=JOyNcUnC3wva4no2MHKp6b8gOKAcQXL_c4cBo7oneVs,13034
14
14
  dodal/beamlines/i04_1.py,sha256=KDxSUQNhIs_NFiRaLY-Jiory0DeN7Y0ErvGuoTrwCDU,4731
15
- dodal/beamlines/i20_1.py,sha256=XJpey1-XZnCVpjK6-tODRYeBofqV44BL8lK5OSdQgiI,746
16
- dodal/beamlines/i22.py,sha256=Lk5S5AHu9hCnqlJJHZj1fhSDm1sTOgEVMe1S20nVqeY,8786
15
+ dodal/beamlines/i20_1.py,sha256=MaPgONHqpoZuBtkiKEzYtViJnKBM2_ekeP4OdbmuXHE,1158
16
+ dodal/beamlines/i22.py,sha256=toBwXJiAFbie_puNJzrV1gSUD1FRO2KT9RastqhPNMw,9836
17
17
  dodal/beamlines/i23.py,sha256=iEFkrA4sPQsRLGAmeD263jPMX4u2SF1NK4_KYqnVwow,1402
18
18
  dodal/beamlines/i24.py,sha256=LIe8tu_ZJsoeQH7tYRZHSvqQ9C9zBGOXO6rb1DPCYjQ,4595
19
19
  dodal/beamlines/p38.py,sha256=TC78u4GwEnj6X0r5cnHhqNdBbbDRnh8lY8pEucBZjEU,8006
@@ -50,28 +50,28 @@ dodal/devices/logging_ophyd_device.py,sha256=xw4lbyqq5_ehESGterVEfubJsBiJTWvBp5b
50
50
  dodal/devices/motors.py,sha256=T0wKGpRKhgduAQj3jE8CGmxy3cWMAFl9_glyjVZwjnA,1473
51
51
  dodal/devices/p45.py,sha256=jzBW2fGRhIbGzSRs5Fgupxro6aqE611n1RTcrTTG-yY,1047
52
52
  dodal/devices/qbpm1.py,sha256=OY7-WbdxMiLGUK8Z57ezwqSXbHxoPP-y3GvBgj9kgMA,220
53
- dodal/devices/robot.py,sha256=V5Gk-e1ZczU7y8SqU4_1YXYQJ6knoVFtXLZmIDY9MI4,2530
53
+ dodal/devices/robot.py,sha256=RcSqBPMMUpWyP7LoyifatII5GWup-vFYZutniM60m_k,4231
54
54
  dodal/devices/s4_slit_gaps.py,sha256=j3kgF9WfGFaU9xdUuiAh-QqI5u_vhiAftaDVINt91SM,243
55
55
  dodal/devices/scatterguard.py,sha256=0qnvhoo3RjLsrxVgIoDJpryqunlgMVgaTsoyKRC2g4Y,331
56
56
  dodal/devices/scintillator.py,sha256=4Dej1a6HRom9GRwTDsaTKGfvloP20POUqIeHqsI8-R8,184
57
57
  dodal/devices/slits.py,sha256=URru9VN2N19KqeUPDZaBmyKYn0_JJiE0Vko4sZpfsl8,601
58
58
  dodal/devices/smargon.py,sha256=ml96h7E1C31qPo8jocAepSouIVXgpIR0vuMF99nZjqM,2964
59
59
  dodal/devices/status.py,sha256=TuUGidZ4Ar-WCRc_sX0wn58DmL6brj1pMr8rNF5Z6VU,1198
60
- dodal/devices/synchrotron.py,sha256=E5vcSum-zoD5vIZxa2Xcl0gAkeRqY6a-AfZQICCwLHg,1947
61
- dodal/devices/tetramm.py,sha256=Xdy3dXFo4Wn6HHsRo4e1tTgMzvDa8MwkVvcDFZxFrYQ,8280
60
+ dodal/devices/synchrotron.py,sha256=QtTufJA_fCaBawHougSc7nxwu240oX46_y0P-4qIW8o,1960
61
+ dodal/devices/tetramm.py,sha256=XriN-zBFVnHxhnTbphSPIZcxEbdWBTbw2g_ulUBl4bw,8538
62
62
  dodal/devices/thawer.py,sha256=L5OYSdzGvx6dIkGgcTbITAbFAm0OKEVVqYBb4MPstOg,382
63
63
  dodal/devices/turbo_slit.py,sha256=W3ZRIqDhq4iMhr5GcIiWvl2U1GaPtGanqkL7upQOZTY,1132
64
64
  dodal/devices/undulator.py,sha256=kn84MQpuBHtQj7H7HeBoAYKXu5buGKvTgs3tf2gdEdw,2074
65
65
  dodal/devices/undulator_dcm.py,sha256=TC9fO55r1YIG_88PPbGGtzfjcRJcaoC2ny51JiDOEX4,5199
66
- dodal/devices/webcam.py,sha256=dvNWJ6hHQR7BUsMRC9TH4XiCCofVhlgZ8HYfVCvd2og,1367
67
- dodal/devices/xbpm_feedback.py,sha256=a4evzdoMANbwoboQCbdMkcrxRogXLnHs966SZJsywYQ,1521
66
+ dodal/devices/webcam.py,sha256=FXYcxQdOOCRIMAf8jMWlDVAhSEs4ycGCnoODvHb-apM,1554
67
+ dodal/devices/xbpm_feedback.py,sha256=8QHYKHo9ksZo30olbFM-tHpCHcJRFozgHKVJijv3Gck,1986
68
68
  dodal/devices/zebra.py,sha256=XE2oEm6kLkXd86ev4dYP8bh3tI9Fesb1SmU61RSMHBA,9082
69
69
  dodal/devices/zebra_controlled_shutter.py,sha256=MqX4KE6w0FliZRDBltswcLCNSsp6vQrD_iBY640IljI,1094
70
70
  dodal/devices/areadetector/__init__.py,sha256=8IwLxuZMW0MOJpJp_ZDdlaE20hrtsH_PXWGaKgMiYs4,240
71
71
  dodal/devices/areadetector/adaravis.py,sha256=pwbmmnakarjhD59XoyAIXJdakS-nqDG09Xmwq17AVw4,3787
72
72
  dodal/devices/areadetector/adsim.py,sha256=3U7kS93RM3Xeh-XWKjeuw5jXbIGWAbrs59LfxtvB7OU,1907
73
73
  dodal/devices/areadetector/adutils.py,sha256=JIx1_sYlehpLtEXcwOEuzVoMplsLdKVW7OWv5eiJqgE,2576
74
- dodal/devices/areadetector/plugins/MJPG.py,sha256=2ISGUg9JxJYzEH640WUIsvFwKolSTywkTyPy9wz6f_k,4064
74
+ dodal/devices/areadetector/plugins/MJPG.py,sha256=pLuEZiRGgCwJM1ONA5jdetGLo6O0OVhvmcVkkYtPeR8,4159
75
75
  dodal/devices/detector/__init__.py,sha256=XEwjopgTtBq93RRuFthVVVI9DT1jUvpOJzWOHantJpU,104
76
76
  dodal/devices/detector/det_dim_constants.py,sha256=MZ4w2nsTKzj4eN7yGsSs1pqKWIuU4vc6UzcSll02uWg,2305
77
77
  dodal/devices/detector/det_dist_to_beam_converter.py,sha256=f6JFp-eEB2v8NzZg27UrN0VDP5CMjRnaPU6BTA7_n_s,1937
@@ -81,15 +81,16 @@ dodal/devices/detector/detector_motion.py,sha256=REREva2kyPcIzOZmahN9rT0jDSuUbV0
81
81
  dodal/devices/i03/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
82
  dodal/devices/i04/transfocator.py,sha256=uieByXIj0JRbmvMB_om5NOAEbEJkzfkCD24bl2aEo1g,3154
83
83
  dodal/devices/i20_1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
- dodal/devices/i22/dcm.py,sha256=ZJL-K7GdJxyH-0wKsV0psX8iaFYJINpqBZljfAyuLbs,6046
84
+ dodal/devices/i22/dcm.py,sha256=Kzyd_qFg8KVhRsgfTQVOpghESE8yIOgACKa0Fv9NaZI,6270
85
85
  dodal/devices/i22/fswitch.py,sha256=AdYtnkCBuhivyJGZqelg_7sjB2pHN7vl1JTtlO4vHo4,3061
86
+ dodal/devices/i22/nxsas.py,sha256=ky7v9UZ1UQFsm5hI0wD9OXG-fTKFLj2wJjB7wADxKpw,5655
86
87
  dodal/devices/i23/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
88
  dodal/devices/i23/gonio.py,sha256=cxqD2Kd578c4-K4h2sHdJjoap2gPGC46Qr4SPudHLTs,864
88
89
  dodal/devices/i24/I24_detector_motion.py,sha256=bKbb44Qs24oguwJ780N4e5XGNtka_3ZZCGGq6BQu99Y,229
89
90
  dodal/devices/i24/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
91
  dodal/devices/i24/dual_backlight.py,sha256=5Xkkt4VqS-G1QLDmBJNHs-LNVYJ_aTso_ev8QNDJiis,1367
91
92
  dodal/devices/i24/i24_vgonio.py,sha256=Igqs7687z6lyhGVeJEDtDmPachYxU48MUH2BF0RpK9Q,461
92
- dodal/devices/i24/pmac.py,sha256=EFLclXWMh7eMk4YNutXeSdLyyqFSBpLe5O6HEWC8OQc,405
93
+ dodal/devices/i24/pmac.py,sha256=CdNLzRiOz2jFoZ80WQTdlHiYoDJeQWdqdKDkSKkCEkI,3872
93
94
  dodal/devices/oav/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
95
  dodal/devices/oav/grid_overlay.py,sha256=FRtjcFd420XY8MEQ9sWedL0i4pK-KUJOSxh2C5zM3PA,5232
95
96
  dodal/devices/oav/microns_for_zoom_levels.json,sha256=5PA71RzldFTp0eTUGPmov0MjxHe583mzvfor5f3thXI,1208
@@ -97,7 +98,7 @@ dodal/devices/oav/oav_calculations.py,sha256=wt71vFcyQrr98FvX8oyUM2n5vmKi3K7PyOT
97
98
  dodal/devices/oav/oav_detector.py,sha256=JtzRdFQVXUdVK4Qyd9knDhsfkK6tsXoD_rIWDpLdpD4,3654
98
99
  dodal/devices/oav/oav_errors.py,sha256=cc4mGnaTiAc5WIlOt_BIYOc7CRSkrCdnBaavfAJ0pXY,754
99
100
  dodal/devices/oav/oav_parameters.py,sha256=4XybkhKeG7IEjPRfx0PVM9KNenuyN0rAGWBZG7H3zvQ,7941
100
- dodal/devices/oav/utils.py,sha256=BkTk0aTqqhIHCZInhcUAYjCRPxumPOlTg9m21skncTc,3018
101
+ dodal/devices/oav/utils.py,sha256=zbUDvNETDoCtclj5jNzxz1XBt5mQlWBbxUrhRP7pZrU,3663
101
102
  dodal/devices/oav/pin_image_recognition/__init__.py,sha256=qEX3BRnrcP1BLZD-f_smHiMMPLJPkWQZQbIWTbW25JA,6499
102
103
  dodal/devices/oav/pin_image_recognition/manual_test.py,sha256=h1Rto6ZDCB3jWhjSy9N8ECxRN583iYDJr9LxrTJ8kfE,903
103
104
  dodal/devices/oav/pin_image_recognition/utils.py,sha256=-7-Zs-331UVTq_AZrfdF-zwZdmMn7eitTkBSqnBrxnk,8620
@@ -106,17 +107,17 @@ dodal/devices/util/adjuster_plans.py,sha256=2AYaywQP_LbA2KJ6Op3cok8GoRtj696utrSS
106
107
  dodal/devices/util/epics_util.py,sha256=FSiTgBhm4id1nILM3UUD7V3eDjJM4DEMIG_wEwzM8Tk,4441
107
108
  dodal/devices/util/lookup_tables.py,sha256=Up-0BlARt79TIEM76SkDyn9LtTFLxPUcaEPZv6D6bws,2141
108
109
  dodal/devices/util/motor_utils.py,sha256=pNY-aUk9LxaIWeDr5rpMS6udiB9j19wcCXkNDLp1uA0,257
109
- dodal/devices/xspress3_mini/xspress3_mini.py,sha256=gBLr_sdt4HmGLAJUimZ4MlPu_0B6gVmjUmYYQYCSTAc,2858
110
- dodal/devices/xspress3_mini/xspress3_mini_channel.py,sha256=eKmsgf4AFaVOwpB2o-5B7EOr9xn4d0A_0gGPuQv3ohk,810
110
+ dodal/devices/xspress3/xspress3.py,sha256=29elzI3JtceryKeMWXhcP9nWl0tlSdnTZhltCitet6A,4668
111
+ dodal/devices/xspress3/xspress3_channel.py,sha256=yJRwseLmtkW2Vv6GB8sLdOFuBn3e4c9Q8fgPacMgl5w,1638
111
112
  dodal/devices/zocalo/__init__.py,sha256=oPhjFB39yf2NWkGD-MMcPFnnOVZ_RtdyBt2OLYn-Xa4,505
112
113
  dodal/devices/zocalo/zocalo_interaction.py,sha256=B6TBTDwUlluksLTwC4TiEEgfFzWLOmwgG8xM5Xd4Wik,3132
113
114
  dodal/devices/zocalo/zocalo_results.py,sha256=U4Vk4OF-eL8w0BR-fbw3k4jyRo6G3Ywaf8NMAkjr4Hs,9658
114
115
  dodal/parameters/experiment_parameter_base.py,sha256=O7JamfuJ5cYHkPf9tsHJPqn-OMHTAGouigvM1cDFehE,313
115
- dodal/plans/check_topup.py,sha256=VOkHak88_r-pdTsSnwAJnbvlK2_UhKnO5I36pJmWKvQ,2985
116
+ dodal/plans/check_topup.py,sha256=Pj6Eu8fa6nvoW4awrMxvzE_ftpLfYz8bN0QDLRw0Yuk,2989
116
117
  dodal/plans/data_session_metadata.py,sha256=QNx9rb1EfGBHb21eFekIi7KjNhC0PL-SVKBCggDuNeg,1650
117
- dls_dodal-1.28.0.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
118
- dls_dodal-1.28.0.dist-info/METADATA,sha256=1EiYYnvAHwt0rilBYosSJaPDpF34SdatvnYUuqud9lE,16837
119
- dls_dodal-1.28.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
120
- dls_dodal-1.28.0.dist-info/entry_points.txt,sha256=wpzz9FsTiYxI8OBwLKX9V9ResLwThBSmtRMcPwII0FA,46
121
- dls_dodal-1.28.0.dist-info/top_level.txt,sha256=xIozdmZk_wmMV4wugpq9-6eZs0vgADNUKz3j2UAwlhc,6
122
- dls_dodal-1.28.0.dist-info/RECORD,,
118
+ dls_dodal-1.29.0.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
119
+ dls_dodal-1.29.0.dist-info/METADATA,sha256=ydEXpqy3OYgQ-oGOFOzOFk_D4Xhr9N7zUQfvWp51Evo,16842
120
+ dls_dodal-1.29.0.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
121
+ dls_dodal-1.29.0.dist-info/entry_points.txt,sha256=wpzz9FsTiYxI8OBwLKX9V9ResLwThBSmtRMcPwII0FA,46
122
+ dls_dodal-1.29.0.dist-info/top_level.txt,sha256=xIozdmZk_wmMV4wugpq9-6eZs0vgADNUKz3j2UAwlhc,6
123
+ dls_dodal-1.29.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
dodal/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.28.0'
16
- __version_tuple__ = version_tuple = (1, 28, 0)
15
+ __version__ = version = '1.29.0'
16
+ __version_tuple__ = version_tuple = (1, 29, 0)
dodal/beamlines/i03.py CHANGED
@@ -30,7 +30,7 @@ from dodal.devices.undulator import Undulator
30
30
  from dodal.devices.undulator_dcm import UndulatorDCM
31
31
  from dodal.devices.webcam import Webcam
32
32
  from dodal.devices.xbpm_feedback import XBPMFeedback
33
- from dodal.devices.xspress3_mini.xspress3_mini import Xspress3Mini
33
+ from dodal.devices.xspress3.xspress3 import Xspress3
34
34
  from dodal.devices.zebra import Zebra
35
35
  from dodal.devices.zebra_controlled_shutter import ZebraShutter
36
36
  from dodal.devices.zocalo import ZocaloResults
@@ -363,12 +363,12 @@ def zebra(wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False) -
363
363
 
364
364
  def xspress3mini(
365
365
  wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False
366
- ) -> Xspress3Mini:
366
+ ) -> Xspress3:
367
367
  """Get the i03 Xspress3Mini device, instantiate it if it hasn't already been.
368
368
  If this is called when already instantiated in i03, it will return the existing object.
369
369
  """
370
370
  return device_instantiation(
371
- Xspress3Mini,
371
+ Xspress3,
372
372
  "xspress3mini",
373
373
  "-EA-XSP3-01:",
374
374
  wait_for_connection,
dodal/beamlines/i20_1.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from dodal.common.beamlines.beamline_utils import device_instantiation
2
2
  from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
3
3
  from dodal.devices.turbo_slit import TurboSlit
4
+ from dodal.devices.xspress3.xspress3 import Xspress3
4
5
  from dodal.log import set_beamline as set_log_beamline
5
6
  from dodal.utils import get_beamline_name
6
7
 
@@ -23,3 +24,20 @@ def turbo_slit(
23
24
  wait=wait_for_connection,
24
25
  fake=fake_with_ophyd_sim,
25
26
  )
27
+
28
+
29
+ def xspress3(
30
+ wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False
31
+ ) -> Xspress3:
32
+ """
33
+ 16 channels Xspress3 detector
34
+ """
35
+
36
+ return device_instantiation(
37
+ Xspress3,
38
+ prefix="-EA-DET-03:",
39
+ name="Xspress3",
40
+ num_channels=16,
41
+ wait=wait_for_connection,
42
+ fake=fake_with_ophyd_sim,
43
+ )
dodal/beamlines/i22.py CHANGED
@@ -10,10 +10,11 @@ from dodal.common.beamlines.beamline_utils import (
10
10
  )
11
11
  from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
12
12
  from dodal.common.beamlines.device_helpers import numbered_slits
13
- from dodal.common.visit import LocalDirectoryServiceClient, StaticVisitDirectoryProvider
13
+ from dodal.common.visit import DirectoryServiceClient, StaticVisitDirectoryProvider
14
14
  from dodal.devices.focusing_mirror import FocusingMirror
15
15
  from dodal.devices.i22.dcm import CrystalMetadata, DoubleCrystalMonochromator
16
16
  from dodal.devices.i22.fswitch import FSwitch
17
+ from dodal.devices.i22.nxsas import NXSasMetadataHolder, NXSasOAV, NXSasPilatus
17
18
  from dodal.devices.linkam3 import Linkam3
18
19
  from dodal.devices.slits import Slits
19
20
  from dodal.devices.synchrotron import Synchrotron
@@ -35,7 +36,7 @@ set_directory_provider(
35
36
  StaticVisitDirectoryProvider(
36
37
  BL,
37
38
  Path("/dls/i22/data/2024/cm37271-2/bluesky"),
38
- client=LocalDirectoryServiceClient(),
39
+ client=DirectoryServiceClient("http://i22-control:8088/api"),
39
40
  )
40
41
  )
41
42
 
@@ -44,13 +45,22 @@ def saxs(
44
45
  wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False
45
46
  ) -> PilatusDetector:
46
47
  return device_instantiation(
47
- PilatusDetector,
48
+ NXSasPilatus,
48
49
  "saxs",
49
50
  "-EA-PILAT-01:",
50
51
  wait_for_connection,
51
52
  fake_with_ophyd_sim,
52
53
  drv_suffix="CAM:",
53
54
  hdf_suffix="HDF5:",
55
+ metadata_holder=NXSasMetadataHolder(
56
+ x_pixel_size=(1.72e-1, "mm"),
57
+ y_pixel_size=(1.72e-1, "mm"),
58
+ description="Dectris Pilatus3 2M",
59
+ type="Photon Counting Hybrid Pixel",
60
+ sensor_material="silicon",
61
+ sensor_thickness=(0.45, "mm"),
62
+ distance=(4711.833684146172, "mm"),
63
+ ),
54
64
  directory_provider=get_directory_provider(),
55
65
  )
56
66
 
@@ -71,13 +81,22 @@ def waxs(
71
81
  wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False
72
82
  ) -> PilatusDetector:
73
83
  return device_instantiation(
74
- PilatusDetector,
84
+ NXSasPilatus,
75
85
  "waxs",
76
86
  "-EA-PILAT-03:",
77
87
  wait_for_connection,
78
88
  fake_with_ophyd_sim,
79
89
  drv_suffix="CAM:",
80
90
  hdf_suffix="HDF5:",
91
+ metadata_holder=NXSasMetadataHolder(
92
+ x_pixel_size=(1.72e-1, "mm"),
93
+ y_pixel_size=(1.72e-1, "mm"),
94
+ description="Dectris Pilatus3 2M",
95
+ type="Photon Counting Hybrid Pixel",
96
+ sensor_material="silicon",
97
+ sensor_thickness=(0.45, "mm"),
98
+ distance=(175.4199417092314, "mm"),
99
+ ),
81
100
  directory_provider=get_directory_provider(),
82
101
  )
83
102
 
@@ -92,6 +111,7 @@ def i0(
92
111
  "-EA-XBPM-02:",
93
112
  wait_for_connection,
94
113
  fake_with_ophyd_sim,
114
+ type="Cividec Diamond XBPM",
95
115
  directory_provider=get_directory_provider(),
96
116
  )
97
117
 
@@ -106,6 +126,7 @@ def it(
106
126
  "-EA-TTRM-02:",
107
127
  wait_for_connection,
108
128
  fake_with_ophyd_sim,
129
+ type="PIN Diode",
109
130
  directory_provider=get_directory_provider(),
110
131
  )
111
132
 
@@ -153,13 +174,13 @@ def dcm(
153
174
  usage="Bragg",
154
175
  type="silicon",
155
176
  reflection=(1, 1, 1),
156
- d_spacing=3.13475,
177
+ d_spacing=(3.13475, "nm"),
157
178
  ),
158
179
  crystal_2_metadata=CrystalMetadata(
159
180
  usage="Bragg",
160
181
  type="silicon",
161
182
  reflection=(1, 1, 1),
162
- d_spacing=3.13475,
183
+ d_spacing=(3.13475, "nm"),
163
184
  ),
164
185
  )
165
186
 
@@ -263,7 +284,6 @@ def fswitch(
263
284
  )
264
285
 
265
286
 
266
- # Must find which PandA IOC(s) are compatible
267
287
  # Must document what PandAs are physically connected to
268
288
  # See: https://github.com/bluesky/ophyd-async/issues/284
269
289
  def panda1(
@@ -325,18 +345,22 @@ def panda4(
325
345
  )
326
346
 
327
347
 
328
- @skip_device
329
348
  def oav(
330
349
  wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False
331
350
  ) -> AravisDetector:
332
351
  return device_instantiation(
333
- AravisDetector,
352
+ NXSasOAV,
334
353
  "oav",
335
354
  "-DI-OAV-01:",
336
355
  wait_for_connection,
337
356
  fake_with_ophyd_sim,
338
357
  drv_suffix="DET:",
339
358
  hdf_suffix="HDF5:",
359
+ metadata_holder=NXSasMetadataHolder(
360
+ x_pixel_size=(3.45e-3, "mm"), # Double check this figure
361
+ y_pixel_size=(3.45e-3, "mm"),
362
+ description="AVT Mako G-507B",
363
+ ),
340
364
  directory_provider=get_directory_provider(),
341
365
  )
342
366
 
@@ -8,6 +8,7 @@ from ophyd import Component, Device, DeviceStatus, EpicsSignal, EpicsSignalRO, S
8
8
  from PIL import Image, ImageDraw
9
9
 
10
10
  from dodal.devices.oav.oav_parameters import OAVConfigParams
11
+ from dodal.devices.oav.utils import save_thumbnail
11
12
  from dodal.log import LOGGER
12
13
 
13
14
 
@@ -49,6 +50,9 @@ class MJPG(Device, ABC):
49
50
 
50
51
  LOGGER.info(f"Saving image to {path}")
51
52
  image.save(path)
53
+
54
+ save_thumbnail(Path(path), image)
55
+
52
56
  self.last_saved_path.put(path)
53
57
 
54
58
  def trigger(self):
dodal/devices/i22/dcm.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import time
2
2
  from dataclasses import dataclass
3
- from typing import Dict, Literal
3
+ from typing import Dict, Literal, Sequence
4
4
 
5
5
  from bluesky.protocols import Reading
6
6
  from event_model.documents.event_descriptor import DataKey
@@ -23,7 +23,7 @@ class CrystalMetadata:
23
23
  usage: Literal["Bragg", "Laue"] | None = None
24
24
  type: str | None = None
25
25
  reflection: tuple[int, int, int] | None = None
26
- d_spacing: float | None = None
26
+ d_spacing: tuple[float, str] | None = None
27
27
 
28
28
 
29
29
  class DoubleCrystalMonochromator(StandardReadable):
@@ -86,13 +86,15 @@ class DoubleCrystalMonochromator(StandardReadable):
86
86
  self.crystal_1_type = None
87
87
  if crystal_1_metadata.reflection is not None:
88
88
  self.crystal_1_reflection, _ = soft_signal_r_and_setter(
89
- str, initial_value=crystal_1_metadata.reflection
89
+ Sequence[int], initial_value=list(crystal_1_metadata.reflection)
90
90
  )
91
91
  else:
92
92
  self.crystal_1_reflection = None
93
93
  if crystal_1_metadata.d_spacing is not None:
94
94
  self.crystal_1_d_spacing, _ = soft_signal_r_and_setter(
95
- str, initial_value=crystal_1_metadata.d_spacing
95
+ float,
96
+ initial_value=crystal_1_metadata.d_spacing[0],
97
+ units=crystal_1_metadata.d_spacing[1],
96
98
  )
97
99
  else:
98
100
  self.crystal_1_d_spacing = None
@@ -110,13 +112,15 @@ class DoubleCrystalMonochromator(StandardReadable):
110
112
  self.crystal_2_type = None
111
113
  if crystal_2_metadata.reflection is not None:
112
114
  self.crystal_2_reflection, _ = soft_signal_r_and_setter(
113
- str, initial_value=crystal_2_metadata.reflection
115
+ Sequence[int], initial_value=list(crystal_2_metadata.reflection)
114
116
  )
115
117
  else:
116
118
  self.crystal_2_reflection = None
117
119
  if crystal_2_metadata.d_spacing is not None:
118
120
  self.crystal_2_d_spacing, _ = soft_signal_r_and_setter(
119
- str, initial_value=crystal_2_metadata.d_spacing
121
+ float,
122
+ initial_value=crystal_2_metadata.d_spacing[0],
123
+ units=crystal_2_metadata.d_spacing[1],
120
124
  )
121
125
  else:
122
126
  self.crystal_2_d_spacing = None
@@ -0,0 +1,173 @@
1
+ from dataclasses import dataclass, fields
2
+ from typing import Dict
3
+
4
+ from bluesky.protocols import Reading
5
+ from event_model.documents.event_descriptor import DataKey
6
+ from ophyd_async.core import DirectoryProvider, merge_gathered_dicts
7
+ from ophyd_async.epics.areadetector import AravisDetector, PilatusDetector
8
+ from ophyd_async.epics.areadetector.aravis import AravisController
9
+
10
+ ValueAndUnits = tuple[float, str]
11
+
12
+
13
+ @dataclass
14
+ class MetadataHolder:
15
+ # TODO: just in case this is useful more widely...
16
+ async def describe(self, parent_name: str) -> Dict[str, DataKey]:
17
+ def datakey(value) -> DataKey:
18
+ if isinstance(value, tuple):
19
+ return {"units": value[1], **datakey(value[0])}
20
+ dtype = "string"
21
+ shape = []
22
+ match value:
23
+ case bool():
24
+ dtype = "boolean"
25
+ case int():
26
+ dtype = "integer"
27
+ case float():
28
+ dtype = "number"
29
+ case str():
30
+ dtype = "string"
31
+ case list():
32
+ dtype = "array"
33
+ shape = [len(value)]
34
+
35
+ return {"dtype": dtype, "shape": shape, "source": "calibration"}
36
+
37
+ return {
38
+ f"{parent_name}-{field.name}": datakey(getattr(self, field.name))
39
+ for field in fields(self)
40
+ if getattr(self, field.name, None) is not None
41
+ }
42
+
43
+ async def read(self, parent_name: str) -> Dict[str, Reading]:
44
+ def reading(value):
45
+ if isinstance(value, tuple):
46
+ return reading(value[0])
47
+ return {"timestamp": -1, "value": value}
48
+
49
+ return {
50
+ f"{parent_name}-{field.name}": reading(getattr(self, field.name))
51
+ for field in fields(self)
52
+ if getattr(self, field.name, None) is not None
53
+ }
54
+
55
+
56
+ @dataclass
57
+ class NXSasMetadataHolder(MetadataHolder):
58
+ """
59
+ Required fields for NXDetectors that are used in an NXsas application definition.
60
+ All fields are Configuration and read once per run only.
61
+ """
62
+
63
+ distance: ValueAndUnits
64
+ x_pixel_size: ValueAndUnits
65
+ y_pixel_size: ValueAndUnits
66
+ beam_center_x: ValueAndUnits | None = None
67
+ beam_center_y: ValueAndUnits | None = None
68
+ aequetorial_angle: ValueAndUnits | None = None
69
+ azimuthal_angle: ValueAndUnits | None = None
70
+ polar_angle: ValueAndUnits | None = None
71
+ rotation_angle: ValueAndUnits | None = None
72
+ threshold_energy: ValueAndUnits | None = None
73
+ serial_number: str | None = None
74
+ sensor_material: str | None = None
75
+ sensor_thickness: ValueAndUnits | None = None
76
+ description: str | None = None
77
+ type: str | None = None
78
+
79
+
80
+ class NXSasPilatus(PilatusDetector):
81
+ def __init__(
82
+ self,
83
+ prefix: str,
84
+ directory_provider: DirectoryProvider,
85
+ drv_suffix: str,
86
+ hdf_suffix: str,
87
+ metadata_holder: NXSasMetadataHolder,
88
+ name: str = "",
89
+ ):
90
+ """Extends detector with configuration metadata required or desired
91
+ to comply with the NXsas application definition.
92
+ Adds all values in the NXSasMetadataHolder's configuration fields
93
+ to the configuration of the parent device.
94
+ Writes hdf5 files."""
95
+ super().__init__(
96
+ prefix,
97
+ directory_provider,
98
+ drv_suffix=drv_suffix,
99
+ hdf_suffix=hdf_suffix,
100
+ name=name,
101
+ )
102
+ self._metadata_holder = metadata_holder
103
+
104
+ async def read_configuration(self) -> Dict[str, Reading]:
105
+ return await merge_gathered_dicts(
106
+ (
107
+ r
108
+ for r in (
109
+ super().read_configuration(),
110
+ self._metadata_holder.read(self.name),
111
+ )
112
+ )
113
+ )
114
+
115
+ async def describe_configuration(self) -> Dict[str, DataKey]:
116
+ return await merge_gathered_dicts(
117
+ (
118
+ r
119
+ for r in (
120
+ super().describe_configuration(),
121
+ self._metadata_holder.describe(self.name),
122
+ )
123
+ )
124
+ )
125
+
126
+
127
+ class NXSasOAV(AravisDetector):
128
+ def __init__(
129
+ self,
130
+ prefix: str,
131
+ directory_provider: DirectoryProvider,
132
+ drv_suffix: str,
133
+ hdf_suffix: str,
134
+ metadata_holder: NXSasMetadataHolder,
135
+ name: str = "",
136
+ gpio_number: AravisController.GPIO_NUMBER = 1,
137
+ ):
138
+ """Extends detector with configuration metadata required or desired
139
+ to comply with the NXsas application definition.
140
+ Adds all values in the NXSasMetadataHolder's configuration fields
141
+ to the configuration of the parent device.
142
+ Writes hdf5 files."""
143
+ super().__init__(
144
+ prefix,
145
+ directory_provider,
146
+ drv_suffix=drv_suffix,
147
+ hdf_suffix=hdf_suffix,
148
+ name=name,
149
+ gpio_number=gpio_number,
150
+ )
151
+ self._metadata_holder = metadata_holder
152
+
153
+ async def read_configuration(self) -> Dict[str, Reading]:
154
+ return await merge_gathered_dicts(
155
+ (
156
+ r
157
+ for r in (
158
+ super().read_configuration(),
159
+ self._metadata_holder.read(self.name),
160
+ )
161
+ )
162
+ )
163
+
164
+ async def describe_configuration(self) -> Dict[str, DataKey]:
165
+ return await merge_gathered_dicts(
166
+ (
167
+ r
168
+ for r in (
169
+ super().describe_configuration(),
170
+ self._metadata_holder.describe(self.name),
171
+ )
172
+ )
173
+ )