dls-dodal 1.36.3__py3-none-any.whl → 1.37.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.
Files changed (43) hide show
  1. {dls_dodal-1.36.3.dist-info → dls_dodal-1.37.0.dist-info}/METADATA +3 -3
  2. {dls_dodal-1.36.3.dist-info → dls_dodal-1.37.0.dist-info}/RECORD +43 -29
  3. {dls_dodal-1.36.3.dist-info → dls_dodal-1.37.0.dist-info}/WHEEL +1 -1
  4. dodal/_version.py +2 -2
  5. dodal/beamlines/i02_1.py +37 -0
  6. dodal/beamlines/i03.py +20 -3
  7. dodal/beamlines/i04.py +3 -3
  8. dodal/beamlines/i10.py +105 -0
  9. dodal/beamlines/i22.py +15 -0
  10. dodal/beamlines/i24.py +1 -1
  11. dodal/beamlines/p99.py +6 -2
  12. dodal/common/crystal_metadata.py +3 -3
  13. dodal/common/udc_directory_provider.py +3 -1
  14. dodal/devices/aperturescatterguard.py +3 -0
  15. dodal/devices/{attenuator.py → attenuator/attenuator.py} +29 -1
  16. dodal/devices/attenuator/filter.py +11 -0
  17. dodal/devices/attenuator/filter_selections.py +72 -0
  18. dodal/devices/bimorph_mirror.py +151 -0
  19. dodal/devices/current_amplifiers/__init__.py +34 -0
  20. dodal/devices/current_amplifiers/current_amplifier.py +103 -0
  21. dodal/devices/current_amplifiers/current_amplifier_detector.py +109 -0
  22. dodal/devices/current_amplifiers/femto.py +143 -0
  23. dodal/devices/current_amplifiers/sr570.py +214 -0
  24. dodal/devices/current_amplifiers/struck_scaler_counter.py +79 -0
  25. dodal/devices/detector/det_dim_constants.py +15 -0
  26. dodal/devices/eiger_odin.py +3 -3
  27. dodal/devices/fast_grid_scan.py +8 -3
  28. dodal/devices/i03/beamstop.py +85 -0
  29. dodal/devices/i04/transfocator.py +67 -53
  30. dodal/devices/i10/rasor/rasor_current_amp.py +72 -0
  31. dodal/devices/i10/rasor/rasor_motors.py +62 -0
  32. dodal/devices/i10/rasor/rasor_scaler_cards.py +12 -0
  33. dodal/devices/p99/sample_stage.py +2 -28
  34. dodal/devices/robot.py +2 -2
  35. dodal/devices/undulator_dcm.py +9 -11
  36. dodal/devices/zebra.py +6 -1
  37. dodal/devices/zocalo/zocalo_interaction.py +2 -1
  38. dodal/devices/zocalo/zocalo_results.py +22 -2
  39. dodal/log.py +2 -2
  40. dodal/plans/wrapped.py +3 -3
  41. {dls_dodal-1.36.3.dist-info → dls_dodal-1.37.0.dist-info}/LICENSE +0 -0
  42. {dls_dodal-1.36.3.dist-info → dls_dodal-1.37.0.dist-info}/entry_points.txt +0 -0
  43. {dls_dodal-1.36.3.dist-info → dls_dodal-1.37.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,62 @@
1
+ from ophyd_async.core import StandardReadable
2
+ from ophyd_async.epics.motor import Motor
3
+
4
+
5
+ class PinHole(StandardReadable):
6
+ "Two motors stage for rasor pinhole"
7
+
8
+ def __init__(
9
+ self,
10
+ prefix: str,
11
+ name: str = "",
12
+ ):
13
+ with self.add_children_as_readables():
14
+ self.x = Motor(prefix + "X")
15
+ self.y = Motor(prefix + "Y")
16
+ super().__init__(name=name)
17
+
18
+
19
+ class Diffractometer(StandardReadable):
20
+ def __init__(
21
+ self,
22
+ prefix: str,
23
+ name: str = "",
24
+ ):
25
+ with self.add_children_as_readables():
26
+ self.tth = Motor(prefix + "TWOTHETA")
27
+ self.th = Motor(prefix + "THETA")
28
+ self.chi = Motor(prefix + "CHI")
29
+ self.chamber_x = Motor(prefix + "X")
30
+ self.alpha = Motor(prefix + "ALPHA")
31
+ super().__init__(name=name)
32
+
33
+
34
+ class DetSlits(StandardReadable):
35
+ "Detector slits"
36
+
37
+ def __init__(
38
+ self,
39
+ prefix: str,
40
+ name: str = "",
41
+ ):
42
+ with self.add_children_as_readables():
43
+ self.upstream = Motor(prefix + "1:TRANS")
44
+ self.downstream = Motor(prefix + "2:TRANS")
45
+ super().__init__(name=name)
46
+
47
+
48
+ class PaStage(StandardReadable):
49
+ "Rasor detector stage"
50
+
51
+ def __init__(
52
+ self,
53
+ prefix: str,
54
+ name: str = "",
55
+ ):
56
+ with self.add_children_as_readables():
57
+ self.ttp = Motor(prefix + "TWOTHETA")
58
+ self.thp = Motor(prefix + "THETA")
59
+ self.py = Motor(prefix + "Y")
60
+ self.pz = Motor(prefix + "Z")
61
+ self.eta = Motor(prefix + "ETA")
62
+ super().__init__(name=name)
@@ -0,0 +1,12 @@
1
+ from ophyd_async.core import Device
2
+
3
+ from dodal.devices.current_amplifiers import StruckScaler
4
+
5
+
6
+ class RasorScalerCard1(Device):
7
+ def __init__(self, prefix, name: str = "") -> None:
8
+ self.mon = StruckScaler(prefix=prefix, suffix=".16")
9
+ self.det = StruckScaler(prefix=prefix, suffix=".17")
10
+ self.fluo = StruckScaler(prefix=prefix, suffix=".18")
11
+ self.drain = StruckScaler(prefix=prefix, suffix=".19")
12
+ super().__init__(name)
@@ -1,5 +1,5 @@
1
- from ophyd_async.core import StandardReadable, SubsetEnum
2
- from ophyd_async.epics.core import epics_signal_rw, epics_signal_rw_rbv
1
+ from ophyd_async.core import StandardReadable
2
+ from ophyd_async.epics.core import epics_signal_rw_rbv
3
3
 
4
4
 
5
5
  class SampleAngleStage(StandardReadable):
@@ -9,29 +9,3 @@ class SampleAngleStage(StandardReadable):
9
9
  self.roll = epics_signal_rw_rbv(float, prefix + "WRITEROLL", ":RBV")
10
10
  self.pitch = epics_signal_rw_rbv(float, prefix + "WRITEPITCH", ":RBV")
11
11
  super().__init__(name=name)
12
-
13
-
14
- class p99StageSelections(SubsetEnum):
15
- EMPTY = "Empty"
16
- MN5UM = "Mn 5um"
17
- FE = "Fe (empty)"
18
- CO5UM = "Co 5um"
19
- NI5UM = "Ni 5um"
20
- CU5UM = "Cu 5um"
21
- ZN5UM = "Zn 5um"
22
- ZR = "Zr (empty)"
23
- MO = "Mo (empty)"
24
- RH = "Rh (empty)"
25
- PD = "Pd (empty)"
26
- AG = "Ag (empty)"
27
- CD25UM = "Cd 25um"
28
- W = "W (empty)"
29
- PT = "Pt (empty)"
30
- USER = "User"
31
-
32
-
33
- class FilterMotor(StandardReadable):
34
- def __init__(self, prefix: str, name: str = ""):
35
- with self.add_children_as_readables():
36
- self.user_setpoint = epics_signal_rw(p99StageSelections, prefix)
37
- super().__init__(name=name)
dodal/devices/robot.py CHANGED
@@ -70,8 +70,8 @@ class BartRobot(StandardReadable, Movable):
70
70
  self.program_running = epics_signal_r(bool, prefix + "PROGRAM_RUNNING")
71
71
  self.program_name = epics_signal_r(str, prefix + "PROGRAM_NAME")
72
72
  self.error_str = epics_signal_r(str, prefix + "PRG_ERR_MSG")
73
- # Change error_code to int type when https://github.com/bluesky/ophyd-async/issues/280 released
74
- self.error_code = epics_signal_r(float, prefix + "PRG_ERR_CODE")
73
+ self.error_code = epics_signal_r(int, prefix + "PRG_ERR_CODE")
74
+ self.reset = epics_signal_x(prefix + "RESET.PROC")
75
75
  super().__init__(name=name)
76
76
 
77
77
  async def pin_mounted_or_no_pin_found(self):
@@ -1,7 +1,7 @@
1
1
  import asyncio
2
2
 
3
3
  from bluesky.protocols import Movable
4
- from ophyd_async.core import AsyncStatus, StandardReadable
4
+ from ophyd_async.core import AsyncStatus, Reference, StandardReadable
5
5
 
6
6
  from dodal.common.beamlines.beamline_parameters import get_beamline_parameters
7
7
 
@@ -33,12 +33,8 @@ class UndulatorDCM(StandardReadable, Movable):
33
33
  prefix: str = "",
34
34
  name: str = "",
35
35
  ):
