dls-dodal 1.32.0__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.32.0
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
@@ -1,6 +1,6 @@
1
1
  dodal/__init__.py,sha256=v-rRiDOgZ3sQSMQKq0vgUQZvpeOkoHFXissAx6Ktg84,61
2
2
  dodal/__main__.py,sha256=kP2S2RPitnOWpNGokjZ1Yq-1umOtp5sNOZk2B3tBPLM,111
3
- dodal/_version.py,sha256=DJRUo3ZQOOrgoMbrpGNhypFaRgQ4TvlEoMxoldzMF6Y,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
@@ -9,6 +9,7 @@ dodal/beamline_specific_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
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/b01_1.py,sha256=nH1CzeGXc9kAZBxISsuQF33On9FuWkwFriGKfU8Qs5g,2176
12
13
  dodal/beamlines/i03.py,sha256=8Lra4u1kLjWUoboxuSx6Po92OymRaKaJjM9ERr9zeUI,17004
13
14
  dodal/beamlines/i04.py,sha256=pRVNIBaUn3oIgbxInCgBUwLqHtPirxf0fKfTfx4RcJ8,13877
14
15
  dodal/beamlines/i04_1.py,sha256=KDxSUQNhIs_NFiRaLY-Jiory0DeN7Y0ErvGuoTrwCDU,4731
@@ -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,7 +37,7 @@ 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=fOdwQl_qZLaUo1cI1-wz1t2OqncMoUm_uqeZNWyHn3M,8459
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
@@ -98,7 +100,7 @@ dodal/devices/oav/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
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
@@ -126,9 +128,9 @@ dodal/parameters/experiment_parameter_base.py,sha256=O7JamfuJ5cYHkPf9tsHJPqn-OMH
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.32.0.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
130
- dls_dodal-1.32.0.dist-info/METADATA,sha256=Y7XXnR4vFkIsqoZ6vXh9STdoUyc9cbudVRqzP30rHUM,16574
131
- dls_dodal-1.32.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
132
- dls_dodal-1.32.0.dist-info/entry_points.txt,sha256=bycw_EKUzup_rxfCetOwcauXV4kLln_OPpPT8jEnr-I,94
133
- dls_dodal-1.32.0.dist-info/top_level.txt,sha256=xIozdmZk_wmMV4wugpq9-6eZs0vgADNUKz3j2UAwlhc,6
134
- dls_dodal-1.32.0.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,,
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.32.0'
16
- __version_tuple__ = version_tuple = (1, 32, 0)
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
+ )
@@ -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
@@ -231,4 +229,3 @@ class ApertureScatterguard(StandardReadable, Movable):
231
229
  self.scatterguard.x.set(scatterguard_x),
232
230
  self.scatterguard.y.set(scatterguard_y),
233
231
  )
234
- await self.selected_aperture.set(value)
@@ -12,7 +12,6 @@ from ophyd import (
12
12
  OverlayPlugin,
13
13
  ProcessPlugin,
14
14
  ROIPlugin,
15
- Signal,
16
15
  StatusBase,
17
16
  )
18
17
 
@@ -35,8 +34,6 @@ class ZoomController(Device):
35
34
 
36
35
  # Level is the string description of the zoom level e.g. "1.0x"
37
36
  level = Component(EpicsSignal, "MP:SELECT", string=True)
38
- # Used by OAV to work out if we're changing the setpoint
39
- _level_sp = Component(Signal)
40
37
 
41
38
  zrst = Component(EpicsSignal, "MP:SELECT.ZRST")
42
39
  onst = Component(EpicsSignal, "MP:SELECT.ONST")
@@ -46,14 +43,6 @@ class ZoomController(Device):
46
43
  fvst = Component(EpicsSignal, "MP:SELECT.FVST")
47
44
  sxst = Component(EpicsSignal, "MP:SELECT.SXST")
48
45
 
49
- def set_flatfield_on_zoom_level_one(self, value):
50
- self.parent: OAV
51
- flat_applied = self.parent.proc.port_name.get()
52
- no_flat_applied = self.parent.cam.port_name.get()
53
- return self.parent.grid_snapshot.input_plugin.set(
54
- flat_applied if value == "1.0x" else no_flat_applied
55
- )
56
-
57
46
  @property
58
47
  def allowed_zoom_levels(self):
59
48
  return [
@@ -67,10 +56,7 @@ class ZoomController(Device):
67
56
  ]
68
57
 
69
58
  def set(self, level_to_set: str) -> StatusBase:
70
- return_status = self._level_sp.set(level_to_set)
71
- return_status &= self.level.set(level_to_set)
72
- return_status &= self.set_flatfield_on_zoom_level_one(level_to_set)
73
- return return_status
59
+ return self.level.set(level_to_set)
74
60
 
75
61
 
76
62
  class OAV(AreaDetector):