dls-dodal 1.47.0__py3-none-any.whl → 1.49.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.47.0.dist-info → dls_dodal-1.49.0.dist-info}/METADATA +3 -2
- {dls_dodal-1.47.0.dist-info → dls_dodal-1.49.0.dist-info}/RECORD +59 -49
- {dls_dodal-1.47.0.dist-info → dls_dodal-1.49.0.dist-info}/WHEEL +1 -1
- dodal/_version.py +2 -2
- dodal/beamlines/aithre.py +21 -0
- dodal/beamlines/b01_1.py +1 -1
- dodal/beamlines/b16.py +65 -0
- dodal/beamlines/b18.py +38 -0
- dodal/beamlines/i03.py +21 -6
- dodal/beamlines/i04.py +17 -10
- dodal/beamlines/i10.py +41 -233
- dodal/beamlines/i18.py +1 -1
- dodal/beamlines/i19_1.py +9 -6
- dodal/beamlines/i24.py +5 -5
- dodal/beamlines/k11.py +35 -0
- dodal/common/beamlines/beamline_parameters.py +2 -28
- dodal/common/beamlines/device_helpers.py +1 -0
- dodal/devices/aithre_lasershaping/goniometer.py +36 -2
- dodal/devices/aithre_lasershaping/laser_robot.py +27 -0
- dodal/devices/apple2_undulator.py +257 -136
- dodal/devices/b16/__init__.py +0 -0
- dodal/devices/b16/detector.py +34 -0
- dodal/devices/bimorph_mirror.py +29 -36
- dodal/devices/electron_analyser/__init__.py +21 -1
- dodal/devices/electron_analyser/abstract/__init__.py +0 -6
- dodal/devices/electron_analyser/abstract/base_detector.py +16 -128
- dodal/devices/electron_analyser/abstract/base_driver_io.py +122 -8
- dodal/devices/electron_analyser/abstract/base_region.py +7 -3
- dodal/devices/electron_analyser/detector.py +141 -0
- dodal/devices/electron_analyser/enums.py +6 -0
- dodal/devices/electron_analyser/specs/__init__.py +3 -2
- dodal/devices/electron_analyser/specs/detector.py +6 -22
- dodal/devices/electron_analyser/specs/driver_io.py +27 -3
- dodal/devices/electron_analyser/specs/enums.py +8 -0
- dodal/devices/electron_analyser/specs/region.py +3 -2
- dodal/devices/electron_analyser/types.py +30 -4
- dodal/devices/electron_analyser/util.py +1 -1
- dodal/devices/electron_analyser/vgscienta/__init__.py +3 -2
- dodal/devices/electron_analyser/vgscienta/detector.py +9 -23
- dodal/devices/electron_analyser/vgscienta/driver_io.py +33 -4
- dodal/devices/electron_analyser/vgscienta/enums.py +19 -0
- dodal/devices/electron_analyser/vgscienta/region.py +7 -23
- dodal/devices/fast_grid_scan.py +1 -1
- dodal/devices/i04/murko_results.py +93 -96
- dodal/devices/i10/__init__.py +0 -0
- dodal/devices/i10/i10_apple2.py +181 -126
- dodal/devices/i18/diode.py +37 -4
- dodal/devices/i22/nxsas.py +1 -1
- dodal/devices/mx_phase1/beamstop.py +23 -6
- dodal/devices/oav/oav_detector.py +101 -25
- dodal/devices/oav/oav_parameters.py +46 -16
- dodal/devices/oav/oav_to_redis_forwarder.py +2 -2
- dodal/devices/robot.py +20 -1
- dodal/devices/smargon.py +43 -4
- dodal/devices/zebra/zebra.py +8 -0
- dodal/plans/configure_arm_trigger_and_disarm_detector.py +167 -0
- dodal/plan_stubs/electron_analyser/__init__.py +0 -3
- dodal/plan_stubs/electron_analyser/configure_driver.py +0 -92
- {dls_dodal-1.47.0.dist-info → dls_dodal-1.49.0.dist-info}/entry_points.txt +0 -0
- {dls_dodal-1.47.0.dist-info → dls_dodal-1.49.0.dist-info}/licenses/LICENSE +0 -0
- {dls_dodal-1.47.0.dist-info → dls_dodal-1.49.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
from typing import Generic, TypeVar
|
|
2
|
+
|
|
3
|
+
from bluesky.protocols import Preparable
|
|
4
|
+
from ophyd_async.core import (
|
|
5
|
+
AsyncStatus,
|
|
6
|
+
Reference,
|
|
7
|
+
)
|
|
8
|
+
from ophyd_async.epics.motor import Motor
|
|
9
|
+
|
|
10
|
+
from dodal.common.data_util import load_json_file_to_class
|
|
11
|
+
from dodal.devices.electron_analyser.abstract.base_detector import (
|
|
12
|
+
AbstractElectronAnalyserDetector,
|
|
13
|
+
)
|
|
14
|
+
from dodal.devices.electron_analyser.abstract.base_driver_io import (
|
|
15
|
+
TAbstractAnalyserDriverIO,
|
|
16
|
+
)
|
|
17
|
+
from dodal.devices.electron_analyser.abstract.base_region import (
|
|
18
|
+
TAbstractBaseRegion,
|
|
19
|
+
TAbstractBaseSequence,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ElectronAnalyserRegionDetector(
|
|
24
|
+
AbstractElectronAnalyserDetector[TAbstractAnalyserDriverIO],
|
|
25
|
+
Preparable,
|
|
26
|
+
Generic[TAbstractAnalyserDriverIO, TAbstractBaseRegion],
|
|
27
|
+
):
|
|
28
|
+
"""
|
|
29
|
+
Extends electron analyser detector to configure specific region settings before data
|
|
30
|
+
acqusition. This object must be passed in a driver and store it as a reference. It
|
|
31
|
+
is designed to only exist inside a plan.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
driver: TAbstractAnalyserDriverIO,
|
|
37
|
+
region: TAbstractBaseRegion,
|
|
38
|
+
name: str = "",
|
|
39
|
+
):
|
|
40
|
+
self._driver_ref = Reference(driver)
|
|
41
|
+
self.region = region
|
|
42
|
+
super().__init__(driver, name)
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def driver(self) -> TAbstractAnalyserDriverIO:
|
|
46
|
+
# Store as a reference, this implementation will be given a driver so needs to
|
|
47
|
+
# make sure we don't get conflicting parents.
|
|
48
|
+
return self._driver_ref()
|
|
49
|
+
|
|
50
|
+
@AsyncStatus.wrap
|
|
51
|
+
async def prepare(self, value: Motor) -> None:
|
|
52
|
+
"""
|
|
53
|
+
Prepare driver with the region stored and energy_source motor.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
value: The excitation energy source that the region has selected.
|
|
57
|
+
"""
|
|
58
|
+
excitation_energy_source = value
|
|
59
|
+
await self.driver.prepare(excitation_energy_source)
|
|
60
|
+
await self.driver.set(self.region)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
TElectronAnalyserRegionDetector = TypeVar(
|
|
64
|
+
"TElectronAnalyserRegionDetector",
|
|
65
|
+
bound=ElectronAnalyserRegionDetector,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ElectronAnalyserDetector(
|
|
70
|
+
AbstractElectronAnalyserDetector[TAbstractAnalyserDriverIO],
|
|
71
|
+
Generic[
|
|
72
|
+
TAbstractAnalyserDriverIO,
|
|
73
|
+
TAbstractBaseSequence,
|
|
74
|
+
TAbstractBaseRegion,
|
|
75
|
+
],
|
|
76
|
+
):
|
|
77
|
+
"""
|
|
78
|
+
Electron analyser detector with the additional functionality to load a sequence file
|
|
79
|
+
and create a list of temporary ElectronAnalyserRegionDetector objects. These will
|
|
80
|
+
setup configured region settings before data acquisition.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
def __init__(
|
|
84
|
+
self,
|
|
85
|
+
prefix: str,
|
|
86
|
+
sequence_class: type[TAbstractBaseSequence],
|
|
87
|
+
driver: TAbstractAnalyserDriverIO,
|
|
88
|
+
name: str = "",
|
|
89
|
+
):
|
|
90
|
+
# Pass in driver
|
|
91
|
+
self._driver = driver
|
|
92
|
+
self._sequence_class = sequence_class
|
|
93
|
+
super().__init__(self.driver, name)
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def driver(self) -> TAbstractAnalyserDriverIO:
|
|
97
|
+
# This implementation creates the driver and wants this to be the parent so it
|
|
98
|
+
# can be used with connect() method.
|
|
99
|
+
return self._driver
|
|
100
|
+
|
|
101
|
+
def load_sequence(self, filename: str) -> TAbstractBaseSequence:
|
|
102
|
+
"""
|
|
103
|
+
Load the sequence data from a provided json file into a sequence class.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
filename: Path to the sequence file containing the region data.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Pydantic model representing the sequence file.
|
|
110
|
+
"""
|
|
111
|
+
return load_json_file_to_class(self._sequence_class, filename)
|
|
112
|
+
|
|
113
|
+
def create_region_detector_list(
|
|
114
|
+
self, filename: str, enabled_only=True
|
|
115
|
+
) -> list[
|
|
116
|
+
ElectronAnalyserRegionDetector[TAbstractAnalyserDriverIO, TAbstractBaseRegion]
|
|
117
|
+
]:
|
|
118
|
+
"""
|
|
119
|
+
Create a list of detectors equal to the number of regions in a sequence file.
|
|
120
|
+
Each detector is responsible for setting up a specific region.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
filename: Path to the sequence file containing the region data.
|
|
124
|
+
enabled_only: If true, only include the region if enabled is True.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
List of ElectronAnalyserRegionDetector, equal to the number of regions in
|
|
128
|
+
the sequence file.
|
|
129
|
+
"""
|
|
130
|
+
seq = self.load_sequence(filename)
|
|
131
|
+
regions = seq.get_enabled_regions() if enabled_only else seq.regions
|
|
132
|
+
return [
|
|
133
|
+
ElectronAnalyserRegionDetector(self.driver, r, self.name + "_" + r.name)
|
|
134
|
+
for r in regions
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
TElectronAnalyserDetector = TypeVar(
|
|
139
|
+
"TElectronAnalyserDetector",
|
|
140
|
+
bound=ElectronAnalyserDetector,
|
|
141
|
+
)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
from .detector import SpecsDetector
|
|
1
|
+
from .detector import SpecsDetector
|
|
2
2
|
from .driver_io import SpecsAnalyserDriverIO
|
|
3
|
+
from .enums import AcquisitionMode
|
|
3
4
|
from .region import SpecsRegion, SpecsSequence
|
|
4
5
|
|
|
5
6
|
__all__ = [
|
|
6
7
|
"SpecsDetector",
|
|
7
|
-
"SpecsRegionDetector",
|
|
8
8
|
"SpecsAnalyserDriverIO",
|
|
9
|
+
"AcquisitionMode",
|
|
9
10
|
"SpecsRegion",
|
|
10
11
|
"SpecsSequence",
|
|
11
12
|
]
|
|
@@ -1,29 +1,13 @@
|
|
|
1
|
-
from dodal.devices.electron_analyser.
|
|
2
|
-
|
|
3
|
-
AbstractElectronAnalyserRegionDetector,
|
|
1
|
+
from dodal.devices.electron_analyser.detector import (
|
|
2
|
+
ElectronAnalyserDetector,
|
|
4
3
|
)
|
|
5
4
|
from dodal.devices.electron_analyser.specs.driver_io import SpecsAnalyserDriverIO
|
|
6
5
|
from dodal.devices.electron_analyser.specs.region import SpecsRegion, SpecsSequence
|
|
7
6
|
|
|
8
7
|
|
|
9
|
-
class SpecsRegionDetector(
|
|
10
|
-
AbstractElectronAnalyserRegionDetector[SpecsAnalyserDriverIO, SpecsRegion]
|
|
11
|
-
):
|
|
12
|
-
def configure_region(self):
|
|
13
|
-
# ToDo - Need to move configure plans to here and rewrite tests
|
|
14
|
-
pass
|
|
15
|
-
|
|
16
|
-
|
|
17
8
|
class SpecsDetector(
|
|
18
|
-
|
|
9
|
+
ElectronAnalyserDetector[SpecsAnalyserDriverIO, SpecsSequence, SpecsRegion]
|
|
19
10
|
):
|
|
20
|
-
def __init__(self, prefix: str, name: str):
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def _create_driver(self, prefix: str) -> SpecsAnalyserDriverIO:
|
|
24
|
-
return SpecsAnalyserDriverIO(prefix, "driver")
|
|
25
|
-
|
|
26
|
-
def _create_region_detector(
|
|
27
|
-
self, driver: SpecsAnalyserDriverIO, region: SpecsRegion
|
|
28
|
-
) -> SpecsRegionDetector:
|
|
29
|
-
return SpecsRegionDetector(self.name, driver, region)
|
|
11
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
12
|
+
driver = SpecsAnalyserDriverIO(prefix=prefix)
|
|
13
|
+
super().__init__(prefix, SpecsSequence, driver, name)
|
|
@@ -1,13 +1,23 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
1
3
|
import numpy as np
|
|
2
|
-
from ophyd_async.core import
|
|
4
|
+
from ophyd_async.core import (
|
|
5
|
+
Array1D,
|
|
6
|
+
AsyncStatus,
|
|
7
|
+
SignalR,
|
|
8
|
+
StandardReadableFormat,
|
|
9
|
+
derived_signal_r,
|
|
10
|
+
)
|
|
3
11
|
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
4
12
|
|
|
5
13
|
from dodal.devices.electron_analyser.abstract.base_driver_io import (
|
|
6
14
|
AbstractAnalyserDriverIO,
|
|
7
15
|
)
|
|
16
|
+
from dodal.devices.electron_analyser.specs.enums import AcquisitionMode
|
|
17
|
+
from dodal.devices.electron_analyser.specs.region import SpecsRegion
|
|
8
18
|
|
|
9
19
|
|
|
10
|
-
class SpecsAnalyserDriverIO(AbstractAnalyserDriverIO):
|
|
20
|
+
class SpecsAnalyserDriverIO(AbstractAnalyserDriverIO[SpecsRegion]):
|
|
11
21
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
12
22
|
with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
|
|
13
23
|
# Used for setting up region data acquisition.
|
|
@@ -19,7 +29,21 @@ class SpecsAnalyserDriverIO(AbstractAnalyserDriverIO):
|
|
|
19
29
|
self.min_angle_axis = epics_signal_r(float, prefix + "Y_MIN_RBV")
|
|
20
30
|
self.max_angle_axis = epics_signal_r(float, prefix + "Y_MAX_RBV")
|
|
21
31
|
|
|
22
|
-
super().__init__(prefix, name)
|
|
32
|
+
super().__init__(prefix, AcquisitionMode, name)
|
|
33
|
+
|
|
34
|
+
@AsyncStatus.wrap
|
|
35
|
+
async def set(self, region: SpecsRegion):
|
|
36
|
+
await super().set(region)
|
|
37
|
+
|
|
38
|
+
await asyncio.gather(
|
|
39
|
+
self.snapshot_values.set(region.values),
|
|
40
|
+
self.psu_mode.set(region.psu_mode),
|
|
41
|
+
)
|
|
42
|
+
if region.acquisition_mode == AcquisitionMode.FIXED_TRANSMISSION:
|
|
43
|
+
await self.centre_energy.set(region.centre_energy)
|
|
44
|
+
|
|
45
|
+
if self.acquisition_mode == AcquisitionMode.FIXED_ENERGY:
|
|
46
|
+
await self.energy_step.set(region.energy_step)
|
|
23
47
|
|
|
24
48
|
def _create_angle_axis_signal(self, prefix: str) -> SignalR[Array1D[np.float64]]:
|
|
25
49
|
angle_axis = derived_signal_r(
|
|
@@ -4,13 +4,14 @@ from dodal.devices.electron_analyser.abstract.base_region import (
|
|
|
4
4
|
AbstractBaseRegion,
|
|
5
5
|
AbstractBaseSequence,
|
|
6
6
|
)
|
|
7
|
+
from dodal.devices.electron_analyser.specs.enums import AcquisitionMode
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
class SpecsRegion(AbstractBaseRegion):
|
|
10
|
+
class SpecsRegion(AbstractBaseRegion[AcquisitionMode]):
|
|
10
11
|
# Override base class with defaults
|
|
11
12
|
lens_mode: str = "SmallArea"
|
|
12
13
|
pass_energy: int = 5
|
|
13
|
-
acquisition_mode:
|
|
14
|
+
acquisition_mode: AcquisitionMode = AcquisitionMode.FIXED_TRANSMISSION
|
|
14
15
|
low_energy: float = Field(default=800, alias="start_energy")
|
|
15
16
|
high_energy: float = Field(default=850, alias="end_energy")
|
|
16
17
|
step_time: float = Field(default=1.0, alias="exposure_time")
|
|
@@ -1,6 +1,32 @@
|
|
|
1
|
-
from
|
|
1
|
+
from dodal.devices.electron_analyser.abstract.base_driver_io import (
|
|
2
|
+
AbstractAnalyserDriverIO,
|
|
3
|
+
)
|
|
4
|
+
from dodal.devices.electron_analyser.abstract.base_region import (
|
|
5
|
+
AbstractBaseRegion,
|
|
6
|
+
AbstractBaseSequence,
|
|
7
|
+
)
|
|
8
|
+
from dodal.devices.electron_analyser.detector import (
|
|
9
|
+
ElectronAnalyserDetector,
|
|
10
|
+
ElectronAnalyserRegionDetector,
|
|
11
|
+
)
|
|
12
|
+
from dodal.devices.electron_analyser.specs.detector import (
|
|
13
|
+
SpecsAnalyserDriverIO,
|
|
14
|
+
SpecsDetector,
|
|
15
|
+
)
|
|
16
|
+
from dodal.devices.electron_analyser.vgscienta.detector import (
|
|
17
|
+
VGScientaAnalyserDriverIO,
|
|
18
|
+
VGScientaDetector,
|
|
19
|
+
)
|
|
2
20
|
|
|
21
|
+
ElectronAnalyserDetectorImpl = VGScientaDetector | SpecsDetector
|
|
22
|
+
ElectronAnalyserDriverImpl = VGScientaAnalyserDriverIO | SpecsAnalyserDriverIO
|
|
3
23
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
24
|
+
GenericElectronAnalyserDetector = ElectronAnalyserDetector[
|
|
25
|
+
AbstractAnalyserDriverIO[AbstractBaseRegion],
|
|
26
|
+
AbstractBaseSequence,
|
|
27
|
+
AbstractBaseRegion,
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
GenericElectronAnalyserRegionDetector = ElectronAnalyserRegionDetector[
|
|
31
|
+
AbstractAnalyserDriverIO[AbstractBaseRegion], AbstractBaseRegion
|
|
32
|
+
]
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
from .detector import VGScientaDetector
|
|
1
|
+
from .detector import VGScientaDetector
|
|
2
2
|
from .driver_io import VGScientaAnalyserDriverIO
|
|
3
|
+
from .enums import AcquisitionMode
|
|
3
4
|
from .region import VGScientaExcitationEnergySource, VGScientaRegion, VGScientaSequence
|
|
4
5
|
|
|
5
6
|
__all__ = [
|
|
6
7
|
"VGScientaDetector",
|
|
7
|
-
"VGScientaRegionDetector",
|
|
8
8
|
"VGScientaAnalyserDriverIO",
|
|
9
|
+
"AcquisitionMode",
|
|
9
10
|
"VGScientaExcitationEnergySource",
|
|
10
11
|
"VGScientaRegion",
|
|
11
12
|
"VGScientaSequence",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
from dodal.devices.electron_analyser.
|
|
2
|
-
|
|
3
|
-
AbstractElectronAnalyserRegionDetector,
|
|
1
|
+
from dodal.devices.electron_analyser.detector import (
|
|
2
|
+
ElectronAnalyserDetector,
|
|
4
3
|
)
|
|
5
4
|
from dodal.devices.electron_analyser.vgscienta.driver_io import (
|
|
6
5
|
VGScientaAnalyserDriverIO,
|
|
@@ -11,26 +10,13 @@ from dodal.devices.electron_analyser.vgscienta.region import (
|
|
|
11
10
|
)
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
class VGScientaRegionDetector(
|
|
15
|
-
AbstractElectronAnalyserRegionDetector[VGScientaAnalyserDriverIO, VGScientaRegion]
|
|
16
|
-
):
|
|
17
|
-
def configure_region(self):
|
|
18
|
-
# ToDo - Need to move configure plans to here and rewrite tests
|
|
19
|
-
pass
|
|
20
|
-
|
|
21
|
-
|
|
22
13
|
class VGScientaDetector(
|
|
23
|
-
|
|
24
|
-
VGScientaAnalyserDriverIO,
|
|
14
|
+
ElectronAnalyserDetector[
|
|
15
|
+
VGScientaAnalyserDriverIO,
|
|
16
|
+
VGScientaSequence,
|
|
17
|
+
VGScientaRegion,
|
|
25
18
|
]
|
|
26
19
|
):
|
|
27
|
-
def __init__(self, prefix: str, name: str):
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def _create_driver(self, prefix: str) -> VGScientaAnalyserDriverIO:
|
|
31
|
-
return VGScientaAnalyserDriverIO(prefix, "driver")
|
|
32
|
-
|
|
33
|
-
def _create_region_detector(
|
|
34
|
-
self, driver: VGScientaAnalyserDriverIO, region: VGScientaRegion
|
|
35
|
-
) -> VGScientaRegionDetector:
|
|
36
|
-
return VGScientaRegionDetector(self.name, driver, region)
|
|
20
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
21
|
+
driver = VGScientaAnalyserDriverIO(prefix)
|
|
22
|
+
super().__init__(prefix, VGScientaSequence, driver, name)
|
|
@@ -1,19 +1,29 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
1
3
|
import numpy as np
|
|
2
|
-
from ophyd_async.core import
|
|
4
|
+
from ophyd_async.core import (
|
|
5
|
+
Array1D,
|
|
6
|
+
AsyncStatus,
|
|
7
|
+
SignalR,
|
|
8
|
+
StandardReadableFormat,
|
|
9
|
+
)
|
|
10
|
+
from ophyd_async.epics.adcore import ADImageMode
|
|
3
11
|
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
4
12
|
|
|
5
13
|
from dodal.devices.electron_analyser.abstract.base_driver_io import (
|
|
6
14
|
AbstractAnalyserDriverIO,
|
|
7
15
|
)
|
|
16
|
+
from dodal.devices.electron_analyser.util import to_kinetic_energy
|
|
17
|
+
from dodal.devices.electron_analyser.vgscienta.enums import AcquisitionMode
|
|
8
18
|
from dodal.devices.electron_analyser.vgscienta.region import (
|
|
9
19
|
DetectorMode,
|
|
20
|
+
VGScientaRegion,
|
|
10
21
|
)
|
|
11
22
|
|
|
12
23
|
|
|
13
|
-
class VGScientaAnalyserDriverIO(AbstractAnalyserDriverIO):
|
|
24
|
+
class VGScientaAnalyserDriverIO(AbstractAnalyserDriverIO[VGScientaRegion]):
|
|
14
25
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
15
26
|
with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
|
|
16
|
-
self.excitation_energy_source = soft_signal_rw(str, initial_value=None)
|
|
17
27
|
# Used for setting up region data acquisition.
|
|
18
28
|
self.centre_energy = epics_signal_rw(float, prefix + "CENTRE_ENERGY")
|
|
19
29
|
self.first_x_channel = epics_signal_rw(int, prefix + "MinX")
|
|
@@ -26,7 +36,26 @@ class VGScientaAnalyserDriverIO(AbstractAnalyserDriverIO):
|
|
|
26
36
|
# Used to read detector data after acqusition.
|
|
27
37
|
self.external_io = epics_signal_r(Array1D[np.float64], prefix + "EXTIO")
|
|
28
38
|
|
|
29
|
-
super().__init__(prefix, name)
|
|
39
|
+
super().__init__(prefix, AcquisitionMode, name)
|
|
40
|
+
|
|
41
|
+
@AsyncStatus.wrap
|
|
42
|
+
async def set(self, region: VGScientaRegion):
|
|
43
|
+
await super().set(region)
|
|
44
|
+
|
|
45
|
+
excitation_energy = await self.excitation_energy.get_value()
|
|
46
|
+
centre_energy = to_kinetic_energy(
|
|
47
|
+
region.fix_energy, region.energy_mode, excitation_energy
|
|
48
|
+
)
|
|
49
|
+
await asyncio.gather(
|
|
50
|
+
self.centre_energy.set(centre_energy),
|
|
51
|
+
self.energy_step.set(region.energy_step),
|
|
52
|
+
self.first_x_channel.set(region.first_x_channel),
|
|
53
|
+
self.first_y_channel.set(region.first_y_channel),
|
|
54
|
+
self.x_channel_size.set(region.x_channel_size()),
|
|
55
|
+
self.y_channel_size.set(region.y_channel_size()),
|
|
56
|
+
self.detector_mode.set(region.detector_mode),
|
|
57
|
+
self.image_mode.set(ADImageMode.SINGLE),
|
|
58
|
+
)
|
|
30
59
|
|
|
31
60
|
def _create_energy_axis_signal(self, prefix: str) -> SignalR[Array1D[np.float64]]:
|
|
32
61
|
return epics_signal_r(Array1D[np.float64], prefix + "X_SCALE_RBV")
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from ophyd_async.core import StrictEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Status(StrictEnum):
|
|
5
|
+
READY = "Ready"
|
|
6
|
+
RUNNING = "Running"
|
|
7
|
+
COMPLETED = "Completed"
|
|
8
|
+
INVALID = "Invalid"
|
|
9
|
+
ABORTED = "Aborted"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DetectorMode(StrictEnum):
|
|
13
|
+
ADC = "ADC"
|
|
14
|
+
PULSE_COUNTING = "Pulse Counting"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AcquisitionMode(StrictEnum):
|
|
18
|
+
SWEPT = "Swept"
|
|
19
|
+
FIXED = "Fixed"
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import uuid
|
|
2
|
-
from enum import Enum
|
|
3
2
|
|
|
4
|
-
from ophyd_async.core import StrictEnum
|
|
5
3
|
from pydantic import Field
|
|
6
4
|
|
|
7
5
|
from dodal.devices.electron_analyser.abstract.base_region import (
|
|
@@ -9,38 +7,24 @@ from dodal.devices.electron_analyser.abstract.base_region import (
|
|
|
9
7
|
AbstractBaseSequence,
|
|
10
8
|
JavaToPythonModel,
|
|
11
9
|
)
|
|
10
|
+
from dodal.devices.electron_analyser.vgscienta.enums import (
|
|
11
|
+
AcquisitionMode,
|
|
12
|
+
DetectorMode,
|
|
13
|
+
Status,
|
|
14
|
+
)
|
|
12
15
|
|
|
13
16
|
|
|
14
|
-
class
|
|
15
|
-
READY = "Ready"
|
|
16
|
-
RUNNING = "Running"
|
|
17
|
-
COMPLETED = "Completed"
|
|
18
|
-
INVALID = "Invalid"
|
|
19
|
-
ABORTED = "Aborted"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class DetectorMode(StrictEnum):
|
|
23
|
-
ADC = "ADC"
|
|
24
|
-
PULSE_COUNTING = "Pulse Counting"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class AcquisitionMode(str, Enum):
|
|
28
|
-
SWEPT = "Swept"
|
|
29
|
-
FIXED = "Fixed"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class VGScientaRegion(AbstractBaseRegion):
|
|
17
|
+
class VGScientaRegion(AbstractBaseRegion[AcquisitionMode]):
|
|
33
18
|
# Override defaults of base region class
|
|
34
19
|
lens_mode: str = "Angular45"
|
|
35
20
|
pass_energy: int = 5
|
|
36
|
-
acquisition_mode:
|
|
21
|
+
acquisition_mode: AcquisitionMode = AcquisitionMode.SWEPT
|
|
37
22
|
low_energy: float = 8.0
|
|
38
23
|
high_energy: float = 10.0
|
|
39
24
|
step_time: float = 1.0
|
|
40
25
|
energy_step: float = Field(default=200.0)
|
|
41
26
|
# Specific to this class
|
|
42
27
|
id: str = Field(default=str(uuid.uuid4()), alias="region_id")
|
|
43
|
-
excitation_energy_source: str = "source1"
|
|
44
28
|
fix_energy: float = 9.0
|
|
45
29
|
total_steps: float = 13.0
|
|
46
30
|
total_time: float = 13.0
|
dodal/devices/fast_grid_scan.py
CHANGED
|
@@ -234,7 +234,7 @@ class FastGridScanCommon(StandardReadable, Flyable, ABC, Generic[ParamType]):
|
|
|
234
234
|
}
|
|
235
235
|
super().__init__(name)
|
|
236
236
|
|
|
237
|
-
def _calculate_expected_images(self, x:
|
|
237
|
+
def _calculate_expected_images(self, x: int, y: int, z: int) -> int:
|
|
238
238
|
LOGGER.info(f"Reading num of images found {x, y, z} images in each axis")
|
|
239
239
|
first_grid = x * y
|
|
240
240
|
second_grid = x * z
|