36
- super().__init__(name)
37
-
38
- # Attributes are set after super call so they are not renamed to
39
- # <name>-undulator, etc.
40
- self.undulator = undulator
41
- self.dcm = dcm
36
+ self.undulator_ref = Reference(undulator)
37
+ self.dcm_ref = Reference(dcm)
42
38
 
43
39
  # These attributes are just used by hyperion for lookup purposes
44
40
  self.pitch_energy_table_path = (
@@ -53,13 +49,15 @@ class UndulatorDCM(StandardReadable, Movable):
53
49
  daq_configuration_path + "/domain/beamlineParameters"
54
50
  )["DCM_Perp_Offset_FIXED"]
55
51
 
52
+ super().__init__(name)
53
+
56
54
  @AsyncStatus.wrap
57
55
  async def set(self, value: float):
58
- await self.undulator.raise_if_not_enabled()
56
+ await self.undulator_ref().raise_if_not_enabled()
59
57
  await asyncio.gather(
60
- self.dcm.energy_in_kev.set(value, timeout=ENERGY_TIMEOUT_S),
61
- self.undulator.set(value),
58
+ self.dcm_ref().energy_in_kev.set(value, timeout=ENERGY_TIMEOUT_S),
59
+ self.undulator_ref().set(value),
62
60
  )
