dls-dodal 1.62.0__py3-none-any.whl → 1.63.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 (79) hide show
  1. {dls_dodal-1.62.0.dist-info → dls_dodal-1.63.0.dist-info}/METADATA +1 -1
  2. {dls_dodal-1.62.0.dist-info → dls_dodal-1.63.0.dist-info}/RECORD +76 -71
  3. dls_dodal-1.63.0.dist-info/entry_points.txt +3 -0
  4. dodal/_version.py +2 -2
  5. dodal/beamlines/__init__.py +1 -0
  6. dodal/beamlines/adsim.py +5 -3
  7. dodal/beamlines/b21.py +3 -1
  8. dodal/beamlines/i02_2.py +32 -0
  9. dodal/beamlines/i03.py +9 -0
  10. dodal/beamlines/i09.py +10 -3
  11. dodal/beamlines/i09_1.py +9 -3
  12. dodal/beamlines/i10.py +7 -69
  13. dodal/beamlines/i10_1.py +35 -0
  14. dodal/beamlines/i10_optics.py +205 -0
  15. dodal/beamlines/i15_1.py +5 -5
  16. dodal/beamlines/i17.py +50 -1
  17. dodal/beamlines/i18.py +15 -9
  18. dodal/beamlines/i19_1.py +3 -3
  19. dodal/beamlines/i19_2.py +2 -2
  20. dodal/beamlines/i19_optics.py +4 -1
  21. dodal/beamlines/i24.py +3 -3
  22. dodal/cli.py +4 -4
  23. dodal/common/visit.py +4 -4
  24. dodal/devices/aperturescatterguard.py +6 -4
  25. dodal/devices/apple2_undulator.py +211 -114
  26. dodal/devices/attenuator/filter_selections.py +6 -6
  27. dodal/devices/common_dcm.py +62 -15
  28. dodal/devices/current_amplifiers/femto.py +4 -4
  29. dodal/devices/current_amplifiers/sr570.py +3 -3
  30. dodal/devices/fast_grid_scan.py +4 -4
  31. dodal/devices/fast_shutter.py +19 -7
  32. dodal/devices/i02_2/__init__.py +0 -0
  33. dodal/devices/i03/dcm.py +4 -2
  34. dodal/devices/i04/murko_results.py +35 -14
  35. dodal/devices/i09/__init__.py +1 -2
  36. dodal/devices/i10/__init__.py +29 -0
  37. dodal/devices/i10/diagnostics.py +37 -5
  38. dodal/devices/i10/i10_apple2.py +125 -229
  39. dodal/devices/i10/slits.py +38 -6
  40. dodal/devices/i15/dcm.py +6 -45
  41. dodal/devices/i17/__init__.py +0 -0
  42. dodal/devices/i17/i17_apple2.py +51 -0
  43. dodal/devices/i19/access_controlled/__init__.py +0 -0
  44. dodal/devices/i19/{shutter.py → access_controlled/shutter.py} +7 -4
  45. dodal/devices/i22/dcm.py +2 -2
  46. dodal/devices/i24/dcm.py +2 -2
  47. dodal/devices/oav/oav_detector.py +1 -1
  48. dodal/devices/oav/oav_parameters.py +4 -4
  49. dodal/devices/oav/oav_to_redis_forwarder.py +4 -4
  50. dodal/devices/oav/pin_image_recognition/__init__.py +3 -3
  51. dodal/devices/oav/pin_image_recognition/utils.py +1 -1
  52. dodal/devices/oav/snapshots/snapshot.py +1 -1
  53. dodal/devices/oav/snapshots/snapshot_image_processing.py +12 -12
  54. dodal/devices/oav/snapshots/snapshot_with_grid.py +1 -1
  55. dodal/devices/oav/utils.py +2 -2
  56. dodal/devices/pgm.py +3 -3
  57. dodal/devices/robot.py +5 -5
  58. dodal/devices/tetramm.py +9 -5
  59. dodal/devices/thawer.py +0 -4
  60. dodal/devices/v2f.py +2 -2
  61. dodal/devices/zebra/zebra_constants_mapping.py +2 -2
  62. dodal/devices/zocalo/__init__.py +4 -4
  63. dodal/devices/zocalo/zocalo_results.py +4 -4
  64. dodal/log.py +9 -9
  65. dodal/plan_stubs/motor_utils.py +4 -4
  66. dodal/plans/configure_arm_trigger_and_disarm_detector.py +2 -2
  67. dodal/plans/save_panda.py +7 -7
  68. dodal/plans/verify_undulator_gap.py +2 -2
  69. dls_dodal-1.62.0.dist-info/entry_points.txt +0 -3
  70. dodal/beamlines/i10-1.py +0 -25
  71. dodal/devices/i09/dcm.py +0 -26
  72. {dls_dodal-1.62.0.dist-info → dls_dodal-1.63.0.dist-info}/WHEEL +0 -0
  73. {dls_dodal-1.62.0.dist-info → dls_dodal-1.63.0.dist-info}/licenses/LICENSE +0 -0
  74. {dls_dodal-1.62.0.dist-info → dls_dodal-1.63.0.dist-info}/top_level.txt +0 -0
  75. /dodal/devices/areadetector/plugins/{CAM.py → cam.py} +0 -0
  76. /dodal/devices/areadetector/plugins/{MJPG.py → mjpg.py} +0 -0
  77. /dodal/devices/i18/{KBMirror.py → kb_mirror.py} +0 -0
  78. /dodal/devices/i19/{blueapi_device.py → access_controlled/blueapi_device.py} +0 -0
  79. /dodal/devices/i19/{hutch_access.py → access_controlled/hutch_access.py} +0 -0
