dls-dodal 1.31.1__py3-none-any.whl → 1.33.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.31.1
3
+ Version: 1.33.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
@@ -216,7 +216,7 @@ Description-Content-Type: text/markdown
216
216
  License-File: LICENSE
217
217
  Requires-Dist: click
218
218
  Requires-Dist: ophyd
219
- Requires-Dist: ophyd-async >=0.5.2
219
+ Requires-Dist: ophyd-async <0.7,>=0.6
220
220
  Requires-Dist: bluesky
221
221
  Requires-Dist: pyepics
222
222
  Requires-Dist: dataclasses-json
@@ -232,6 +232,7 @@ Requires-Dist: numpy <2.0
232
232
  Requires-Dist: aiofiles
233
233
  Requires-Dist: aiohttp
234
234
  Requires-Dist: redis
235
+ Requires-Dist: deepdiff
235
236
  Provides-Extra: dev
236
237
  Requires-Dist: black ; extra == 'dev'
237
238
  Requires-Dist: diff-cover ; extra == 'dev'
@@ -1,20 +1,21 @@
1
1
  dodal/__init__.py,sha256=v-rRiDOgZ3sQSMQKq0vgUQZvpeOkoHFXissAx6Ktg84,61
2
2
  dodal/__main__.py,sha256=kP2S2RPitnOWpNGokjZ1Yq-1umOtp5sNOZk2B3tBPLM,111
3
- dodal/_version.py,sha256=PiWs-LuU4Z2lwlP2cmR1JpAL95YAAdwL2Jy98tsKfJ0,413
3
+ dodal/_version.py,sha256=LSm0nkFA2tiEbj_K2UaSqjWn-14u8icXCZ6ghuRODjM,413
4
4
  dodal/adsim.py,sha256=OW2dcS7ciD4Yq9WFw4PN_c5Bwccrmu7R-zr-u6ZCbQM,497
5
5
  dodal/cli.py,sha256=_crmaHchxphSW8eEJB58_XZIeK82aiUv9bV7tpz-LpA,2122
6
6
  dodal/log.py,sha256=0to7CRsbzbgVfAAfKRAMhsaUuKqF2-7CGdQc-z8Uhno,9499
7
- dodal/utils.py,sha256=VV-IQHehAdE95wxq3C4kIl5Dt5MTtmgzVaqKm-k3Q4I,11769
7
+ dodal/utils.py,sha256=zlHPQjJOYeEvdC-UHPRvuTZaLt4hG6o9x2Vm4eHFBDU,11851
8
8
  dodal/beamline_specific_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  dodal/beamline_specific_utils/i03.py,sha256=eM6ZWZzpL0JYNBff8LhOnwFoZTJ5PDCY2XWI7ZKdtFY,276
10
10
  dodal/beamlines/README.md,sha256=K9MkL_GomxlsoTB7Mz-_dJA5NNSbmCfMiutchGg3C8o,404
11
11
  dodal/beamlines/__init__.py,sha256=CD0Dz2H1adLsqY4H3-_QxTdODPZD6mquMfsep5W5s0Q,3076
12
- dodal/beamlines/i03.py,sha256=VHfGk4-Smz5KviL4OpPVlnYGO4rbDAtnGwKtN20hxK0,17004
13
- dodal/beamlines/i04.py,sha256=JbpOssCBdpDd-TbElc0TfVOZ1tUnDjEFZkj5h1gR6Og,13767
12
+ dodal/beamlines/b01_1.py,sha256=nH1CzeGXc9kAZBxISsuQF33On9FuWkwFriGKfU8Qs5g,2176
13
+ dodal/beamlines/i03.py,sha256=8Lra4u1kLjWUoboxuSx6Po92OymRaKaJjM9ERr9zeUI,17004
14
+ dodal/beamlines/i04.py,sha256=pRVNIBaUn3oIgbxInCgBUwLqHtPirxf0fKfTfx4RcJ8,13877
14
15
  dodal/beamlines/i04_1.py,sha256=KDxSUQNhIs_NFiRaLY-Jiory0DeN7Y0ErvGuoTrwCDU,4731
15
16
  dodal/beamlines/i13_1.py,sha256=csXHrdwUh4sXTmb4X6ZiiSS_XxRkNShsVoBMxYI6rG0,1833
16
17
  dodal/beamlines/i20_1.py,sha256=MaPgONHqpoZuBtkiKEzYtViJnKBM2_ekeP4OdbmuXHE,1158
17
- dodal/beamlines/i22.py,sha256=ko3bo0WoZCFTSQkrNs9m_qDhvEpGWkSzEAZgpo0sRU0,9804
18
+ dodal/beamlines/i22.py,sha256=YWTz2PjOMTEO7n3QRfrCerIEUMHd6JTHsd2dYe_4F7c,9915
18
19
  dodal/beamlines/i23.py,sha256=2j5qLoqE_hg9ETHqNkOVu7LLkVB8qalgXeORnVYKN_I,1075