63
61
  # DCM Perp pitch
64
62
  LOGGER.info(f"Adjusting DCM offset to {self.dcm_fixed_offset_mm} mm")
65
- await self.dcm.offset_in_mm.set(self.dcm_fixed_offset_mm)
63
+ await self.dcm_ref().offset_in_mm.set(self.dcm_fixed_offset_mm)
dodal/devices/zebra.py CHANGED
@@ -81,6 +81,11 @@ class I24Axes:
81
81
 
82
82
 
83
83
  class RotationDirection(StrictEnum):
84
+ """
85
+ Defines for a swept angle whether the scan width (sweep) is to be added or subtracted from
86
+ the initial angle to obtain the final angle.
87
+ """
88
+
84
89
  POSITIVE = "Positive"
85
90
  NEGATIVE = "Negative"
86
91
 
@@ -281,7 +286,7 @@ class LogicGateConfiguration:
281
286
  for input, (source, invert) in enumerate(
282
287
  zip(self.sources, self.invert, strict=False)
283
288
  ):
284
- input_strings.append(f"INP{input+1}={'!' if invert else ''}{source}")
289
+ input_strings.append(f"INP{input + 1}={'!' if invert else ''}{source}")
285
290
 
286
291
  return ", ".join(input_strings)
287
292
 
@@ -55,7 +55,8 @@ class ZocaloTrigger:
55
55
  intended to be used in bluesky callback classes. To get results from zocalo back
56
56
  into a plan, use the ZocaloResults ophyd device.
57
57
 