@@ -31,7 +31,7 @@ from dodal.log import LOGGER
31
31
  from dodal.parameters.experiment_parameter_base import AbstractExperimentWithBeamParams
32
32
 
33
33
 
34
- class GridScanInvalidException(RuntimeError):
34
+ class GridScanInvalidError(RuntimeError):
35
35
  """Raised when the gridscan parameters are not valid."""
36
36
 
37
37
 
@@ -302,7 +302,7 @@ class FastGridScanCommon(
302
302
  value: the gridscan parameters
303
303
 
304
304
  Raises:
305
- GridScanInvalidException: if the gridscan parameters were not valid
305
+ GridScanInvalidError: if the gridscan parameters were not valid
306
306
  """
307
307
  set_statuses = []
308
308
 
@@ -326,7 +326,7 @@ class FastGridScanCommon(
326
326
  self.scan_invalid, 0.0, timeout=self.VALIDITY_CHECK_TIMEOUT
327
327
  )
328
328
  except TimeoutError as e:
329
- raise GridScanInvalidException(
329
+ raise GridScanInvalidError(
330
330
  f"Gridscan parameters not validated after {self.VALIDITY_CHECK_TIMEOUT}s"
331
331
  ) from e
332
332
 
@@ -470,6 +470,6 @@ def set_fast_grid_scan_params(scan: FastGridScanCommon[ParamType], params: Param
470
470
  params: The parameters to set
471
471
 
472
472
  Raises:
473
- GridScanInvalidException: if the grid scan parameters are not valid
473
+ GridScanInvalidError: if the grid scan parameters are not valid
474
474
  """
475
475
  yield from prepare(scan, params, wait=True)
@@ -21,27 +21,27 @@ class GenericFastShutter(StandardReadable, Movable[StrictEnumT]):
21
21
  await shutter.set(shutter.open_state)
22
22
  await shutter.set(shutter.close_state)
23
23
  OR
24
- RE(bps.mv(shutter, shutter.open_state))
25
- RE(bps.mv(shutter, shutter.close_state))
24
+ run_engine(bps.mv(shutter, shutter.open_state))
25
+ run_engine(bps.mv(shutter, shutter.close_state))
26
26
  """
27
27
 
28
28
  def __init__(
29
29
  self,
30
- prefix: str,
30
+ pv: str,
31
31
  open_state: StrictEnumT,
32
32
  close_state: StrictEnumT,
33
33
  name: str = "",
34
34
  ):
35
35
  """
36
36
  Arguments:
37
- prefix: The prefix for the shutter device.
37
+ pv: The pv to connect to the shutter device.
38
38
  open_state: The enum value that corresponds with opening the shutter.
39
39
  close_state: The enum value that corresponds with closing the shutter.
40
40
  """
41
41
  self.open_state = open_state
42
42
  self.close_state = close_state
43
43
  with self.add_children_as_readables():
44
- self.state = epics_signal_rw(type(self.open_state), prefix)
44
+ self.state = epics_signal_rw(type(self.open_state), pv)
45
45
  super().__init__(name)
46
46
 
47
47
  @AsyncStatus.wrap
@@ -49,9 +49,21 @@ class GenericFastShutter(StandardReadable, Movable[StrictEnumT]):
49
49
  await self.state.set(value)
50
50
 
51
51
  async def is_open(self) -> bool:
52
- """Checks to see if shutter is currently open"""
52
+ """
53
+ Checks to see if shutter is in open_state. Should not be used directly inside a
54
+ plan. A user should use the following instead in a plan:
55
+
56
+ from bluesky import plan_stubs as bps
57
+ is_open = yield from bps.rd(shutter.state) == shutter.open_state
58
+ """
53
59
  return await self.state.get_value() == self.open_state
54
60
 
55
61
  async def is_closed(self) -> bool:
56
- """Checks to see if shutter is currently closed"""
62
+ """
63
+ Checks to see if shutter is in close_state. Should not be used directly inside a
64
+ plan. A user should use the following instead in a plan:
65
+
66
+ from bluesky import plan_stubs as bps
67
+ is_closed = yield from bps.rd(shutter.state) == shutter.close_state
68
+ """
57
69
  return await self.state.get_value() == self.close_state
File without changes
dodal/devices/i03/dcm.py CHANGED
@@ -9,13 +9,15 @@ from dodal.common.crystal_metadata import (
9
9
  make_crystal_metadata_from_material,
10
10
  )
11
11
  from dodal.devices.common_dcm import (
12
- BaseDCM,
12
+ DoubleCrystalMonochromatorWithDSpacing,
13
13
  PitchAndRollCrystal,
14
14
  StationaryCrystal,
15
15
  )
16
16
 
17
17
 
18
- class DCM(BaseDCM[PitchAndRollCrystal, StationaryCrystal]):
18
+ class DCM(
19
+ DoubleCrystalMonochromatorWithDSpacing[PitchAndRollCrystal, StationaryCrystal]
20
+ ):
19
21
  """
20
22
  A double crystal monochromator (DCM), used to select the energy of the beam.
21
23
 
@@ -43,7 +43,7 @@ class Coord(Enum):
43
43
 
44
44
  @dataclass
45
45
  class MurkoResult:
46
- centre_px: tuple
46
+ chosen_point_px: tuple[int, int]
47
47
  x_dist_mm: float
48
48
  y_dist_mm: float
49
49
  omega: float
@@ -51,7 +51,7 @@ class MurkoResult:
51
51
  metadata: MurkoMetadata
52
52
 
53
53
 
54
- class NoResultsFound(ValueError):
54
+ class NoResultsFoundError(ValueError):
55
55
  pass
56
56
 
57
57
 
@@ -73,6 +73,7 @@ class MurkoResultsDevice(StandardReadable, Triggerable, Stageable):
73
73
 
74
74
  TIMEOUT_S = 2
75
75
  PERCENTAGE_TO_USE = 25
76
+ LEFTMOST_PIXEL_TO_USE = 10
76
77
  NUMBER_OF_WRONG_RESULTS_TO_LOG = 5
77
78
 
78
79
  def __init__(
@@ -129,7 +130,7 @@ class MurkoResultsDevice(StandardReadable, Triggerable, Stageable):
129
130
  await self.process_batch(message, sample_id)
130
131
 
131
132
  if not self._results:
132
- raise NoResultsFound("No results retrieved from Murko")
133
+ raise NoResultsFoundError("No results retrieved from Murko")
133
134
 
134
135
  for result in self._results:
135
136
  LOGGER.debug(result)
@@ -186,16 +187,16 @@ class MurkoResultsDevice(StandardReadable, Triggerable, Stageable):
186
187
  else:
187
188
  shape = result["original_shape"] # Dimensions of image in pixels
188
189
  # Murko returns coords as y, x
189
- centre_px = (coords[1] * shape[1], coords[0] * shape[0])
190
+ chosen_point_px = (coords[1] * shape[1], coords[0] * shape[0])
190
191
 
191
192
  beam_dist_px = calculate_beam_distance(
192
193
  (metadata["beam_centre_i"], metadata["beam_centre_j"]),
193
- centre_px[0],
194
- centre_px[1],
194
+ chosen_point_px[0],
195
+ chosen_point_px[1],
195
196
  )
196
197
  self._results.append(
197
198
  MurkoResult(
198
- centre_px=centre_px,
199
+ chosen_point_px=chosen_point_px,
199
200
  x_dist_mm=beam_dist_px[0] * metadata["microns_per_x_pixel"] / 1000,
200
201
  y_dist_mm=beam_dist_px[1] * metadata["microns_per_y_pixel"] / 1000,
201
202
  omega=omega,
@@ -209,10 +210,27 @@ class MurkoResultsDevice(StandardReadable, Triggerable, Stageable):
209
210
  """Whilst murko is not fully trained it often gives us poor results.
210
211
  When it is wrong it usually picks up the base of the pin, rather than the tip,
211
212
  meaning that by keeping only a percentage of the results with the smallest X we
212
- remove many of the outliers.
213
+ remove many of the outliers. Murko also occasionally picks a point in the bottom
214
+ left corner, which can be removed by filtering results with a small x pixel.
213
215
  """
216
+
214
217
  LOGGER.info(f"Number of results before filtering: {len(self._results)}")
215
- sorted_results = sorted(self._results, key=lambda item: item.centre_px[0])
218
+ sorted_results = sorted(self._results, key=lambda item: item.chosen_point_px[0])
219
+
220
+ results_without_tiny_x = [
221
+ result
222
+ for result in sorted_results
223
+ if result.chosen_point_px[0] >= self.LEFTMOST_PIXEL_TO_USE
224
+ ]
225
+ result_uuids_with_tiny_x = [
226
+ result.uuid
227
+ for result in sorted_results
228
+ if result not in results_without_tiny_x
229
+ ]
230
+
231
+ LOGGER.info(
232
+ f"Results with tiny x have been removed: {result_uuids_with_tiny_x}"
233
+ )
216
234
 
217
235
  worst_results = [
218
236
  r.uuid for r in sorted_results[-self.NUMBER_OF_WRONG_RESULTS_TO_LOG :]
@@ -221,14 +239,17 @@ class MurkoResultsDevice(StandardReadable, Triggerable, Stageable):
221
239
  LOGGER.info(
222
240
  f"Worst {self.NUMBER_OF_WRONG_RESULTS_TO_LOG} murko results were {worst_results}"
223
241
  )
242
+
224
243
  cutoff = max(1, int(len(sorted_results) * self.PERCENTAGE_TO_USE / 100))
225
- for i, result in enumerate(sorted_results):
226
- result.metadata["used_for_centring"] = i < cutoff
244
+ cutoff = min(cutoff, len(results_without_tiny_x))
245
+
246
+ best_x = results_without_tiny_x[:cutoff]
227
247
 
228
- smallest_x = sorted_results[:cutoff]
248
+ for result in sorted_results:
249
+ result.metadata["used_for_centring"] = result in best_x
229
250
 
230
- LOGGER.info(f"Number of results after filtering: {len(smallest_x)}")
231
- return smallest_x
251
+ LOGGER.info(f"Number of results after filtering: {len(best_x)}")
252
+ return best_x
232
253
 
233
254
 
234
255
  def get_yz_least_squares(vertical_dists: list, omegas: list) -> tuple[float, float]:
@@ -1,4 +1,3 @@
1
- from dodal.devices.i09.dcm import DCM
2
1
  from dodal.devices.i09.enums import Grating, LensMode, PassEnergy, PsuMode
3
2
 
4
- __all__ = ["DCM", "Grating", "LensMode", "PsuMode", "PassEnergy"]
3
+ __all__ = ["Grating", "LensMode", "PsuMode", "PassEnergy"]
@@ -0,0 +1,29 @@
1
+ from .diagnostics import (
2
+ I10Diagnostic,
3
+ I10Diagnostic5ADet,
4
+ I10JDiagnostic,
5
+ I10PneumaticStage,
6
+ I10SharedDiagnostic,
7
+ )
8
+ from .mirrors import PiezoMirror
9
+ from .slits import (
10
+ I10JSlits,
11
+ I10SharedSlits,
12
+ I10SharedSlitsDrainCurrent,
13
+ I10Slits,
14
+ I10SlitsDrainCurrent,
15
+ )
16
+
17
+ __all__ = [
18
+ "I10Diagnostic",
19
+ "I10Diagnostic5ADet",
20
+ "I10PneumaticStage",
21
+ "PiezoMirror",
22
+ "I10Slits",
23
+ "I10SlitsDrainCurrent",
24
+ "I10SharedDiagnostic",
25
+ "I10SharedSlits",
26
+ "I10JSlits",
27
+ "I10SharedSlitsDrainCurrent",
28
+ "I10JDiagnostic",
29
+ ]
@@ -28,7 +28,7 @@ class D3Position(StrictEnum):
28
28
  GRID = "Grid"
29
29
 
30
30
 
31
- class D5Position(StrictEnum):
31
+ class CellPosition(StrictEnum):
32
32
  CELL_IN = "Cell In"
33
33
  CELL_OUT = "Cell Out"
34
34
 
@@ -68,6 +68,21 @@ class InStateReadBackTable(StrictEnum):
68
68
  OUT_OF_BEAM = "Out of Beam"
69
69
 
70
70
 
71
+ class D2jPosition(StrictEnum):
72
+ OUT_OF_THE_BEAM = "Out of the beam"
73
+ DIODE = "Diode"
74
+ BLADE = "Blade"
75
+ LA = "La ref"
76
+ GD = "Gd ref"
77
+ YB = "Yb ref"
78
+
79
+
80
+ class D3jPosition(StrictEnum):
81
+ OUT_OF_THE_BEAM = "Out of the beam"
82
+ DIODE_IN = "Diode In"
83
+ DIAMOND_WINDOW = "Diamond window"
84
+
85
+
71
86
  class I10PneumaticStage(StandardReadable):
72
87
  """Pneumatic stage only has two real positions in or out.
73
88
  Use for fluorescent screen which can be insert into the x-ray beam.
@@ -138,9 +153,7 @@ class FullDiagnostic(Device):
138
153
  super().__init__(name)
139
154
 
140
155
 
141
- class I10Diagnostic(Device):
142
- """Collection of all the diagnostic stage on i10."""
143
-
156
+ class I10SharedDiagnostic(Device):
144
157
  def __init__(self, prefix, name: str = "") -> None:
145
158
  self.d1 = ScreenCam(prefix=prefix + "PHDGN-01:")
146
159
  self.d2 = ScreenCam(prefix=prefix + "PHDGN-02:")
@@ -149,8 +162,15 @@ class I10Diagnostic(Device):
149
162
  positioner_enum=D3Position,
150
163
  positioner_suffix="DET:X",
151
164
  )
165
+ super().__init__(name)
166
+
167
+
168
+ class I10Diagnostic(Device):
169
+ """Collection of all the diagnostic stage on i10."""
170
+
171
+ def __init__(self, prefix, name: str = "") -> None:
152
172
  self.d4 = ScreenCam(prefix=prefix + "PHDGN-04:")
153
- self.d5 = create_positioner(D5Position, f"{prefix}IONC-01:Y")
173
+ self.d5 = create_positioner(CellPosition, f"{prefix}IONC-01:Y")
154
174
  self.d5A = create_positioner(D5APosition, f"{prefix}PHDGN-06:DET:X")
155
175
  self.d6 = FullDiagnostic(f"{prefix}PHDGN-05:", D6Position, "DET:X")
156
176
  self.d7 = create_positioner(D7Position, f"{prefix}PHDGN-07:Y")
@@ -158,6 +178,18 @@ class I10Diagnostic(Device):
158
178
  super().__init__(name)
159
179
 
160
180
 
181
+ class I10JDiagnostic(Device):
182
+ """Collection of all the diagnostic stage on i10-1."""
183
+
184
+ def __init__(self, prefix, name: str = "") -> None:
185
+ self.dj1 = ScreenCam(prefix=prefix + "PHDGN-01:")
186
+ self.dj2 = create_positioner(CellPosition, f"{prefix}IONC-01:Y")
187
+ self.dj2A = create_positioner(D2jPosition, f"{prefix}PHDGN-03:DET:X")
188
+ self.dj3 = FullDiagnostic(f"{prefix}PHDGN-02:", D3jPosition, "DET:X")
189
+
190
+ super().__init__(name)
191
+
192
+
161
193
  class I10Diagnostic5ADet(Device):
162
194
  """Diagnostic 5a detection with drain current and photo diode"""
163
195