19
20
  dodal/beamlines/i24.py,sha256=1XVCNWbzowQB6CWpJGSLp9Ih0zypktIzHxb64h-Xj6Y,6583
20
21
  dodal/beamlines/p38.py,sha256=mCDjRVpY6AIFIAAYCWe-jGABHadFwfJB7poa-dGMU6s,7940
@@ -24,6 +25,7 @@ dodal/beamlines/training_rig.py,sha256=yagMEQruA1iTOeQCNpux-6xOtkBuB-hhGvAJwQ5c9
24
25
  dodal/common/__init__.py,sha256=ZC4ICKUDB0BDxRaVy8nmqclVmDBne-dPtk6UJsoFq6I,258
25
26
  dodal/common/coordination.py,sha256=OxIjDiO1-9A9KESRPFtzwkvvQlavbgA5RHemlbubBPg,1168
26
27
  dodal/common/maths.py,sha256=K9x7iL3xXLtWYTV-xlFHDNSTIL9a2UP3Ws7wr6Dm2rQ,1803
28
+ dodal/common/signal_utils.py,sha256=OsVJFntyTOHVEjhw27ZSp1e8SpKR2BhqdY1kzG6sago,1774
27
29
  dodal/common/types.py,sha256=r7Oxcw4lIGi-mvBWc1TF4LDB45q7N4IawNgOMhPohK8,621
28
30
  dodal/common/udc_directory_provider.py,sha256=H-9f6uSVGuA8jyiErPi8ikCw1JDrhRAJv-qPpN-HwJk,2379
29
31
  dodal/common/visit.py,sha256=2UbbCmgOjZWSCxFzE9RYiTJhA_IoVOegma-Jv-PJqps,5787
@@ -35,24 +37,24 @@ dodal/devices/CTAB.py,sha256=MoExneblYUHg9Va8vAVx_p_Vw_HnqbhkzxxrX7Ic_wo,2000
35
37
  dodal/devices/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
38
  dodal/devices/adsim.py,sha256=dMU0TKIuiODHYFHQOH4_5UvB8iJtaJEtjqaEDGjcU-w,311
37
39
  dodal/devices/aperture.py,sha256=BLaroQ3n8yd7uZyacJ3KvDWZH8yhA_sJc8b49QMKg9o,585
38
- dodal/devices/aperturescatterguard.py,sha256=id2-h6VB9hMU2dmgkpFkTLOPKiqAktMHsLb7YY0LX-4,8428
40
+ dodal/devices/aperturescatterguard.py,sha256=KW4ERvfMpUadixJlzCVU6oRvLqLm6pFvsldruplAHc4,8404
39
41
  dodal/devices/attenuator.py,sha256=viK1iccNekX6ZvR_ZmSwj5JdM1j2B8pcTg8qWDdmzhQ,2584
40
42
  dodal/devices/backlight.py,sha256=mOnptopsVOsT8JUIX_siDRgJ73CQPz_bm0Eb7oA81wc,1607
41
43
  dodal/devices/cryostream.py,sha256=CpNA2HGhN_PXkL9eqH_yAPsDxyOLIiehlUxEoNmXJVg,668
42
44
  dodal/devices/dcm.py,sha256=eZNMGjLM56Ll0siU14XomB77W_grLIdxIrMOQNmYFG8,1609
43
45
  dodal/devices/eiger.py,sha256=sR-Fr97Y0lzzq57fFOUTwUZw5E7asoj36A1JR1QUkLI,13985
44
46
  dodal/devices/eiger_odin.py,sha256=tDpEhOUY02YManYAMRI3TwSDDa3uITBxI0JHevaK7Rk,7010
45
- dodal/devices/fast_grid_scan.py,sha256=7u4YvaoR0CsKs9hgawi5p73v0dY_yJwC0_RlFz25R7Y,11922
47
+ dodal/devices/fast_grid_scan.py,sha256=WQGeKR-82fbnY4zUD_MQBsQyJgyIiuRpJK5nn_mfR1E,11969
46
48
  dodal/devices/fluorescence_detector_motion.py,sha256=5IcyaVHXa9TXLFlLB0tfpQ1_ThgIRJNaFNw_uj6ahCA,501
47
49
  dodal/devices/flux.py,sha256=RtPStHw7Mad0igVKntKWVZfuZn2clokVJqH14HLix6M,198
48
- dodal/devices/focusing_mirror.py,sha256=Gx3diH-0VH457MR40HMCovXRjcAALSCO0q2np4l-dL4,5911
50
+ dodal/devices/focusing_mirror.py,sha256=-jq2uqBfDjSgRVrV3-sqswPAND72cagBUQVvzd04diw,5901
49
51
  dodal/devices/hutch_shutter.py,sha256=_-hR3SJHM05YHV_fEtc0VYOLamYnpVGDE56AwJGJS48,3320
50
52
  dodal/devices/ipin.py,sha256=qsf8E3xrJYNDwzsacNLCCp3gaqsadqmN1b-Fvou8y8k,420
