dls-dodal 1.36.1a0__py3-none-any.whl → 1.36.3__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.36.1a0.dist-info → dls_dodal-1.36.3.dist-info}/METADATA +2 -2
- {dls_dodal-1.36.1a0.dist-info → dls_dodal-1.36.3.dist-info}/RECORD +31 -33
- dodal/_version.py +2 -2
- dodal/beamlines/__init__.py +1 -0
- dodal/beamlines/adsim.py +75 -0
- dodal/beamlines/i10.py +74 -7
- dodal/beamlines/i24.py +17 -1
- dodal/devices/adsim.py +10 -10
- dodal/devices/aperture.py +0 -7
- dodal/devices/aperturescatterguard.py +79 -195
- dodal/devices/apple2_undulator.py +9 -9
- dodal/devices/attenuator.py +15 -5
- dodal/devices/focusing_mirror.py +12 -3
- dodal/devices/i10/i10_setting_data.py +3 -3
- dodal/devices/i10/mirrors.py +24 -0
- dodal/devices/i10/slits.py +37 -0
- dodal/devices/i24/dual_backlight.py +1 -0
- dodal/devices/i24/focus_mirrors.py +12 -12
- dodal/devices/linkam3.py +2 -2
- dodal/devices/oav/pin_image_recognition/__init__.py +2 -4
- dodal/devices/p99/sample_stage.py +15 -15
- dodal/devices/slits.py +29 -7
- dodal/devices/tetramm.py +16 -16
- dodal/devices/undulator_dcm.py +4 -0
- dodal/devices/util/test_utils.py +2 -2
- dodal/devices/xspress3/xspress3.py +3 -3
- dodal/devices/zebra.py +13 -13
- dodal/adsim.py +0 -17
- dodal/devices/areadetector/__init__.py +0 -10
- dodal/devices/areadetector/adaravis.py +0 -101
- dodal/devices/areadetector/adsim.py +0 -47
- dodal/devices/areadetector/adutils.py +0 -81
- {dls_dodal-1.36.1a0.dist-info → dls_dodal-1.36.3.dist-info}/LICENSE +0 -0
- {dls_dodal-1.36.1a0.dist-info → dls_dodal-1.36.3.dist-info}/WHEEL +0 -0
- {dls_dodal-1.36.1a0.dist-info → dls_dodal-1.36.3.dist-info}/entry_points.txt +0 -0
- {dls_dodal-1.36.1a0.dist-info → dls_dodal-1.36.3.dist-info}/top_level.txt +0 -0
dodal/devices/slits.py
CHANGED
|
@@ -2,16 +2,38 @@ from ophyd_async.core import StandardReadable
|
|
|
2
2
|
from ophyd_async.epics.motor import Motor
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
class
|
|
5
|
+
class MinimalSlits(StandardReadable):
|
|
6
|
+
"""Gap only X Y slits."""
|
|
7
|
+
|
|
8
|
+
def __init__(
|
|
9
|
+
self,
|
|
10
|
+
prefix: str,
|
|
11
|
+
x_gap: str = "X:SIZE",
|
|
12
|
+
y_gap: str = "Y:SIZE",
|
|
13
|
+
name: str = "",
|
|
14
|
+
) -> None:
|
|
15
|
+
with self.add_children_as_readables():
|
|
16
|
+
self.x_gap = Motor(prefix + x_gap)
|
|
17
|
+
self.y_gap = Motor(prefix + y_gap)
|
|
18
|
+
super().__init__(name=name)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Slits(MinimalSlits):
|
|
6
22
|
"""
|
|
7
23
|
Representation of a 4-blade set of slits. Allows control/readout of the gap
|
|
8
24
|
between each pair of blades.
|
|
9
25
|
"""
|
|
10
26
|
|
|
11
|
-
def __init__(
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
prefix: str,
|
|
30
|
+
x_gap: str = "X:SIZE",
|
|
31
|
+
y_gap: str = "Y:SIZE",
|
|
32
|
+
x_centre: str = "X:CENTRE",
|
|
33
|
+
y_centre: str = "Y:CENTRE",
|
|
34
|
+
name: str = "",
|
|
35
|
+
) -> None:
|
|
12
36
|
with self.add_children_as_readables():
|
|
13
|
-
self.
|
|
14
|
-
self.
|
|
15
|
-
|
|
16
|
-
self.y_centre = Motor(prefix + "Y:CENTRE")
|
|
17
|
-
super().__init__(name)
|
|
37
|
+
self.x_centre = Motor(prefix + x_centre)
|
|
38
|
+
self.y_centre = Motor(prefix + y_centre)
|
|
39
|
+
super().__init__(prefix=prefix, x_gap=x_gap, y_gap=y_gap, name=name)
|
dodal/devices/tetramm.py
CHANGED
|
@@ -22,31 +22,31 @@ from ophyd_async.epics.core import (
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class TetrammRange(StrictEnum):
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
UA = "+- 120 uA"
|
|
26
|
+
NA = "+- 120 nA"
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class TetrammTrigger(StrictEnum):
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
FREE_RUN = "Free run"
|
|
31
|
+
EXT_TRIGGER = "Ext. trig."
|
|
32
|
+
EXT_BULB = "Ext. bulb"
|
|
33
|
+
EXT_GATE = "Ext. gate"
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class TetrammChannels(StrictEnum):
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
ONE = "1"
|
|
38
|
+
TWO = "2"
|
|
39
|
+
FOUR = "4"
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
class TetrammResolution(StrictEnum):
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
SIXTEEN_BITS = "16 bits"
|
|
44
|
+
TWENTY_FOUR_BITS = "24 bits"
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
class TetrammGeometry(StrictEnum):
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
DIAMOND = "Diamond"
|
|
49
|
+
SQUARE = "Square"
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
class TetrammDriver(Device):
|
|
@@ -118,7 +118,7 @@ class TetrammController(DetectorController):
|
|
|
118
118
|
assert trigger_info.livetime is not None
|
|
119
119
|
|
|
120
120
|
# trigger mode must be set first and on its own!
|
|
121
|
-
await self._drv.trigger_mode.set(TetrammTrigger.
|
|
121
|
+
await self._drv.trigger_mode.set(TetrammTrigger.EXT_TRIGGER)
|
|
122
122
|
|
|
123
123
|
await asyncio.gather(
|
|
124
124
|
self._drv.averaging_time.set(trigger_info.livetime),
|
|
@@ -134,8 +134,8 @@ class TetrammController(DetectorController):
|
|
|
134
134
|
|
|
135
135
|
def _validate_trigger(self, trigger: DetectorTrigger) -> None:
|
|
136
136
|
supported_trigger_types = {
|
|
137
|
-
DetectorTrigger.
|
|
138
|
-
DetectorTrigger.
|
|
137
|
+
DetectorTrigger.EDGE_TRIGGER,
|
|
138
|
+
DetectorTrigger.CONSTANT_GATE,
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
if trigger not in supported_trigger_types:
|
dodal/devices/undulator_dcm.py
CHANGED
|
@@ -5,6 +5,7 @@ from ophyd_async.core import AsyncStatus, StandardReadable
|
|
|
5
5
|
|
|
6
6
|
from dodal.common.beamlines.beamline_parameters import get_beamline_parameters
|
|
7
7
|
|
|
8
|
+
from ..log import LOGGER
|
|
8
9
|
from .dcm import DCM
|
|
9
10
|
from .undulator import Undulator
|
|
10
11
|
|
|
@@ -59,3 +60,6 @@ class UndulatorDCM(StandardReadable, Movable):
|
|
|
59
60
|
self.dcm.energy_in_kev.set(value, timeout=ENERGY_TIMEOUT_S),
|
|
60
61
|
self.undulator.set(value),
|
|
61
62
|
)
|
|
63
|
+
# DCM Perp pitch
|
|
64
|
+
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)
|
dodal/devices/util/test_utils.py
CHANGED
|
@@ -26,12 +26,12 @@ class TriggerMode(StrictEnum):
|
|
|
26
26
|
SOFTWARE = "Software"
|
|
27
27
|
HARDWARE = "Hardware"
|
|
28
28
|
BURST = "Burst"
|
|
29
|
-
|
|
29
|
+
TTL_VETO_ONLY = "TTL Veto Only"
|
|
30
30
|
IDC = "IDC"
|
|
31
31
|
SOTWARE_START_STOP = "Software Start/Stop"
|
|
32
32
|
TTL_BOTH = "TTL Both"
|
|
33
33
|
LVDS_VETO_ONLY = "LVDS Veto Only"
|
|
34
|
-
|
|
34
|
+
LVDS_BOTH = "LVDS Both"
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
class UpdateRBV(StrictEnum):
|
|
@@ -49,7 +49,7 @@ class DetectorState(StrictEnum):
|
|
|
49
49
|
ACQUIRE = "Acquire"
|
|
50
50
|
READOUT = "Readout"
|
|
51
51
|
CORRECT = "Correct"
|
|
52
|
-
|
|
52
|
+
SAVING = "Saving"
|
|
53
53
|
ABORTING = "Aborting"
|
|
54
54
|
ERROR = "Error"
|
|
55
55
|
WAITING = "Waiting"
|
dodal/devices/zebra.py
CHANGED
|
@@ -59,25 +59,25 @@ class TrigSource(StrictEnum):
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
class EncEnum(StrictEnum):
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
ENC1 = "Enc1"
|
|
63
|
+
ENC2 = "Enc2"
|
|
64
|
+
ENC3 = "Enc3"
|
|
65
|
+
ENC4 = "Enc4"
|
|
66
|
+
ENC1_4AV = "Enc1-4Av"
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
class I03Axes:
|
|
70
|
-
SMARGON_X1 = EncEnum.
|
|
71
|
-
SMARGON_Y = EncEnum.
|
|
72
|
-
SMARGON_Z = EncEnum.
|
|
73
|
-
OMEGA = EncEnum.
|
|
70
|
+
SMARGON_X1 = EncEnum.ENC1
|
|
71
|
+
SMARGON_Y = EncEnum.ENC2
|
|
72
|
+
SMARGON_Z = EncEnum.ENC3
|
|
73
|
+
OMEGA = EncEnum.ENC4
|
|
74
74
|
|
|
75
75
|
|
|
76
76
|
class I24Axes:
|
|
77
|
-
VGON_Z = EncEnum.
|
|
78
|
-
OMEGA = EncEnum.
|
|
79
|
-
VGON_X = EncEnum.
|
|
80
|
-
VGON_YH = EncEnum.
|
|
77
|
+
VGON_Z = EncEnum.ENC1
|
|
78
|
+
OMEGA = EncEnum.ENC2
|
|
79
|
+
VGON_X = EncEnum.ENC3
|
|
80
|
+
VGON_YH = EncEnum.ENC4
|
|
81
81
|
|
|
82
82
|
|
|
83
83
|
class RotationDirection(StrictEnum):
|
dodal/adsim.py
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
|
-
from dodal.devices.adsim import SimStage
|
|
4
|
-
from dodal.devices.areadetector import AdSimDetector
|
|
5
|
-
|
|
6
|
-
from .utils import get_hostname
|
|
7
|
-
|
|
8
|
-
# Default prefix to hostname unless overriden with export PREFIX=<prefix>
|
|
9
|
-
PREFIX: str = os.environ.get("PREFIX", get_hostname())
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def stage(name: str = "sim_motors") -> SimStage:
|
|
13
|
-
return SimStage(name=name, prefix=f"{PREFIX}-MO-SIM-01:")
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def det(name: str = "adsim") -> AdSimDetector:
|
|
17
|
-
return AdSimDetector(name=name, prefix=f"{PREFIX}-AD-SIM-01:")
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
from collections.abc import Mapping
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from ophyd import EpicsSignal, Signal
|
|
5
|
-
from ophyd.areadetector.base import ADComponent as Cpt
|
|
6
|
-
from ophyd.areadetector.detectors import DetectorBase
|
|
7
|
-
|
|
8
|
-
from .adutils import Hdf5Writer, SingleTriggerV33, SynchronisedAdDriverBase
|
|
9
|
-
|
|
10
|
-
_ACQUIRE_BUFFER_PERIOD = 0.2
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class AdAravisDetector(SingleTriggerV33, DetectorBase):
|
|
14
|
-
cam = Cpt(SynchronisedAdDriverBase, suffix="DET:")
|
|
15
|
-
hdf = Cpt(
|
|
16
|
-
Hdf5Writer,
|
|
17
|
-
suffix="HDF5:",
|
|
18
|
-
root="",
|
|
19
|
-
write_path_template="",
|
|
20
|
-
)
|
|
21
|
-
_priming_settings: Mapping[Signal, Any]
|
|
22
|
-
|
|
23
|
-
def __init__(self, *args, **kwargs) -> None:
|
|
24
|
-
super().__init__(*args, **kwargs)
|
|
25
|
-
self.hdf.kind = "normal"
|
|
26
|
-
|
|
27
|
-
# Values for staging
|
|
28
|
-
self.stage_sigs = {
|
|
29
|
-
# Get stage to wire up the plugins
|
|
30
|
-
self.hdf.nd_array_port: self.cam.port_name.get(),
|
|
31
|
-
# Reset array counter on stage
|
|
32
|
-
self.cam.array_counter: 0,
|
|
33
|
-
# Set image mode to multiple on stage so we have the option, can still
|
|
34
|
-
# set num_images to 1
|
|
35
|
-
self.cam.image_mode: "Multiple",
|
|
36
|
-
# For now, this Ophyd device does not support hardware
|
|
37
|
-
# triggered scanning, disable on stage
|
|
38
|
-
self.cam.trigger_mode: "Off",
|
|
39
|
-
**self.stage_sigs, # type: ignore
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
# Settings to apply when priming plugins during pre-stage
|
|
43
|
-
self._priming_settings = {
|
|
44
|
-
self.hdf.enable: 1,
|
|
45
|
-
self.hdf.nd_array_port: self.cam.port_name.get(),
|
|
46
|
-
self.cam.array_callbacks: 1,
|
|
47
|
-
self.cam.image_mode: "Single",
|
|
48
|
-
self.cam.trigger_mode: "Off",
|
|
49
|
-
# Take the quickest possible frame
|
|
50
|
-
self.cam.acquire_time: 6.3e-05,
|
|
51
|
-
self.cam.acquire_period: 0.003,
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
# Signals that control driver and hdf writer should be put_complete to
|
|
55
|
-
# avoid race conditions during priming
|
|
56
|
-
for signal in set(self.stage_sigs.keys()).union(
|
|
57
|
-
set(self._priming_settings.keys())
|
|
58
|
-
):
|
|
59
|
-
if isinstance(signal, EpicsSignal):
|
|
60
|
-
signal.put_complete = True
|
|
61
|
-
self.cam.acquire.put_complete = True
|
|
62
|
-
|
|
63
|
-
def stage(self, *args, **kwargs) -> list[object]:
|
|
64
|
-
# We have to manually set the acquire period bcause the EPICS driver
|
|
65
|
-
# doesn't do it for us. If acquire time is a staged signal, we use the
|
|
66
|
-
# stage value to calculate the acquire period, otherwise we perform
|
|
67
|
-
# a caget and use the current acquire time.
|
|
68
|
-
if self.cam.acquire_time in self.stage_sigs:
|
|
69
|
-
acquire_time = self.stage_sigs[self.cam.acquire_time]
|
|
70
|
-
else:
|
|
71
|
-
acquire_time = self.cam.acquire_time.get()
|
|
72
|
-
self.stage_sigs[self.cam.acquire_period] = (
|
|
73
|
-
float(acquire_time) + _ACQUIRE_BUFFER_PERIOD
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
# Ensure detector warmed up
|
|
77
|
-
self._prime_hdf()
|
|
78
|
-
|
|
79
|
-
# Now calling the super method should set the acquire period
|
|
80
|
-
return super().stage(*args, **kwargs)
|
|
81
|
-
|
|
82
|
-
def _prime_hdf(self) -> None:
|
|
83
|
-
"""
|
|
84
|
-
Take a single frame and pipe it through the HDF5 writer plugin
|
|
85
|
-
"""
|
|
86
|
-
|
|
87
|
-
# Backup state and ensure we are not acquiring
|
|
88
|
-
reset_to = {signal: signal.get() for signal in self._priming_settings.keys()}
|
|
89
|
-
self.cam.acquire.set(0).wait(timeout=10)
|
|
90
|
-
|
|
91
|
-
# Apply all settings for acquisition
|
|
92
|
-
for signal, value in self._priming_settings.items():
|
|
93
|
-
# Ensure that .wait really will wait until the PV is set including its RBV
|
|
94
|
-
signal.set(value).wait(timeout=10)
|
|
95
|
-
|
|
96
|
-
# Acquire a frame
|
|
97
|
-
self.cam.acquire.set(1).wait(timeout=10)
|
|
98
|
-
|
|
99
|
-
# Revert settings to previous values
|
|
100
|
-
for signal, value in reversed(reset_to.items()):
|
|
101
|
-
signal.set(value).wait(timeout=10)
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
from ophyd.areadetector.base import ADComponent as Cpt
|
|
2
|
-
from ophyd.areadetector.detectors import DetectorBase
|
|
3
|
-
|
|
4
|
-
from .adutils import Hdf5Writer, SingleTriggerV33, SynchronisedAdDriverBase
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class AdSimDetector(SingleTriggerV33, DetectorBase):
|
|
8
|
-
cam = Cpt(SynchronisedAdDriverBase, suffix="CAM:", lazy=True)
|
|
9
|
-
hdf = Cpt(
|
|
10
|
-
Hdf5Writer,
|
|
11
|
-
suffix="HDF5:",
|
|
12
|
-
root="",
|
|
13
|
-
write_path_template="",
|
|
14
|
-
lazy=True,
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
def __init__(self, *args, **kwargs) -> None:
|
|
18
|
-
super().__init__(*args, **kwargs)
|
|
19
|
-
self.hdf.kind = "normal"
|
|
20
|
-
|
|
21
|
-
self.stage_sigs = {
|
|
22
|
-
# Get stage to wire up the plugins
|
|
23
|
-
self.hdf.nd_array_port: self.cam.port_name.get(),
|
|
24
|
-
# Reset array counter on stage
|
|
25
|
-
self.cam.array_counter: 0,
|
|
26
|
-
# Set image mode to multiple on stage so we have the option, can still
|
|
27
|
-
# set num_images to 1
|
|
28
|
-
self.cam.image_mode: "Multiple",
|
|
29
|
-
# For now, this Ophyd device does not support hardware
|
|
30
|
-
# triggered scanning, disable on stage
|
|
31
|
-
self.cam.trigger_mode: "Internal",
|
|
32
|
-
**self.stage_sigs, # type: ignore
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
def stage(self, *args, **kwargs) -> list[object]:
|
|
36
|
-
# We have to manually set the acquire period bcause the EPICS driver
|
|
37
|
-
# doesn't do it for us. If acquire time is a staged signal, we use the
|
|
38
|
-
# stage value to calculate the acquire period, otherwise we perform
|
|
39
|
-
# a caget and use the current acquire time.
|
|
40
|
-
if self.cam.acquire_time in self.stage_sigs:
|
|
41
|
-
acquire_time = self.stage_sigs[self.cam.acquire_time]
|
|
42
|
-
else:
|
|
43
|
-
acquire_time = self.cam.acquire_time.get()
|
|
44
|
-
self.stage_sigs[self.cam.acquire_period] = acquire_time
|
|
45
|
-
|
|
46
|
-
# Now calling the super method should set the acquire period
|
|
47
|
-
return super().stage(*args, **kwargs)
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import time as ttime
|
|
2
|
-
|
|
3
|
-
from ophyd import Component as Cpt
|
|
4
|
-
from ophyd import DetectorBase, Device, EpicsSignal, EpicsSignalRO, Staged
|
|
5
|
-
from ophyd.areadetector import ADTriggerStatus, TriggerBase
|
|
6
|
-
from ophyd.areadetector.cam import AreaDetectorCam
|
|
7
|
-
from ophyd.areadetector.filestore_mixins import FileStoreHDF5, FileStoreIterativeWrite
|
|
8
|
-
from ophyd.areadetector.plugins import HDF5Plugin
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class SingleTriggerV33(TriggerBase):
|
|
12
|
-
_status_type = ADTriggerStatus
|
|
13
|
-
|
|
14
|
-
def __init__(self, *args, image_name=None, **kwargs):
|
|
15
|
-
super().__init__(*args, **kwargs)
|
|
16
|
-
if image_name is None:
|
|
17
|
-
# Ensure that this mixin is part of valid device with name
|
|
18
|
-
assert isinstance(self, Device)
|
|
19
|
-
image_name = "_".join([self.name, "image"])
|
|
20
|
-
self._image_name = image_name
|
|
21
|
-
|
|
22
|
-
def trigger(self):
|
|
23
|
-
"Trigger one acquisition."
|
|
24
|
-
if self._staged != Staged.yes:
|
|
25
|
-
raise RuntimeError(
|
|
26
|
-
"This detector is not ready to trigger."
|
|
27
|
-
"Call the stage() method before triggering."
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
self._status = self._status_type(self)
|
|
31
|
-
|
|
32
|
-
def _acq_done(*args, **kwargs):
|
|
33
|
-
# TODO sort out if anything useful in here
|
|
34
|
-
self._status._finished() # noqa: SLF001
|
|
35
|
-
|
|
36
|
-
self._acquisition_signal.put(1, use_complete=True, callback=_acq_done)
|
|
37
|
-
# Ensure that this mixin is part of valid Detector with generate_datum
|
|
38
|
-
assert isinstance(self, DetectorBase)
|
|
39
|
-
self.generate_datum(self._image_name, ttime.time())
|
|
40
|
-
return self._status
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
class SynchronisedAdDriverBase(AreaDetectorCam):
|
|
44
|
-
"""
|
|
45
|
-
Base Ophyd device to control an AreaDetector driver and
|
|
46
|
-
syncrhonise it on other AreaDetector plugins, even non-blocking ones.
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
adcore_version = Cpt(EpicsSignalRO, "ADCoreVersion_RBV", string=True, kind="config")
|
|
50
|
-
driver_version = Cpt(EpicsSignalRO, "DriverVersion_RBV", string=True, kind="config")
|
|
51
|
-
wait_for_plugins = Cpt(EpicsSignal, "WaitForPlugins", string=True, kind="config")
|
|
52
|
-
|
|
53
|
-
def stage(self, *args, **kwargs):
|
|
54
|
-
# Makes the detector allow non-blocking AD plugins but makes Ophyd use
|
|
55
|
-
# the AcquireBusy PV to determine when an acquisition is complete
|
|
56
|
-
self.ensure_nonblocking()
|
|
57
|
-
return super().stage(*args, **kwargs)
|
|
58
|
-
|
|
59
|
-
def ensure_nonblocking(self):
|
|
60
|
-
self.stage_sigs["wait_for_plugins"] = "Yes"
|
|
61
|
-
if self.parent is not None:
|
|
62
|
-
for c in self.parent.component_names:
|
|
63
|
-
cpt = getattr(self.parent, c)
|
|
64
|
-
if cpt is self:
|
|
65
|
-
continue
|
|
66
|
-
if hasattr(cpt, "ensure_nonblocking"):
|
|
67
|
-
cpt.ensure_nonblocking()
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
# ophyd code to be removed, only used for adim
|
|
71
|
-
# https://github.com/DiamondLightSource/dodal/issues/404
|
|
72
|
-
class Hdf5Writer(HDF5Plugin, FileStoreHDF5, FileStoreIterativeWrite): # type: ignore
|
|
73
|
-
""" """
|
|
74
|
-
|
|
75
|
-
pool_max_buffers = None
|
|
76
|
-
file_number_sync = None
|
|
77
|
-
file_number_write = None
|
|
78
|
-
|
|
79
|
-
def get_frames_per_point(self):
|
|
80
|
-
assert isinstance(self.parent, DetectorBase)
|
|
81
|
-
return self.parent.cam.num_images.get()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|