dls-dodal 1.45.0__py3-none-any.whl → 1.47.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.45.0.dist-info → dls_dodal-1.47.0.dist-info}/METADATA +2 -2
- {dls_dodal-1.45.0.dist-info → dls_dodal-1.47.0.dist-info}/RECORD +76 -64
- {dls_dodal-1.45.0.dist-info → dls_dodal-1.47.0.dist-info}/WHEEL +1 -1
- dodal/_version.py +2 -2
- dodal/beamlines/__init__.py +0 -1
- dodal/beamlines/b07.py +2 -6
- dodal/beamlines/b07_1.py +1 -3
- dodal/beamlines/i03.py +16 -19
- dodal/beamlines/i04.py +49 -17
- dodal/beamlines/i09.py +1 -3
- dodal/beamlines/i09_1.py +1 -3
- dodal/beamlines/i18.py +7 -4
- dodal/beamlines/i22.py +3 -3
- dodal/beamlines/i23.py +75 -4
- dodal/beamlines/p38.py +4 -4
- dodal/beamlines/p60.py +2 -6
- dodal/beamlines/p99.py +48 -4
- dodal/common/beamlines/beamline_parameters.py +1 -2
- dodal/common/beamlines/beamline_utils.py +5 -0
- dodal/common/data_util.py +4 -0
- dodal/devices/aperturescatterguard.py +47 -47
- dodal/devices/common_dcm.py +77 -0
- dodal/devices/current_amplifiers/struck_scaler_counter.py +1 -1
- dodal/devices/diamond_filter.py +5 -17
- dodal/devices/eiger.py +1 -1
- dodal/devices/electron_analyser/__init__.py +8 -0
- dodal/devices/electron_analyser/abstract/__init__.py +28 -0
- dodal/devices/electron_analyser/abstract/base_detector.py +210 -0
- dodal/devices/electron_analyser/abstract/base_driver_io.py +121 -0
- dodal/devices/electron_analyser/{abstract_region.py → abstract/base_region.py} +2 -9
- dodal/devices/electron_analyser/specs/__init__.py +11 -0
- dodal/devices/electron_analyser/specs/detector.py +29 -0
- dodal/devices/electron_analyser/specs/driver_io.py +64 -0
- dodal/devices/electron_analyser/{specs_region.py → specs/region.py} +1 -1
- dodal/devices/electron_analyser/types.py +6 -0
- dodal/devices/electron_analyser/util.py +13 -0
- dodal/devices/electron_analyser/vgscienta/__init__.py +12 -0
- dodal/devices/electron_analyser/vgscienta/detector.py +36 -0
- dodal/devices/electron_analyser/vgscienta/driver_io.py +39 -0
- dodal/devices/electron_analyser/{vgscienta_region.py → vgscienta/region.py} +1 -1
- dodal/devices/fast_grid_scan.py +7 -9
- dodal/devices/i03/__init__.py +3 -0
- dodal/devices/{dcm.py → i03/dcm.py} +8 -12
- dodal/devices/{undulator_dcm.py → i03/undulator_dcm.py} +6 -4
- dodal/devices/i04/__init__.py +3 -0
- dodal/devices/i04/constants.py +9 -0
- dodal/devices/i04/murko_results.py +195 -0
- dodal/devices/i10/diagnostics.py +9 -61
- dodal/devices/i13_1/merlin.py +3 -4
- dodal/devices/i13_1/merlin_controller.py +1 -1
- dodal/devices/i22/dcm.py +10 -12
- dodal/devices/i24/dcm.py +8 -17
- dodal/devices/i24/focus_mirrors.py +9 -13
- dodal/devices/i24/pilatus_metadata.py +9 -9
- dodal/devices/i24/pmac.py +19 -14
- dodal/devices/{i03 → mx_phase1}/beamstop.py +6 -12
- dodal/devices/oav/oav_calculations.py +2 -2
- dodal/devices/oav/oav_detector.py +32 -22
- dodal/devices/oav/utils.py +2 -2
- dodal/devices/p99/andor2_point.py +41 -0
- dodal/devices/positioner.py +49 -0
- dodal/devices/tetramm.py +8 -6
- dodal/devices/turbo_slit.py +2 -2
- dodal/devices/util/adjuster_plans.py +1 -1
- dodal/devices/zebra/zebra.py +4 -0
- dodal/devices/zebra/zebra_constants_mapping.py +1 -1
- dodal/devices/zocalo/__init__.py +0 -3
- dodal/devices/zocalo/zocalo_results.py +6 -32
- dodal/log.py +14 -14
- dodal/plan_stubs/data_session.py +10 -1
- dodal/plan_stubs/electron_analyser/__init__.py +3 -0
- dodal/plan_stubs/electron_analyser/{configure_controller.py → configure_driver.py} +30 -18
- dodal/plans/verify_undulator_gap.py +2 -2
- dodal/common/signal_utils.py +0 -88
- dodal/devices/electron_analyser/abstract_analyser_io.py +0 -47
- dodal/devices/electron_analyser/specs_analyser_io.py +0 -19
- dodal/devices/electron_analyser/vgscienta_analyser_io.py +0 -26
- dodal/devices/logging_ophyd_device.py +0 -17
- {dls_dodal-1.45.0.dist-info → dls_dodal-1.47.0.dist-info}/entry_points.txt +0 -0
- {dls_dodal-1.45.0.dist-info → dls_dodal-1.47.0.dist-info}/licenses/LICENSE +0 -0
- {dls_dodal-1.45.0.dist-info → dls_dodal-1.47.0.dist-info}/top_level.txt +0 -0
|
@@ -1,37 +1,44 @@
|
|
|
1
1
|
from bluesky import plan_stubs as bps
|
|
2
|
+
from bluesky.utils import MsgGenerator, plan
|
|
3
|
+
from ophyd_async.epics.adcore import ADImageMode
|
|
2
4
|
|
|
3
|
-
from dodal.
|
|
5
|
+
from dodal.common.types import MsgGenerator
|
|
6
|
+
from dodal.devices.electron_analyser.abstract import (
|
|
4
7
|
AbstractAnalyserDriverIO,
|
|
5
|
-
)
|
|
6
|
-
from dodal.devices.electron_analyser.abstract_region import (
|
|
7
8
|
AbstractBaseRegion,
|
|
8
9
|
)
|
|
9
|
-
from dodal.devices.electron_analyser.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
from dodal.devices.electron_analyser.specs_region import SpecsRegion
|
|
13
|
-
from dodal.devices.electron_analyser.vgscienta_analyser_io import (
|
|
10
|
+
from dodal.devices.electron_analyser.specs import SpecsAnalyserDriverIO, SpecsRegion
|
|
11
|
+
from dodal.devices.electron_analyser.util import to_kinetic_energy
|
|
12
|
+
from dodal.devices.electron_analyser.vgscienta import (
|
|
14
13
|
VGScientaAnalyserDriverIO,
|
|
15
|
-
)
|
|
16
|
-
from dodal.devices.electron_analyser.vgscienta_region import (
|
|
17
14
|
VGScientaRegion,
|
|
18
15
|
)
|
|
19
16
|
from dodal.log import LOGGER
|
|
20
17
|
|
|
21
18
|
|
|
19
|
+
@plan
|
|
22
20
|
def configure_analyser(
|
|
23
21
|
analyser: AbstractAnalyserDriverIO,
|
|
24
22
|
region: AbstractBaseRegion,
|
|
25
23
|
excitation_energy: float,
|
|
26
|
-
):
|
|
24
|
+
) -> MsgGenerator:
|
|
27
25
|
LOGGER.info(f'Configuring analyser with region "{region.name}"')
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
|
|
27
|
+
low_energy = to_kinetic_energy(
|
|
28
|
+
region.low_energy, region.energy_mode, excitation_energy
|
|
29
|
+
)
|
|
30
|
+
high_energy = to_kinetic_energy(
|
|
31
|
+
region.high_energy, region.energy_mode, excitation_energy
|
|
32
|
+
)
|
|
30
33
|
pass_energy_type = analyser.pass_energy_type
|
|
31
34
|
pass_energy = pass_energy_type(region.pass_energy)
|
|
35
|
+
|
|
32
36
|
# Set detector settings, wait for them all to have completed
|
|
33
37
|
# fmt: off
|
|
34
38
|
yield from bps.mv(
|
|
39
|
+
analyser.region_name, region.name,
|
|
40
|
+
analyser.energy_mode, region.energy_mode,
|
|
41
|
+
analyser.excitation_energy, excitation_energy,
|
|
35
42
|
analyser.low_energy, low_energy,
|
|
36
43
|
analyser.high_energy, high_energy,
|
|
37
44
|
analyser.slices, region.slices,
|
|
@@ -43,13 +50,14 @@ def configure_analyser(
|
|
|
43
50
|
# fmt: on
|
|
44
51
|
|
|
45
52
|
|
|
53
|
+
@plan
|
|
46
54
|
def configure_specs(
|
|
47
55
|
analyser: SpecsAnalyserDriverIO, region: SpecsRegion, excitation_energy: float
|
|
48
|
-
):
|
|
56
|
+
) -> MsgGenerator:
|
|
49
57
|
yield from configure_analyser(analyser, region, excitation_energy)
|
|
50
58
|
# fmt: off
|
|
51
59
|
yield from bps.mv(
|
|
52
|
-
analyser.
|
|
60
|
+
analyser.snapshot_values, region.values,
|
|
53
61
|
analyser.psu_mode, region.psu_mode,
|
|
54
62
|
)
|
|
55
63
|
# fmt: on
|
|
@@ -60,11 +68,14 @@ def configure_specs(
|
|
|
60
68
|
yield from bps.mv(analyser.energy_step, region.energy_step)
|
|
61
69
|
|
|
62
70
|
|
|
71
|
+
@plan
|
|
63
72
|
def configure_vgscienta(
|
|
64
73
|
analyser: VGScientaAnalyserDriverIO, region: VGScientaRegion, excitation_energy
|
|
65
|
-
):
|
|
74
|
+
) -> MsgGenerator:
|
|
66
75
|
yield from configure_analyser(analyser, region, excitation_energy)
|
|
67
|
-
centre_energy =
|
|
76
|
+
centre_energy = to_kinetic_energy(
|
|
77
|
+
region.fix_energy, region.energy_mode, excitation_energy
|
|
78
|
+
)
|
|
68
79
|
|
|
69
80
|
# fmt: off
|
|
70
81
|
yield from bps.mv(
|
|
@@ -75,6 +86,7 @@ def configure_vgscienta(
|
|
|
75
86
|
analyser.x_channel_size, region.x_channel_size(),
|
|
76
87
|
analyser.y_channel_size, region.y_channel_size(),
|
|
77
88
|
analyser.detector_mode, region.detector_mode,
|
|
78
|
-
analyser.
|
|
89
|
+
analyser.excitation_energy_source, region.excitation_energy_source,
|
|
90
|
+
analyser.image_mode, ADImageMode.SINGLE,
|
|
79
91
|
)
|
|
80
92
|
# fmt: on
|
|
@@ -2,14 +2,14 @@ from typing import Protocol, runtime_checkable
|
|
|
2
2
|
|
|
3
3
|
from bluesky import plan_stubs as bps
|
|
4
4
|
|
|
5
|
-
from dodal.devices.
|
|
5
|
+
from dodal.devices.common_dcm import BaseDCM
|
|
6
6
|
from dodal.devices.undulator import Undulator
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
@runtime_checkable
|
|
10
10
|
class CheckUndulatorDevices(Protocol):
|
|
11
11
|
undulator: Undulator
|
|
12
|
-
dcm:
|
|
12
|
+
dcm: BaseDCM
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def verify_undulator_gap(devices: CheckUndulatorDevices):
|
dodal/common/signal_utils.py
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
from collections.abc import Callable, Coroutine
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from bluesky.protocols import Reading
|
|
5
|
-
from ophyd_async.core import SignalDatatypeT, SignalR, SignalRW, SoftSignalBackend
|
|
6
|
-
|
|
7
|
-
SetHardwareType = Callable[[SignalDatatypeT], Coroutine[Any, Any, None]]
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class HardwareBackedSoftSignalBackend(SoftSignalBackend[SignalDatatypeT]):
|
|
11
|
-
def __init__(
|
|
12
|
-
self,
|
|
13
|
-
get_from_hardware_func: Callable[[], Coroutine[Any, Any, SignalDatatypeT]],
|
|
14
|
-
set_to_hardware_func: SetHardwareType | None = None,
|
|
15
|
-
*args,
|
|
16
|
-
**kwargs,
|
|
17
|
-
) -> None:
|
|
18
|
-
self.get_from_hardware_func = get_from_hardware_func
|
|
19
|
-
self.set_to_hardware_func = set_to_hardware_func
|
|
20
|
-
super().__init__(*args, **kwargs)
|
|
21
|
-
|
|
22
|
-
async def _update_value(self):
|
|
23
|
-
new_value = await self.get_from_hardware_func()
|
|
24
|
-
self.set_value(new_value)
|
|
25
|
-
|
|
26
|
-
async def get_reading(self) -> Reading:
|
|
27
|
-
await self._update_value()
|
|
28
|
-
return await super().get_reading()
|
|
29
|
-
|
|
30
|
-
async def get_value(self) -> SignalDatatypeT:
|
|
31
|
-
await self._update_value()
|
|
32
|
-
return await super().get_value()
|
|
33
|
-
|
|
34
|
-
async def put(self, value: SignalDatatypeT | None, wait: bool) -> None:
|
|
35
|
-
if self.set_to_hardware_func:
|
|
36
|
-
write_value = self.initial_value if value is None else value
|
|
37
|
-
await self.set_to_hardware_func(write_value)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def create_rw_hardware_backed_soft_signal(
|
|
41
|
-
datatype: type[SignalDatatypeT],
|
|
42
|
-
get_from_hardware_func: Callable[[], Coroutine[Any, Any, SignalDatatypeT]],
|
|
43
|
-
set_to_hardware_func: SetHardwareType,
|
|
44
|
-
units: str | None = None,
|
|
45
|
-
precision: int | None = None,
|
|
46
|
-
):
|
|
47
|
-
"""Creates a soft signal that, when read will call the function passed into
|
|
48
|
-
`get_from_hardware_func` and return this. When set it will call `set_to_hardware_func`
|
|
49
|
-
and send something to the hardware.
|
|
50
|
-
|
|
51
|
-
This will allow you to make soft signals derived from arbitrary hardware signals.
|
|
52
|
-
However, calling subscribe on this signal does not give you a sensible value. See https://github.com/bluesky/ophyd-async/issues/525
|
|
53
|
-
for a more full solution.
|
|
54
|
-
"""
|
|
55
|
-
return SignalRW(
|
|
56
|
-
backend=HardwareBackedSoftSignalBackend(
|
|
57
|
-
get_from_hardware_func,
|
|
58
|
-
set_to_hardware_func,
|
|
59
|
-
datatype,
|
|
60
|
-
units=units,
|
|
61
|
-
precision=precision,
|
|
62
|
-
)
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def create_r_hardware_backed_soft_signal(
|
|
67
|
-
datatype: type[SignalDatatypeT],
|
|
68
|
-
get_from_hardware_func: Callable[[], Coroutine[Any, Any, SignalDatatypeT]],
|
|
69
|
-
units: str | None = None,
|
|
70
|
-
precision: int | None = None,
|
|
71
|
-
):
|
|
72
|
-
"""Creates a soft signal that, when read will call the function passed into
|
|
73
|
-
`get_from_hardware_func` and return this.
|
|
74
|
-
|
|
75
|
-
This will allow you to make soft signals derived from arbitrary hardware signals.
|
|
76
|
-
However, calling subscribe on this signal does not give you a sensible value and
|
|
77
|
-
the signal is currently read only. See https://github.com/bluesky/ophyd-async/issues/525
|
|
78
|
-
for a more full solution.
|
|
79
|
-
"""
|
|
80
|
-
return SignalR(
|
|
81
|
-
backend=HardwareBackedSoftSignalBackend(
|
|
82
|
-
get_from_hardware_func,
|
|
83
|
-
None,
|
|
84
|
-
datatype,
|
|
85
|
-
units=units,
|
|
86
|
-
precision=precision,
|
|
87
|
-
)
|
|
88
|
-
)
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import TypeVar
|
|
3
|
-
|
|
4
|
-
from ophyd_async.core import StandardReadable
|
|
5
|
-
from ophyd_async.epics.core import epics_signal_rw
|
|
6
|
-
|
|
7
|
-
from dodal.devices.electron_analyser.abstract_region import EnergyMode
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class AbstractAnalyserDriverIO(ABC, StandardReadable):
|
|
11
|
-
"""
|
|
12
|
-
Generic device to configure electron analyser with new region settings.
|
|
13
|
-
Electron analysers should inherit from this class for further specialisation.
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
def __init__(self, prefix: str, name: str = "") -> None:
|
|
17
|
-
with self.add_children_as_readables():
|
|
18
|
-
self.low_energy = epics_signal_rw(float, prefix + "LOW_ENERGY")
|
|
19
|
-
self.high_energy = epics_signal_rw(float, prefix + "HIGH_ENERGY")
|
|
20
|
-
self.slices = epics_signal_rw(int, prefix + "SLICES")
|
|
21
|
-
self.lens_mode = epics_signal_rw(str, prefix + "LENS_MODE")
|
|
22
|
-
self.pass_energy = epics_signal_rw(
|
|
23
|
-
self.pass_energy_type, prefix + "PASS_ENERGY"
|
|
24
|
-
)
|
|
25
|
-
self.energy_step = epics_signal_rw(float, prefix + "STEP_SIZE")
|
|
26
|
-
self.iterations = epics_signal_rw(int, prefix + "NumExposures")
|
|
27
|
-
self.acquisition_mode = epics_signal_rw(str, prefix + "ACQ_MODE")
|
|
28
|
-
|
|
29
|
-
super().__init__(name)
|
|
30
|
-
|
|
31
|
-
def to_kinetic_energy(
|
|
32
|
-
self, value: float, excitation_energy: float, mode: EnergyMode
|
|
33
|
-
) -> float:
|
|
34
|
-
return excitation_energy - value if mode == EnergyMode.BINDING else value
|
|
35
|
-
|
|
36
|
-
@property
|
|
37
|
-
@abstractmethod
|
|
38
|
-
def pass_energy_type(self) -> type:
|
|
39
|
-
"""
|
|
40
|
-
Return the type the pass_energy should be. Each one is unfortunately different
|
|
41
|
-
for the underlying analyser software and cannot be changed on epics side.
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
TAbstractAnalyserDriverIO = TypeVar(
|
|
46
|
-
"TAbstractAnalyserDriverIO", bound=AbstractAnalyserDriverIO
|
|
47
|
-
)
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
from ophyd_async.epics.core import epics_signal_rw
|
|
2
|
-
|
|
3
|
-
from dodal.devices.electron_analyser.abstract_analyser_io import (
|
|
4
|
-
AbstractAnalyserDriverIO,
|
|
5
|
-
)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class SpecsAnalyserDriverIO(AbstractAnalyserDriverIO):
|
|
9
|
-
def __init__(self, prefix: str, name: str = "") -> None:
|
|
10
|
-
with self.add_children_as_readables():
|
|
11
|
-
self.psu_mode = epics_signal_rw(str, prefix + "SCAN_RANGE")
|
|
12
|
-
self.values = epics_signal_rw(int, prefix + "VALUES")
|
|
13
|
-
self.centre_energy = epics_signal_rw(float, prefix + "KINETIC_ENERGY")
|
|
14
|
-
|
|
15
|
-
super().__init__(prefix, name)
|
|
16
|
-
|
|
17
|
-
@property
|
|
18
|
-
def pass_energy_type(self) -> type:
|
|
19
|
-
return float
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
from ophyd_async.epics.core import epics_signal_rw
|
|
2
|
-
|
|
3
|
-
from dodal.devices.electron_analyser.abstract_analyser_io import (
|
|
4
|
-
AbstractAnalyserDriverIO,
|
|
5
|
-
)
|
|
6
|
-
from dodal.devices.electron_analyser.vgscienta_region import (
|
|
7
|
-
DetectorMode,
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class VGScientaAnalyserDriverIO(AbstractAnalyserDriverIO):
|
|
12
|
-
def __init__(self, prefix: str, name: str = "") -> None:
|
|
13
|
-
with self.add_children_as_readables():
|
|
14
|
-
self.centre_energy = epics_signal_rw(float, prefix + "CENTRE_ENERGY")
|
|
15
|
-
self.first_x_channel = epics_signal_rw(int, prefix + "MinX")
|
|
16
|
-
self.first_y_channel = epics_signal_rw(int, prefix + "MinY")
|
|
17
|
-
self.x_channel_size = epics_signal_rw(int, prefix + "SizeX")
|
|
18
|
-
self.y_channel_size = epics_signal_rw(int, prefix + "SizeY")
|
|
19
|
-
self.detector_mode = epics_signal_rw(DetectorMode, prefix + "DETECTOR_MODE")
|
|
20
|
-
self.image_mode = epics_signal_rw(str, prefix + "ImageMode")
|
|
21
|
-
|
|
22
|
-
super().__init__(prefix, name)
|
|
23
|
-
|
|
24
|
-
@property
|
|
25
|
-
def pass_energy_type(self) -> type:
|
|
26
|
-
return str
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
from ophyd import Device
|
|
2
|
-
from ophyd.log import logger as ophyd_logger
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class InfoLoggingDevice(Device):
|
|
6
|
-
def wait_for_connection(self, all_signals=False, timeout=2.0):
|
|
7
|
-
class_name = self.__class__.__name__
|
|
8
|
-
ophyd_logger.info(
|
|
9
|
-
f"{class_name} waiting for connection, {'not' if all_signals else ''} waiting for all signals, timeout = {timeout}s.",
|
|
10
|
-
)
|
|
11
|
-
try:
|
|
12
|
-
super().wait_for_connection(all_signals, timeout)
|
|
13
|
-
except TimeoutError as e:
|
|
14
|
-
ophyd_logger.error(f"{class_name} failed to connect.", exc_info=True)
|
|
15
|
-
raise e
|
|
16
|
-
else:
|
|
17
|
-
ophyd_logger.info(f"{class_name} connected.")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|