51
53
  dodal/devices/linkam3.py,sha256=3oYwPtaKSPvLKEat8m7tuhE4Wizz8mg8HMrEWPCYxn0,3820
52
54
  dodal/devices/logging_ophyd_device.py,sha256=dUVE-XhWA56WUXez0mrc4sf322CXY3MVLreTycO5j_A,668
53
55
  dodal/devices/motors.py,sha256=dYa9T6FDMTbr8GvTb-lXtk3v4QEqAWRuGmHIO20fazQ,1039
54
56
  dodal/devices/p45.py,sha256=jzBW2fGRhIbGzSRs5Fgupxro6aqE611n1RTcrTTG-yY,1047
55
- dodal/devices/robot.py,sha256=VaD2_ogt497myakfkCC1cGfBoz1I6QVdO8AXzFuGis4,4813
57
+ dodal/devices/robot.py,sha256=yzRq-77fVrlhxaIqeORJLGkDHzGgLrHsFYTxmkG-b0w,5343
56
58
  dodal/devices/s4_slit_gaps.py,sha256=j3kgF9WfGFaU9xdUuiAh-QqI5u_vhiAftaDVINt91SM,243
57
59
  dodal/devices/scatterguard.py,sha256=jx03in9QgaThWxD4t1S8_Llent2kWrn_hThJ9KkUWTk,330
58
60
  dodal/devices/scintillator.py,sha256=PlD6cnJ39PTB_e7QrRspPliLYE4kL_K7ziJURzuxgdA,365
@@ -60,12 +62,12 @@ dodal/devices/slits.py,sha256=uOyVmbgeygiP6e5Z9t5zMPXLuVEWFfYg9GB3ZU76Tug,600
60
62
  dodal/devices/smargon.py,sha256=hX-tCftKumxk67eS5-_gQRmYOrjSyQ4s3mMJsTRuvCk,4706
61
63
  dodal/devices/status.py,sha256=hVrJS1yooQo6PRumRACoIEh-SKBUKxvBlQl-MtLFUMQ,327
62
64
  dodal/devices/synchrotron.py,sha256=QtTufJA_fCaBawHougSc7nxwu240oX46_y0P-4qIW8o,1960
63
- dodal/devices/tetramm.py,sha256=ofWhLYFZHCRopDK_WRs1eo-B1ra4bUhwq1MLaVKl4ys,8572
65
+ dodal/devices/tetramm.py,sha256=EgtaExJBZWZC6lWgUEg0RcWQYmSKwRm20KjTZyhCjBk,8439
64
66
  dodal/devices/thawer.py,sha256=Gq-3f__KJUM6_Ds9OVxpZ5jC447HywJxQGXen6L33Lk,1616
65
67
  dodal/devices/turbo_slit.py,sha256=B6SPXqviMnG-U4PnUF1BdTO0LBKmTuwAUKRbxMiNJXo,1125
66
- dodal/devices/undulator.py,sha256=Uf7DpRjhtqkRcNWTqgtrRjoj6tLLgHEPgkxccWU6LE8,2073
67
- dodal/devices/undulator_dcm.py,sha256=qUMGKnRluO2jsfz6TuXx6ddN59MlLg1lBqloeBgYZIg,5134
68
- dodal/devices/webcam.py,sha256=znZHHmQjM0T0XSAYXJraCGlwPPGbt3PF6rWjTSbAikI,1394
68
+ dodal/devices/undulator.py,sha256=udwAodxYM9XgtsQGH2PDBA6ehtel5dAFkjsK13nKp6Q,5160
69
+ dodal/devices/undulator_dcm.py,sha256=5hn3UZeu4CYXmfUVSdIxjrcIpStgeA1S744p0iIFp4I,2725
70
+ dodal/devices/webcam.py,sha256=EqdzUBov5wMCULzzkfnCfD-5TQMZFQLp-2nlDHezmPs,2332
69
71
  dodal/devices/xbpm_feedback.py,sha256=-1wbnahJ_oSljQR0Sjiwn3mytVP-VwsAy0a_YPjPM0Y,1168
70
72
  dodal/devices/zebra.py,sha256=iTHkKv8EP-gkr0Cl2gR9yxt2qTHT2Q4etS67Rshf83k,9327
71
73
  dodal/devices/zebra_controlled_shutter.py,sha256=w2ISASJ_sb3dbQGi63Yuj3ymTkjX73aSl_ZTYs8TyaI,1860
@@ -73,7 +75,7 @@ dodal/devices/areadetector/__init__.py,sha256=8IwLxuZMW0MOJpJp_ZDdlaE20hrtsH_PXW
73
75
  dodal/devices/areadetector/adaravis.py,sha256=Cqw_Mzrp_zODFxQ2LZBJzHp_DsZ6_dAITkZz8gYz_0w,3797
74
76
  dodal/devices/areadetector/adsim.py,sha256=cIc9PRbKnftBk7Ut8d8CU_TVrin8EwcKHObP2n9VxWM,1876
