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.
- {dls_dodal-1.62.0.dist-info → dls_dodal-1.63.0.dist-info}/METADATA +1 -1
- {dls_dodal-1.62.0.dist-info → dls_dodal-1.63.0.dist-info}/RECORD +76 -71
- dls_dodal-1.63.0.dist-info/entry_points.txt +3 -0
- dodal/_version.py +2 -2
- dodal/beamlines/__init__.py +1 -0
- dodal/beamlines/adsim.py +5 -3
- dodal/beamlines/b21.py +3 -1
- dodal/beamlines/i02_2.py +32 -0
- dodal/beamlines/i03.py +9 -0
- dodal/beamlines/i09.py +10 -3
- dodal/beamlines/i09_1.py +9 -3
- dodal/beamlines/i10.py +7 -69
- dodal/beamlines/i10_1.py +35 -0
- dodal/beamlines/i10_optics.py +205 -0
- dodal/beamlines/i15_1.py +5 -5
- dodal/beamlines/i17.py +50 -1
- dodal/beamlines/i18.py +15 -9
- dodal/beamlines/i19_1.py +3 -3
- dodal/beamlines/i19_2.py +2 -2
- dodal/beamlines/i19_optics.py +4 -1
- dodal/beamlines/i24.py +3 -3
- dodal/cli.py +4 -4
- dodal/common/visit.py +4 -4
- dodal/devices/aperturescatterguard.py +6 -4
- dodal/devices/apple2_undulator.py +211 -114
- dodal/devices/attenuator/filter_selections.py +6 -6
- dodal/devices/common_dcm.py +62 -15
- dodal/devices/current_amplifiers/femto.py +4 -4
- dodal/devices/current_amplifiers/sr570.py +3 -3
- dodal/devices/fast_grid_scan.py +4 -4
- dodal/devices/fast_shutter.py +19 -7
- dodal/devices/i02_2/__init__.py +0 -0
- dodal/devices/i03/dcm.py +4 -2
- dodal/devices/i04/murko_results.py +35 -14
- dodal/devices/i09/__init__.py +1 -2
- dodal/devices/i10/__init__.py +29 -0
- dodal/devices/i10/diagnostics.py +37 -5
- dodal/devices/i10/i10_apple2.py +125 -229
- dodal/devices/i10/slits.py +38 -6
- dodal/devices/i15/dcm.py +6 -45
- dodal/devices/i17/__init__.py +0 -0
- dodal/devices/i17/i17_apple2.py +51 -0
- dodal/devices/i19/access_controlled/__init__.py +0 -0
- dodal/devices/i19/{shutter.py → access_controlled/shutter.py} +7 -4
- dodal/devices/i22/dcm.py +2 -2
- dodal/devices/i24/dcm.py +2 -2
- dodal/devices/oav/oav_detector.py +1 -1
- dodal/devices/oav/oav_parameters.py +4 -4
- dodal/devices/oav/oav_to_redis_forwarder.py +4 -4
- dodal/devices/oav/pin_image_recognition/__init__.py +3 -3
- dodal/devices/oav/pin_image_recognition/utils.py +1 -1
- dodal/devices/oav/snapshots/snapshot.py +1 -1
- dodal/devices/oav/snapshots/snapshot_image_processing.py +12 -12
- dodal/devices/oav/snapshots/snapshot_with_grid.py +1 -1
- dodal/devices/oav/utils.py +2 -2
- dodal/devices/pgm.py +3 -3
- dodal/devices/robot.py +5 -5
- dodal/devices/tetramm.py +9 -5
- dodal/devices/thawer.py +0 -4
- dodal/devices/v2f.py +2 -2
- dodal/devices/zebra/zebra_constants_mapping.py +2 -2
- dodal/devices/zocalo/__init__.py +4 -4
- dodal/devices/zocalo/zocalo_results.py +4 -4
- dodal/log.py +9 -9
- dodal/plan_stubs/motor_utils.py +4 -4
- dodal/plans/configure_arm_trigger_and_disarm_detector.py +2 -2
- dodal/plans/save_panda.py +7 -7
- dodal/plans/verify_undulator_gap.py +2 -2
- dls_dodal-1.62.0.dist-info/entry_points.txt +0 -3
- dodal/beamlines/i10-1.py +0 -25
- dodal/devices/i09/dcm.py +0 -26
- {dls_dodal-1.62.0.dist-info → dls_dodal-1.63.0.dist-info}/WHEEL +0 -0
- {dls_dodal-1.62.0.dist-info → dls_dodal-1.63.0.dist-info}/licenses/LICENSE +0 -0
- {dls_dodal-1.62.0.dist-info → dls_dodal-1.63.0.dist-info}/top_level.txt +0 -0
- /dodal/devices/areadetector/plugins/{CAM.py → cam.py} +0 -0
- /dodal/devices/areadetector/plugins/{MJPG.py → mjpg.py} +0 -0
- /dodal/devices/i18/{KBMirror.py → kb_mirror.py} +0 -0
- /dodal/devices/i19/{blueapi_device.py → access_controlled/blueapi_device.py} +0 -0
- /dodal/devices/i19/{hutch_access.py → access_controlled/hutch_access.py} +0 -0
dodal/devices/fast_grid_scan.py
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
473
|
+
GridScanInvalidError: if the grid scan parameters are not valid
|
|
474
474
|
"""
|
|
475
475
|
yield from prepare(scan, params, wait=True)
|
dodal/devices/fast_shutter.py
CHANGED
|
@@ -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
|
-
|
|
25
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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),
|
|
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
|
-
"""
|
|
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
|
-
"""
|
|
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
|
-
|
|
12
|
+
DoubleCrystalMonochromatorWithDSpacing,
|
|
13
13
|
PitchAndRollCrystal,
|
|
14
14
|
StationaryCrystal,
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
class DCM(
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
194
|
-
|
|
194
|
+
chosen_point_px[0],
|
|
195
|
+
chosen_point_px[1],
|
|
195
196
|
)
|
|
196
197
|
self._results.append(
|
|
197
198
|
MurkoResult(
|
|
198
|
-
|
|
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.
|
|
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
|
-
|
|
226
|
-
|
|
244
|
+
cutoff = min(cutoff, len(results_without_tiny_x))
|
|
245
|
+
|
|
246
|
+
best_x = results_without_tiny_x[:cutoff]
|
|
227
247
|
|
|
228
|
-
|
|
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(
|
|
231
|
-
return
|
|
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]:
|
dodal/devices/i09/__init__.py
CHANGED
dodal/devices/i10/__init__.py
CHANGED
|
@@ -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
|
+
]
|
dodal/devices/i10/diagnostics.py
CHANGED
|
@@ -28,7 +28,7 @@ class D3Position(StrictEnum):
|
|
|
28
28
|
GRID = "Grid"
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
class
|
|
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
|
|
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(
|
|
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
|
|