58
- see https://github.com/DiamondLightSource/dodal/wiki/How-to-Interact-with-Zocalo"""
58
+ see https://diamondlightsource.github.io/dodal/main/how-to/zocalo.html for
59
+ more information about zocalo."""
59
60
 
60
61
  def __init__(self, environment: str = ZOCALO_ENV):
61
62
  self.zocalo_environment: str = environment
@@ -11,7 +11,7 @@ import workflows.recipe
11
11
  import workflows.transport
12
12
  from bluesky.protocols import Triggerable
13
13
  from bluesky.utils import Msg
14
- from deepdiff import DeepDiff
14
+ from deepdiff.diff import DeepDiff
15
15
  from ophyd_async.core import (
16
16
  Array1D,
17
17
  AsyncStatus,
@@ -53,6 +53,26 @@ ZOCALO_STAGE_GROUP = "clear zocalo queue"
53
53
 
54
54
 
55
55
  class XrcResult(TypedDict):
56
+ """
57
+ Information about a diffracting centre.
58
+
59
+ NOTE: the coordinate systems of centre_of_mass and max_voxel/bounding_box are not
60
+ the same; centre_of_mass coordinates are continuous whereas max_voxel and bounding_box
61
+ coordinates are discrete.
62
+ Attributes:
63
+ centre_of_mass: The position of the centre of mass of the crystal, adjusted so that
64
+ grid box centres lie on integer grid coordinates, such that a 1x1x1 crystal detected in
65
+ a single grid box at 0, 0, 0, has c.o.m. of 0, 0, 0, not 0.5, 0.5, 0.5
66
+ max_voxel: Position of the voxel with the maximum count, in integer coordinates
67
+ max_count: max count achieved in a single voxel for the crystal
68
+ n_voxels: Number of voxels (aka grid boxes) in the diffracting centre
69
+ total_count: Total of above-threshold spot counts in the labelled voxels
70
+ bounding_box: The rectangular prism that bounds the crystal, expressed
71
+ as the volume of whole boxes as a half-open range i.e such that
72
+ p1 = (x1, y1, z1) <= p < p2 = (x2, y2, z2) and
73
+ p2 - p1 gives the dimensions in whole voxels.
74
+ """
75
+
56
76
  centre_of_mass: list[float]
57
77
  max_voxel: list[int]
58
78
  max_count: int
@@ -133,7 +153,7 @@ class ZocaloResults(StandardReadable, Triggerable):
133
153
  self.use_cpu_and_gpu = use_cpu_and_gpu
134
154
 
135
155
  self.centre_of_mass, self._com_setter = soft_signal_r_and_setter(
136
- Array1D[np.uint64], name="centre_of_mass"
156
+ Array1D[np.float64], name="centre_of_mass"
137
157
  )
138
158
  self.bounding_box, self._bounding_box_setter = soft_signal_r_and_setter(
139
159
  Array1D[np.uint64], name="bounding_box"
dodal/log.py CHANGED
@@ -152,7 +152,7 @@ def set_up_graylog_handler(logger: Logger, host: str, port: int):
152
152
  def set_up_INFO_file_handler(logger, path: Path, filename: str):
153
153
  """Set up a file handler for the logger, at INFO level, which will keep 30 days
154
154
  of logs, rotating once per day. Creates the directory if necessary."""
155
- print(f"Logging to INFO file handler {path/filename}")
155
+ print(f"Logging to INFO file handler {path / filename}")
156
156
  path.mkdir(parents=True, exist_ok=True)
157
157
  file_handler = TimedRotatingFileHandler(
158
158
  filename=path / filename, when="MIDNIGHT", backupCount=INFO_LOG_DAYS
@@ -169,7 +169,7 @@ def set_up_DEBUG_memory_handler(
169
169
  log file when it sees a message of severity ERROR. Creates the directory if
170
170
  necessary"""
171
171
  debug_path = path / "debug"
172
- print(f"Logging to DEBUG handler {debug_path/filename}")
172
+ print(f"Logging to DEBUG handler {debug_path / filename}")
173
173
  debug_path.mkdir(parents=True, exist_ok=True)
174
174
  file_handler = TimedRotatingFileHandler(
175
175
  filename=debug_path / filename, when="H", backupCount=DEBUG_LOG_FILES_TO_KEEP
dodal/plans/wrapped.py CHANGED
@@ -49,9 +49,9 @@ def count(
49
49
  Wraps bluesky.plans.count(det, num, delay, md=metadata) exposing only serializable
50
50
  parameters and metadata."""
51
51
  if isinstance(delay, Sequence):
52
- assert (
53
- len(delay) == num - 1
54
- ), f"Number of delays given must be {num - 1}: was given {len(delay)}"
52
+ assert len(delay) == num - 1, (
53
+ f"Number of delays given must be {num - 1}: was given {len(delay)}"
54
+ )
55
55
  metadata = metadata or {}
56
56
  metadata["shape"] = (num,)
57
57
  yield from bp.count(tuple(detectors), num, delay=delay, md=metadata)