75
77
  dodal/devices/areadetector/adutils.py,sha256=4axFR3wtn-K-sjMVJyfTcu-8g35odf2cY8mTKv1gS-o,3093
76
- dodal/devices/areadetector/plugins/MJPG.py,sha256=MqxDbrgpTzM0ezjcEWuLlK80i4M_KLNfdknHCx7k_LM,4100
78
+ dodal/devices/areadetector/plugins/MJPG.py,sha256=XztHFB1e7qHeZORYxvPgHfDMfkpXGKvfQYmej_hGVVc,4934
77
79
  dodal/devices/detector/__init__.py,sha256=-RdACL3tzc3lLArWOoGNje48UUlv2fElOmGOz9yOuO0,317
78
80
  dodal/devices/detector/det_dim_constants.py,sha256=LNrVMd0DbFEcnyNFmXosCP-VYaZ71Ajuv6inwo4Mg3U,2299
79
81
  dodal/devices/detector/det_dist_to_beam_converter.py,sha256=7keoqZYfvgayePVx97lHYpcFRTJnQOfAk_PYP4EZTZQ,1951
@@ -93,12 +95,12 @@ dodal/devices/i24/dcm.py,sha256=nP2qymTy5TrOu078XOY7h1TEwVfcgli5lTyxmwsG4O8,1990
93
95
  dodal/devices/i24/dual_backlight.py,sha256=Th-RKr28aFxE8LCT_mdN9KkRIVw0BHLGKkI0ienfRZU,2049
94
96
  dodal/devices/i24/i24_detector_motion.py,sha256=_HgdsZqFYY0tKqUgMzViHaPEUFXL3WlXXioGvDehRUw,364
95
97
  dodal/devices/i24/i24_vgonio.py,sha256=Igqs7687z6lyhGVeJEDtDmPachYxU48MUH2BF0RpK9Q,461
96
- dodal/devices/i24/pmac.py,sha256=suWoOIQKhCeQvgBJ8_htRAG6k0REN32viElwvs2nkEg,5224
98
+ dodal/devices/i24/pmac.py,sha256=qug40tz00vjvmQox3W6GrEcorriEeGkNyP5m4u5CVHo,7201
97
99
  dodal/devices/oav/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
100
  dodal/devices/oav/grid_overlay.py,sha256=kYs4sCvmo7yG75HQtptuI8jPzM7dR4fSqnOGL0D5j6g,5338
99
101
  dodal/devices/oav/microns_for_zoom_levels.json,sha256=kJTkbu2v6_Ccc_cDy7FRTX-gRhXxfYskjVqwBCZIqCQ,1209
100
102
  dodal/devices/oav/oav_calculations.py,sha256=wt71vFcyQrr98FvX8oyUM2n5vmKi3K7PyOTuWp0gq5w,1665
101
- dodal/devices/oav/oav_detector.py,sha256=NpIs6gcMrwe39M1y42M2ZtUhjrbl2LuMmNuUjjc13vg,3785
103
+ dodal/devices/oav/oav_detector.py,sha256=ZlVzFo01hYi2qITMP6k6TbTE9-7c8veMDoDcTiyU6kc,3178
102
104
  dodal/devices/oav/oav_errors.py,sha256=cc4mGnaTiAc5WIlOt_BIYOc7CRSkrCdnBaavfAJ0pXY,754
103
105
  dodal/devices/oav/oav_parameters.py,sha256=rI0kRl8B-N2mw91yYf1lEQVn0hkBQCPU7jvljr5ZNpk,8235
104
106
  dodal/devices/oav/oav_to_redis_forwarder.py,sha256=3I8Vk1Qx04aVftXb7VVkHUVHweGGUyuLFdmaasmb_Qk,4606
@@ -120,15 +122,15 @@ dodal/devices/util/test_utils.py,sha256=VrSFFGLNKOcCAsWFMZOxwhng3wGR5kV8NqqnKfj8
120
122
  dodal/devices/xspress3/xspress3.py,sha256=JTx3ppAc8GwV9K-Gfqo81iGYH_L-ONyFWiPRs9XUs-w,4661
121
123
  dodal/devices/xspress3/xspress3_channel.py,sha256=yJRwseLmtkW2Vv6GB8sLdOFuBn3e4c9Q8fgPacMgl5w,1638
122
124
  dodal/devices/zocalo/__init__.py,sha256=oPhjFB39yf2NWkGD-MMcPFnnOVZ_RtdyBt2OLYn-Xa4,505
123
- dodal/devices/zocalo/zocalo_interaction.py,sha256=cc-OwjNsh9oMpMghceVWKW9gym_TFmP-mOYBd3H1H7Q,3379
124
- dodal/devices/zocalo/zocalo_results.py,sha256=L4bUc8xkYCmn5KCx_vcMKFBiBO5F9nhYEffv8fGUS48,9891
125
+ dodal/devices/zocalo/zocalo_interaction.py,sha256=y8YKMaVwfsRPBofHGGLYmYsd4QwMvm7JIPEo6wrN_Xo,3493
126
+ dodal/devices/zocalo/zocalo_results.py,sha256=MStx8iK--ITff-rT3AQu_RHnqKqNGLJDVyV3ewBwaKE,14316
125
127
  dodal/parameters/experiment_parameter_base.py,sha256=O7JamfuJ5cYHkPf9tsHJPqn-OMHTAGouigvM1cDFehE,313
126
128
  dodal/plans/check_topup.py,sha256=3gyLHfHNQBCgEWuAg4QE-ONx7y2Do1vVv5HP8ss0Z1I,5371
127
129
  dodal/plans/data_session_metadata.py,sha256=urexZ3mA0K6VWxVW3MlrcsB1Tyi09tFvpKBlaVil7TQ,1567
128
130
  dodal/plans/motor_util_plans.py,sha256=JT1K4DBB66MrzNqimxFgiL6mRsj11fF7xZXOz0udEeo,4522
129
- dls_dodal-1.31.1.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
130
- dls_dodal-1.31.1.dist-info/METADATA,sha256=DcnbFBg6UX0o2covzHK0zCgw05wLGCXlzWN08tB6Cvg,16547
131
- dls_dodal-1.31.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
132
- dls_dodal-1.31.1.dist-info/entry_points.txt,sha256=bycw_EKUzup_rxfCetOwcauXV4kLln_OPpPT8jEnr-I,94
133
- dls_dodal-1.31.1.dist-info/top_level.txt,sha256=xIozdmZk_wmMV4wugpq9-6eZs0vgADNUKz3j2UAwlhc,6
134
- dls_dodal-1.31.1.dist-info/RECORD,,
131
+ dls_dodal-1.33.0.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
132
+ dls_dodal-1.33.0.dist-info/METADATA,sha256=wwy8R9Z3KMfUP7WOcWSZVk7EdoYqRSPXREOqroAGALo,16574
133
+ dls_dodal-1.33.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
134
+ dls_dodal-1.33.0.dist-info/entry_points.txt,sha256=bycw_EKUzup_rxfCetOwcauXV4kLln_OPpPT8jEnr-I,94
135
+ dls_dodal-1.33.0.dist-info/top_level.txt,sha256=xIozdmZk_wmMV4wugpq9-6eZs0vgADNUKz3j2UAwlhc,6
136
+ dls_dodal-1.33.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (74.1.2)
2
+ Generator: setuptools (75.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.31.1'
16
- __version_tuple__ = version_tuple = (1, 31, 1)
15
+ __version__ = version = '1.33.0'
16
+ __version_tuple__ = version_tuple = (1, 33, 0)
@@ -0,0 +1,77 @@
1
+ from pathlib import Path
2
+
3
+ from ophyd_async.epics.adaravis import AravisDetector
4
+ from ophyd_async.fastcs.panda import HDFPanda
5
+
6
+ from dodal.common.beamlines.beamline_utils import (
7
+ device_instantiation,
8
+ get_path_provider,
9
+ set_path_provider,
10
+ )
11
+ from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
12
+ from dodal.common.visit import LocalDirectoryServiceClient, StaticVisitPathProvider
13
+ from dodal.devices.synchrotron import Synchrotron
14
+ from dodal.log import set_beamline as set_log_beamline
15
+
16
+ BL = "c01"
17
+ set_log_beamline(BL)
18
+ set_utils_beamline(BL)
19
+
20
+ set_path_provider(
21
+ StaticVisitPathProvider(
22
+ BL,
23
+ Path("/dls/b01-1/data/"),
24
+ client=LocalDirectoryServiceClient(),
25
+ )
26
+ )
27
+
28
+ """
29
+ NOTE: Due to ArgoCD and the k8s cluster configuration those PVs are not available remotely.
30
+ You need to be on the beamline-local network to access them.
31
+ The simplest way to do this is to `ssh b01-1-ws001` and run `dodal connect b01_1` from there.
32
+ remember about the underscore in the beamline name.
33
+
34
+ See the IOC status here:
35
+ https://argocd.diamond.ac.uk/applications?showFavorites=false&proj=&sync=&autoSync=&health=&namespace=&cluster=&labels=
36
+ """
37
+
38
+
39
+ def panda(
40
+ wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False
41
+ ) -> HDFPanda:
42
+ return device_instantiation(
43
+ device_factory=HDFPanda,
44
+ name="panda",
45
+ prefix="-EA-PANDA-01:",
46
+ wait=wait_for_connection,
47
+ fake=fake_with_ophyd_sim,
48
+ path_provider=get_path_provider(),
49
+ )
50
+
51
+
52
+ def synchrotron(
53
+ wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False
54
+ ) -> Synchrotron:
55
+ return device_instantiation(
56
+ Synchrotron,
57
+ "synchrotron",
58
+ "",
59
+ wait_for_connection,
60
+ fake_with_ophyd_sim,
61
+ bl_prefix=False,
62
+ )
63
+
64
+
65
+ def manta(
66
+ wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False
67
+ ) -> AravisDetector:
68
+ return device_instantiation(
69
+ AravisDetector,
70
+ "manta",
71
+ "-DI-DCAM-02:",
72
+ wait_for_connection,
73
+ fake_with_ophyd_sim,
74
+ path_provider=get_path_provider(),
75
+ drv_suffix="CAM:",
76
+ hdf_suffix="HDF5:",
77
+ )
dodal/beamlines/i03.py CHANGED
@@ -316,6 +316,7 @@ def undulator(
316
316
  wait_for_connection,
317
317
  fake_with_ophyd_sim,
318
318
  bl_prefix=False,
319
+ id_gap_lookup_table_path="/dls_sw/i03/software/daq_configuration/lookup/BeamLine_Undulator_toGap.txt",
319
320
  )
320
321
 
321
322
 
@@ -334,7 +335,6 @@ def undulator_dcm(
334
335
  undulator=undulator(wait_for_connection, fake_with_ophyd_sim),
335
336
  dcm=dcm(wait_for_connection, fake_with_ophyd_sim),
336
337
  daq_configuration_path=DAQ_CONFIGURATION_PATH,
337
- id_gap_lookup_table_path="/dls_sw/i03/software/daq_configuration/lookup/BeamLine_Undulator_toGap.txt",
338
338
  )
339
339
 
340
340
 
dodal/beamlines/i04.py CHANGED
@@ -308,6 +308,7 @@ def undulator(
308
308
  wait_for_connection,
309
309
  fake_with_ophyd_sim,
310
310
  bl_prefix=False,
311
+ id_gap_lookup_table_path="/dls_sw/i04/software/gda/config/lookupTables/BeamLine_Undulator_toGap.txt",
311
312
  )
312
313
 
313
314
 
dodal/beamlines/i22.py CHANGED
@@ -199,6 +199,7 @@ def undulator(
199
199
  bl_prefix=False,
200
200
  poles=80,
201
201
  length=2.0,
202
+ id_gap_lookup_table_path="/dls_sw/i22/software/daq_configuration/lookup/BeamLine_Undulator_toGap.txt",
202
203
  )
203
204
 
204
205
 
@@ -0,0 +1,53 @@
1
+ from collections.abc import Callable, Coroutine
2
+ from typing import Any, TypeVar
3
+
4
+ from bluesky.protocols import Reading
5
+ from ophyd_async.core import SignalR, SoftSignalBackend
6
+ from ophyd_async.core._soft_signal_backend import SignalMetadata
7
+
8
+ T = TypeVar("T")
9
+
10
+
11
+ class HarwareBackedSoftSignalBackend(SoftSignalBackend[T]):
12
+ def __init__(
13
+ self,
14
+ get_from_hardware_func: Callable[[], Coroutine[Any, Any, T]],
15
+ *args,
16
+ **kwargs,
17
+ ) -> None:
18
+ self.get_from_hardware_func = get_from_hardware_func
19
+ super().__init__(*args, **kwargs)
20
+
21
+ async def _update_value(self):
22
+ new_value = await self.get_from_hardware_func()
23
+ await self.put(new_value)
24
+
25
+ async def get_reading(self) -> Reading:
26
+ await self._update_value()
27
+ return await super().get_reading()
28
+
29
+ async def get_value(self) -> T:
30
+ await self._update_value()
31
+ return await super().get_value()
32
+
33
+
34
+ def create_hardware_backed_soft_signal(
35
+ datatype: type[T],
36
+ get_from_hardware_func: Callable[[], Coroutine[Any, Any, T]],
37
+ units: str | None = None,
38
+ precision: int | None = None,
39
+ ):
40
+ """Creates a soft signal that, when read will call the function passed into
41
+ `get_from_hardware_func` and return this.
42
+
43
+ This will allow you to make soft signals derived from arbitrary hardware signals.
44
+ However, calling subscribe on this signal does not give you a sensible value and
45
+ the signal is currently read only. See https://github.com/bluesky/ophyd-async/issues/525
46
+ for a more full solution.
47
+ """
48
+ metadata = SignalMetadata(units=units, precision=precision)
49
+ return SignalR(
50
+ backend=HarwareBackedSoftSignalBackend(
51
+ get_from_hardware_func, datatype, metadata=metadata
52
+ )
53
+ )
@@ -8,11 +8,11 @@ from ophyd_async.core import (
8
8
  AsyncStatus,
9
9
  HintedSignal,
10
10
  StandardReadable,
11
- soft_signal_rw,
12
11
  )
13
12
  from pydantic import BaseModel, Field
14
13
 
15
14
  from dodal.common.beamlines.beamline_parameters import GDABeamlineParameters
15
+ from dodal.common.signal_utils import create_hardware_backed_soft_signal
16
16
  from dodal.devices.aperture import Aperture
17
17
  from dodal.devices.scatterguard import Scatterguard
18
18
 
@@ -105,7 +105,9 @@ class ApertureScatterguard(StandardReadable, Movable):
105
105
  ) -> None:
106
106
  self.aperture = Aperture(prefix + "-MO-MAPT-01:")
107
107
  self.scatterguard = Scatterguard(prefix + "-MO-SCAT-01:")
108
- self.radius = soft_signal_rw(float, units="µm")
108
+ self.radius = create_hardware_backed_soft_signal(
109
+ float, self._get_current_radius, units="µm"
110
+ )
109
111
  self._loaded_positions = loaded_positions
110
112
  self._tolerances = tolerances
111
113
  self.add_readables(
@@ -119,7 +121,9 @@ class ApertureScatterguard(StandardReadable, Movable):
119
121
  ],
120
122
  )
121
123
  with self.add_children_as_readables(HintedSignal):
122
- self.selected_aperture = soft_signal_rw(ApertureValue)
124
+ self.selected_aperture = create_hardware_backed_soft_signal(
125
+ ApertureValue, self._get_current_aperture_position
126
+ )
123
127
 
124
128
  super().__init__(name)
125
129
 
@@ -136,9 +140,6 @@ class ApertureScatterguard(StandardReadable, Movable):
136
140
  @AsyncStatus.wrap
137
141
  async def _set_raw_unsafe(self, position: AperturePosition):
138
142
  """Accept the risks and move in an unsafe way. Collisions possible."""
139
- if position.radius is not None:
140
- await self.radius.set(position.radius)
141
-
142
143
  aperture_x, aperture_y, aperture_z, scatterguard_x, scatterguard_y = (
143
144
  position.values
144
145
  )
@@ -150,13 +151,8 @@ class ApertureScatterguard(StandardReadable, Movable):
150
151
  self.scatterguard.x.set(scatterguard_x),
151
152
  self.scatterguard.y.set(scatterguard_y),
152
153
  )
153
- try:
154
- value = await self.get_current_aperture_position()
155
- self.selected_aperture.set(value)
156
- except InvalidApertureMove:
157
- self.selected_aperture.set(None) # type: ignore
158
154
 
159
- async def get_current_aperture_position(self) -> ApertureValue:
155
+ async def _get_current_aperture_position(self) -> ApertureValue:
160
156
  """
161
157
  Returns the current aperture position using readback values
162
158
  for SMALL, MEDIUM, LARGE. ROBOT_LOAD position defined when
@@ -176,6 +172,10 @@ class ApertureScatterguard(StandardReadable, Movable):
176
172
 
177
173
  raise InvalidApertureMove("Current aperture/scatterguard state unrecognised")
178
174
 
175
+ async def _get_current_radius(self) -> float | None:
176
+ current_value = await self._get_current_aperture_position()
177
+ return self._loaded_positions[current_value].radius
178
+
179
179
  async def _safe_move_within_datacollection_range(
180
180
  self, position: AperturePosition, value: ApertureValue
181
181
  ):
@@ -203,8 +203,6 @@ class ApertureScatterguard(StandardReadable, Movable):
203
203
  )
204
204
 
205
205
  current_ap_y = await self.aperture.y.user_readback.get_value()
206
- if position.radius is not None:
207
- await self.radius.set(position.radius)
208
206
 
209
207
  aperture_x, aperture_y, aperture_z, scatterguard_x, scatterguard_y = (
210
208
  position.values
@@ -220,15 +218,14 @@ class ApertureScatterguard(StandardReadable, Movable):
220
218
  self.aperture.y.set(aperture_y),
221
219
  self.aperture.z.set(aperture_z),
222
220
  )
223
- return
224
- await asyncio.gather(
225
- self.aperture.x.set(aperture_x),
226
- self.aperture.y.set(aperture_y),
227
- self.aperture.z.set(aperture_z),
228
- )
221
+ else:
222
+ await asyncio.gather(
223
+ self.aperture.x.set(aperture_x),
224
+ self.aperture.y.set(aperture_y),
225
+ self.aperture.z.set(aperture_z),
226
+ )
229
227
 
230
- await asyncio.gather(
231
- self.scatterguard.x.set(scatterguard_x),
232
- self.scatterguard.y.set(scatterguard_y),
233
- )
234
- await self.selected_aperture.set(value)
228
+ await asyncio.gather(
229
+ self.scatterguard.x.set(scatterguard_x),
230
+ self.scatterguard.y.set(scatterguard_y),
231
+ )
@@ -87,11 +87,12 @@ class MJPG(Device, ABC):
87
87
 
88
88
 
89
89
  class SnapshotWithBeamCentre(MJPG):
90
- """A child of MJPG which, when triggered, draws a crosshair at the beam centre in the
91
- image and saves the image to disk."""
90
+ """A child of MJPG which, when triggered, draws an outlined crosshair at the beam
91
+ centre in the image and saves the image to disk."""
92
92
 
93
93
  CROSSHAIR_LENGTH_PX = 20
94
- CROSSHAIR_COLOUR = "Blue"
94
+ CROSSHAIR_OUTLINE_COLOUR = "Black"
95
+ CROSSHAIR_FILL_COLOUR = "White"
95
96
 
96
97
  def post_processing(self, image: Image.Image):
97
98
  assert (
@@ -100,15 +101,38 @@ class SnapshotWithBeamCentre(MJPG):
100
101
  beam_x = self.oav_params.beam_centre_i
101
102
  beam_y = self.oav_params.beam_centre_j
102
103
 
104
+ SnapshotWithBeamCentre.draw_crosshair(image, beam_x, beam_y)
105
+
106
+ self._save_image(image)
107
+
108
+ @classmethod
109
+ def draw_crosshair(cls, image: Image.Image, beam_x: int, beam_y: int):
103
110
  draw = ImageDraw.Draw(image)
104
- HALF_LEN = self.CROSSHAIR_LENGTH_PX / 2
111
+ OUTLINE_WIDTH = 1
112
+ HALF_LEN = cls.CROSSHAIR_LENGTH_PX / 2
113
+ draw.rectangle(
114
+ [
115
+ beam_x - OUTLINE_WIDTH,
116
+ beam_y - HALF_LEN - OUTLINE_WIDTH,
117
+ beam_x + OUTLINE_WIDTH,
118
+ beam_y + HALF_LEN + OUTLINE_WIDTH,
119
+ ],
120
+ fill=cls.CROSSHAIR_OUTLINE_COLOUR,
121
+ )
122
+ draw.rectangle(
123
+ [
124
+ beam_x - HALF_LEN - OUTLINE_WIDTH,
125
+ beam_y - OUTLINE_WIDTH,
126
+ beam_x + HALF_LEN + OUTLINE_WIDTH,
127
+ beam_y + OUTLINE_WIDTH,
128
+ ],
129
+ fill=cls.CROSSHAIR_OUTLINE_COLOUR,
130
+ )
105
131
  draw.line(
106
132
  ((beam_x, beam_y - HALF_LEN), (beam_x, beam_y + HALF_LEN)),
107
- fill=self.CROSSHAIR_COLOUR,
133
+ fill=cls.CROSSHAIR_FILL_COLOUR,
108
134
  )
109
135
  draw.line(
110
136
  ((beam_x - HALF_LEN, beam_y), (beam_x + HALF_LEN, beam_y)),
111
- fill=self.CROSSHAIR_COLOUR,
137
+ fill=cls.CROSSHAIR_FILL_COLOUR,
112
138
  )
113
-
114
- self._save_image(image)
@@ -3,6 +3,7 @@ from typing import Generic, TypeVar
3
3
 
4
4
  import numpy as np
5
5
  from bluesky.plan_stubs import mv
6
+ from bluesky.protocols import Flyable
6
7
  from numpy import ndarray
7
8
  from ophyd_async.core import (
8
9
  AsyncStatus,
@@ -193,7 +194,7 @@ class ExpectedImages(SignalR[int]):
193
194
  return first_grid + second_grid
194
195
 
195
196
 
196
- class FastGridScanCommon(StandardReadable, ABC, Generic[ParamType]):
197
+ class FastGridScanCommon(StandardReadable, Flyable, ABC, Generic[ParamType]):
197
198
  """Device for a general fast grid scan
198
199
 
199
200
  When the motion program is started, the goniometer will move in a snake-like grid trajectory,
@@ -76,7 +76,7 @@ class MirrorVoltageDevice(Device):
76
76
  LOGGER.debug(f"{setpoint_v.name} already at {value} - skipping set")
77
77
  return
78
78
 
79
- LOGGER.debug(f"setting {setpoint_v.name} to {value}")
79
+ LOGGER.debug(f"Setting {setpoint_v.name} to {value}")
80
80
 
81
81
  # Register an observer up front to ensure we don't miss events after we
82
82
  # perform the set
@@ -85,16 +85,14 @@ class MirrorVoltageDevice(Device):
85
85
  )
86
86
  # discard the current value (OK) so we can await a subsequent change
87
87
  await anext(demand_accepted_iterator)
88
- await setpoint_v.set(value)
88
+ set_status = setpoint_v.set(value, wait=False)
89
89
 
90
90
  # The set should always change to SLEW regardless of whether we are
91
91
  # already at the set point, then change back to OK/FAIL depending on
92
92
  # success
93
93
  accepted_value = await anext(demand_accepted_iterator)
94
94
  assert accepted_value == MirrorVoltageDemand.SLEW
95
- LOGGER.debug(
96
- f"Demand not accepted for {setpoint_v.name}, waiting for acceptance..."
97
- )
95
+ LOGGER.debug(f"Waiting for {setpoint_v.name} to set")
98
96
  while MirrorVoltageDemand.SLEW == (
99
97
  accepted_value := await anext(demand_accepted_iterator)
100
98
  ):
@@ -104,6 +102,7 @@ class MirrorVoltageDevice(Device):
104
102
  raise AssertionError(
105
103
  f"Voltage slew failed for {setpoint_v.name}, new state={accepted_value}"
106
104
  )
105
+ await set_status
107
106
 
108
107
 
109
108
  class VFMMirrorVoltages(StandardReadable):