ophyd-async 0.4.0__py3-none-any.whl → 0.5.1__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.
- ophyd_async/_version.py +2 -2
- ophyd_async/core/__init__.py +86 -73
- ophyd_async/core/{detector.py → _detector.py} +42 -36
- ophyd_async/core/{device.py → _device.py} +1 -1
- ophyd_async/core/{device_save_loader.py → _device_save_loader.py} +3 -3
- ophyd_async/core/{flyer.py → _flyer.py} +6 -8
- ophyd_async/{epics/areadetector/writers/general_hdffile.py → core/_hdf_dataset.py} +4 -8
- ophyd_async/{log.py → core/_log.py} +11 -3
- ophyd_async/core/{mock_signal_backend.py → _mock_signal_backend.py} +3 -3
- ophyd_async/core/{mock_signal_utils.py → _mock_signal_utils.py} +7 -7
- ophyd_async/{protocols.py → core/_protocol.py} +1 -1
- ophyd_async/core/_providers.py +24 -37
- ophyd_async/core/{standard_readable.py → _readable.py} +6 -16
- ophyd_async/core/{signal.py → _signal.py} +79 -35
- ophyd_async/core/{signal_backend.py → _signal_backend.py} +4 -13
- ophyd_async/core/{soft_signal_backend.py → _soft_signal_backend.py} +3 -12
- ophyd_async/core/{async_status.py → _status.py} +3 -11
- ophyd_async/epics/adaravis/__init__.py +9 -0
- ophyd_async/epics/{areadetector/aravis.py → adaravis/_aravis.py} +9 -11
- ophyd_async/epics/{areadetector/controllers/aravis_controller.py → adaravis/_aravis_controller.py} +7 -10
- ophyd_async/epics/{areadetector/drivers/aravis_driver.py → adaravis/_aravis_io.py} +6 -3
- ophyd_async/epics/adcore/__init__.py +47 -0
- ophyd_async/epics/adcore/_core_io.py +138 -0
- ophyd_async/epics/{areadetector/drivers/ad_base.py → adcore/_core_logic.py} +16 -52
- ophyd_async/epics/{areadetector/writers/hdf_writer.py → adcore/_hdf_writer.py} +54 -29
- ophyd_async/epics/{areadetector/single_trigger_det.py → adcore/_single_trigger.py} +5 -6
- ophyd_async/epics/adcore/_utils.py +132 -0
- ophyd_async/epics/adkinetix/__init__.py +9 -0
- ophyd_async/epics/{areadetector/kinetix.py → adkinetix/_kinetix.py} +9 -11
- ophyd_async/epics/{areadetector/controllers/kinetix_controller.py → adkinetix/_kinetix_controller.py} +6 -9
- ophyd_async/epics/{areadetector/drivers/kinetix_driver.py → adkinetix/_kinetix_io.py} +9 -5
- ophyd_async/epics/adpilatus/__init__.py +11 -0
- ophyd_async/epics/{areadetector/pilatus.py → adpilatus/_pilatus.py} +10 -14
- ophyd_async/epics/{areadetector/controllers/pilatus_controller.py → adpilatus/_pilatus_controller.py} +15 -17
- ophyd_async/epics/{areadetector/drivers/pilatus_driver.py → adpilatus/_pilatus_io.py} +6 -4
- ophyd_async/epics/adsimdetector/__init__.py +7 -0
- ophyd_async/epics/{demo/demo_ad_sim_detector.py → adsimdetector/_sim.py} +10 -11
- ophyd_async/epics/{areadetector/controllers/ad_sim_controller.py → adsimdetector/_sim_controller.py} +8 -14
- ophyd_async/epics/advimba/__init__.py +9 -0
- ophyd_async/epics/{areadetector/vimba.py → advimba/_vimba.py} +9 -9
- ophyd_async/epics/{areadetector/controllers/vimba_controller.py → advimba/_vimba_controller.py} +9 -17
- ophyd_async/epics/{areadetector/drivers/vimba_driver.py → advimba/_vimba_io.py} +11 -8
- ophyd_async/epics/demo/__init__.py +9 -132
- ophyd_async/epics/demo/_mover.py +97 -0
- ophyd_async/epics/demo/_sensor.py +36 -0
- ophyd_async/epics/{motion/motor.py → motor.py} +28 -14
- ophyd_async/epics/pvi/__init__.py +2 -2
- ophyd_async/epics/pvi/{pvi.py → _pvi.py} +17 -14
- ophyd_async/epics/signal/__init__.py +7 -1
- ophyd_async/epics/{_backend → signal}/_aioca.py +15 -7
- ophyd_async/epics/{_backend/common.py → signal/_common.py} +2 -2
- ophyd_async/epics/signal/_epics_transport.py +3 -3
- ophyd_async/epics/{_backend → signal}/_p4p.py +18 -14
- ophyd_async/epics/signal/{signal.py → _signal.py} +10 -9
- ophyd_async/fastcs/odin/__init__.py +0 -0
- ophyd_async/{panda → fastcs/panda}/__init__.py +20 -15
- ophyd_async/{panda/_common_blocks.py → fastcs/panda/_block.py} +5 -3
- ophyd_async/{panda/_panda_controller.py → fastcs/panda/_control.py} +2 -1
- ophyd_async/{panda → fastcs/panda}/_hdf_panda.py +5 -10
- ophyd_async/{panda → fastcs/panda}/_trigger.py +3 -7
- ophyd_async/{panda/writers/_hdf_writer.py → fastcs/panda/_writer.py} +36 -28
- ophyd_async/plan_stubs/__init__.py +5 -2
- ophyd_async/plan_stubs/{ensure_connected.py → _ensure_connected.py} +1 -2
- ophyd_async/plan_stubs/{fly.py → _fly.py} +13 -9
- ophyd_async/plan_stubs/_nd_attributes.py +63 -0
- ophyd_async/sim/__init__.py +0 -11
- ophyd_async/sim/demo/__init__.py +18 -2
- ophyd_async/sim/demo/_pattern_detector/__init__.py +13 -0
- ophyd_async/sim/{sim_pattern_generator.py → demo/_pattern_detector/_pattern_detector.py} +8 -8
- ophyd_async/sim/{sim_pattern_detector_control.py → demo/_pattern_detector/_pattern_detector_controller.py} +9 -7
- ophyd_async/sim/{sim_pattern_detector_writer.py → demo/_pattern_detector/_pattern_detector_writer.py} +4 -4
- ophyd_async/sim/{pattern_generator.py → demo/_pattern_detector/_pattern_generator.py} +13 -11
- ophyd_async/sim/demo/{sim_motor.py → _sim_motor.py} +7 -5
- ophyd_async/sim/testing/__init__.py +0 -0
- ophyd_async/tango/__init__.py +0 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.dist-info}/METADATA +46 -44
- ophyd_async-0.5.1.dist-info/RECORD +90 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.dist-info}/WHEEL +1 -1
- ophyd_async/epics/areadetector/__init__.py +0 -23
- ophyd_async/epics/areadetector/controllers/__init__.py +0 -5
- ophyd_async/epics/areadetector/drivers/__init__.py +0 -23
- ophyd_async/epics/areadetector/utils.py +0 -104
- ophyd_async/epics/areadetector/writers/__init__.py +0 -5
- ophyd_async/epics/areadetector/writers/nd_file_hdf.py +0 -43
- ophyd_async/epics/areadetector/writers/nd_plugin.py +0 -68
- ophyd_async/epics/motion/__init__.py +0 -3
- ophyd_async/panda/writers/__init__.py +0 -3
- ophyd_async-0.4.0.dist-info/RECORD +0 -84
- /ophyd_async/core/{utils.py → _utils.py} +0 -0
- /ophyd_async/{epics/_backend → fastcs}/__init__.py +0 -0
- /ophyd_async/{panda → fastcs/panda}/_table.py +0 -0
- /ophyd_async/{panda → fastcs/panda}/_utils.py +0 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.dist-info}/LICENSE +0 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.dist-info}/entry_points.txt +0 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
|
-
from ophyd_async.epics
|
|
4
|
-
|
|
5
|
-
from .ad_base import ADBase
|
|
3
|
+
from ophyd_async.epics import adcore
|
|
4
|
+
from ophyd_async.epics.signal import epics_signal_rw_rbv
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class KinetixTriggerMode(str, Enum):
|
|
@@ -15,13 +14,18 @@ class KinetixReadoutMode(str, Enum):
|
|
|
15
14
|
sensitivity = 1
|
|
16
15
|
speed = 2
|
|
17
16
|
dynamic_range = 3
|
|
17
|
+
sub_electron = 4
|
|
18
|
+
|
|
18
19
|
|
|
20
|
+
class KinetixDriverIO(adcore.ADBaseIO):
|
|
21
|
+
"""This mirrors the interface provided by ADKinetix/db/ADKinetix.template."""
|
|
19
22
|
|
|
20
|
-
class KinetixDriver(ADBase):
|
|
21
23
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
22
24
|
# self.pixel_format = epics_signal_rw_rbv(PixelFormat, prefix + "PixelFormat")
|
|
23
25
|
self.trigger_mode = epics_signal_rw_rbv(
|
|
24
26
|
KinetixTriggerMode, prefix + "TriggerMode"
|
|
25
27
|
)
|
|
26
|
-
self.
|
|
28
|
+
self.readout_port_idx = epics_signal_rw_rbv(
|
|
29
|
+
KinetixReadoutMode, prefix + "ReadoutPortIdx"
|
|
30
|
+
)
|
|
27
31
|
super().__init__(prefix, name)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from ._pilatus import PilatusDetector, PilatusReadoutTime
|
|
2
|
+
from ._pilatus_controller import PilatusController
|
|
3
|
+
from ._pilatus_io import PilatusDriverIO, PilatusTriggerMode
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"PilatusDetector",
|
|
7
|
+
"PilatusReadoutTime",
|
|
8
|
+
"PilatusController",
|
|
9
|
+
"PilatusDriverIO",
|
|
10
|
+
"PilatusTriggerMode",
|
|
11
|
+
]
|
|
@@ -2,15 +2,11 @@ from enum import Enum
|
|
|
2
2
|
|
|
3
3
|
from bluesky.protocols import Hints
|
|
4
4
|
|
|
5
|
-
from ophyd_async.core import PathProvider
|
|
6
|
-
from ophyd_async.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
from ophyd_async.epics.areadetector.drivers.ad_base import ADBaseShapeProvider
|
|
11
|
-
from ophyd_async.epics.areadetector.drivers.pilatus_driver import PilatusDriver
|
|
12
|
-
from ophyd_async.epics.areadetector.writers.hdf_writer import HDFWriter
|
|
13
|
-
from ophyd_async.epics.areadetector.writers.nd_file_hdf import NDFileHDF
|
|
5
|
+
from ophyd_async.core import PathProvider, StandardDetector
|
|
6
|
+
from ophyd_async.epics import adcore
|
|
7
|
+
|
|
8
|
+
from ._pilatus_controller import PilatusController
|
|
9
|
+
from ._pilatus_io import PilatusDriverIO
|
|
14
10
|
|
|
15
11
|
|
|
16
12
|
#: Cite: https://media.dectris.com/User_Manual-PILATUS2-V1_4.pdf
|
|
@@ -31,7 +27,7 @@ class PilatusDetector(StandardDetector):
|
|
|
31
27
|
"""A Pilatus StandardDetector writing HDF files"""
|
|
32
28
|
|
|
33
29
|
_controller: PilatusController
|
|
34
|
-
_writer:
|
|
30
|
+
_writer: adcore.ADHDFWriter
|
|
35
31
|
|
|
36
32
|
def __init__(
|
|
37
33
|
self,
|
|
@@ -42,16 +38,16 @@ class PilatusDetector(StandardDetector):
|
|
|
42
38
|
hdf_suffix: str = "HDF1:",
|
|
43
39
|
name: str = "",
|
|
44
40
|
):
|
|
45
|
-
self.drv =
|
|
46
|
-
self.hdf =
|
|
41
|
+
self.drv = PilatusDriverIO(prefix + drv_suffix)
|
|
42
|
+
self.hdf = adcore.NDFileHDFIO(prefix + hdf_suffix)
|
|
47
43
|
|
|
48
44
|
super().__init__(
|
|
49
45
|
PilatusController(self.drv, readout_time=readout_time.value),
|
|
50
|
-
|
|
46
|
+
adcore.ADHDFWriter(
|
|
51
47
|
self.hdf,
|
|
52
48
|
path_provider,
|
|
53
49
|
lambda: self.name,
|
|
54
|
-
ADBaseShapeProvider(self.drv),
|
|
50
|
+
adcore.ADBaseShapeProvider(self.drv),
|
|
55
51
|
),
|
|
56
52
|
config_sigs=(self.drv.acquire_time,),
|
|
57
53
|
name=name,
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
|
-
from ophyd_async.core import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
from ophyd_async.core import (
|
|
5
|
+
DEFAULT_TIMEOUT,
|
|
6
|
+
AsyncStatus,
|
|
7
|
+
DetectorControl,
|
|
8
|
+
DetectorTrigger,
|
|
9
|
+
wait_for_value,
|
|
10
10
|
)
|
|
11
|
-
from ophyd_async.epics
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
)
|
|
15
|
-
from ophyd_async.epics.areadetector.utils import ImageMode, stop_busy_record
|
|
11
|
+
from ophyd_async.epics import adcore
|
|
12
|
+
|
|
13
|
+
from ._pilatus_io import PilatusDriverIO, PilatusTriggerMode
|
|
16
14
|
|
|
17
15
|
|
|
18
16
|
class PilatusController(DetectorControl):
|
|
@@ -24,7 +22,7 @@ class PilatusController(DetectorControl):
|
|
|
24
22
|
|
|
25
23
|
def __init__(
|
|
26
24
|
self,
|
|
27
|
-
driver:
|
|
25
|
+
driver: PilatusDriverIO,
|
|
28
26
|
readout_time: float,
|
|
29
27
|
) -> None:
|
|
30
28
|
self._drv = driver
|
|
@@ -40,23 +38,23 @@ class PilatusController(DetectorControl):
|
|
|
40
38
|
exposure: Optional[float] = None,
|
|
41
39
|
) -> AsyncStatus:
|
|
42
40
|
if exposure is not None:
|
|
43
|
-
await set_exposure_time_and_acquire_period_if_supplied(
|
|
41
|
+
await adcore.set_exposure_time_and_acquire_period_if_supplied(
|
|
44
42
|
self, self._drv, exposure
|
|
45
43
|
)
|
|
46
44
|
await asyncio.gather(
|
|
47
45
|
self._drv.trigger_mode.set(self._get_trigger_mode(trigger)),
|
|
48
46
|
self._drv.num_images.set(999_999 if num == 0 else num),
|
|
49
|
-
self._drv.image_mode.set(ImageMode.multiple),
|
|
47
|
+
self._drv.image_mode.set(adcore.ImageMode.multiple),
|
|
50
48
|
)
|
|
51
49
|
|
|
52
50
|
# Standard arm the detector and wait for the acquire PV to be True
|
|
53
|
-
idle_status = await start_acquiring_driver_and_ensure_status(self._drv)
|
|
51
|
+
idle_status = await adcore.start_acquiring_driver_and_ensure_status(self._drv)
|
|
54
52
|
|
|
55
53
|
# The pilatus has an additional PV that goes True when the camserver
|
|
56
54
|
# is actually ready. Should wait for that too or we risk dropping
|
|
57
55
|
# a frame
|
|
58
56
|
await wait_for_value(
|
|
59
|
-
self._drv.
|
|
57
|
+
self._drv.armed,
|
|
60
58
|
True,
|
|
61
59
|
timeout=DEFAULT_TIMEOUT,
|
|
62
60
|
)
|
|
@@ -74,4 +72,4 @@ class PilatusController(DetectorControl):
|
|
|
74
72
|
return cls._supported_trigger_types[trigger]
|
|
75
73
|
|
|
76
74
|
async def disarm(self):
|
|
77
|
-
await stop_busy_record(self._drv.acquire, False, timeout=1)
|
|
75
|
+
await adcore.stop_busy_record(self._drv.acquire, False, timeout=1)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from .
|
|
3
|
+
from ophyd_async.epics import adcore
|
|
4
|
+
from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw_rbv
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class PilatusTriggerMode(str, Enum):
|
|
@@ -12,10 +12,12 @@ class PilatusTriggerMode(str, Enum):
|
|
|
12
12
|
alignment = "Alignment"
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class
|
|
15
|
+
class PilatusDriverIO(adcore.ADBaseIO):
|
|
16
|
+
"""This mirrors the interface provided by ADPilatus/db/pilatus.template."""
|
|
17
|
+
|
|
16
18
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
17
19
|
self.trigger_mode = epics_signal_rw_rbv(
|
|
18
20
|
PilatusTriggerMode, prefix + "TriggerMode"
|
|
19
21
|
)
|
|
20
|
-
self.
|
|
22
|
+
self.armed = epics_signal_r(bool, prefix + "Armed")
|
|
21
23
|
super().__init__(prefix, name)
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
from typing import Sequence
|
|
2
2
|
|
|
3
3
|
from ophyd_async.core import PathProvider, SignalR, StandardDetector
|
|
4
|
+
from ophyd_async.epics import adcore
|
|
4
5
|
|
|
5
|
-
from
|
|
6
|
-
from ..areadetector.drivers import ADBase, ADBaseShapeProvider
|
|
7
|
-
from ..areadetector.writers import HDFWriter, NDFileHDF
|
|
6
|
+
from ._sim_controller import SimController
|
|
8
7
|
|
|
9
8
|
|
|
10
|
-
class
|
|
11
|
-
_controller:
|
|
12
|
-
_writer:
|
|
9
|
+
class SimDetector(StandardDetector):
|
|
10
|
+
_controller: SimController
|
|
11
|
+
_writer: adcore.ADHDFWriter
|
|
13
12
|
|
|
14
13
|
def __init__(
|
|
15
14
|
self,
|
|
16
|
-
drv:
|
|
17
|
-
hdf:
|
|
15
|
+
drv: adcore.ADBaseIO,
|
|
16
|
+
hdf: adcore.NDFileHDFIO,
|
|
18
17
|
path_provider: PathProvider,
|
|
19
18
|
name: str = "",
|
|
20
19
|
config_sigs: Sequence[SignalR] = (),
|
|
@@ -23,12 +22,12 @@ class DemoADSimDetector(StandardDetector):
|
|
|
23
22
|
self.hdf = hdf
|
|
24
23
|
|
|
25
24
|
super().__init__(
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
SimController(self.drv),
|
|
26
|
+
adcore.ADHDFWriter(
|
|
28
27
|
self.hdf,
|
|
29
28
|
path_provider,
|
|
30
29
|
lambda: self.name,
|
|
31
|
-
ADBaseShapeProvider(self.drv),
|
|
30
|
+
adcore.ADBaseShapeProvider(self.drv),
|
|
32
31
|
),
|
|
33
32
|
config_sigs=config_sigs,
|
|
34
33
|
name=name,
|
ophyd_async/epics/{areadetector/controllers/ad_sim_controller.py → adsimdetector/_sim_controller.py}
RENAMED
|
@@ -7,20 +7,14 @@ from ophyd_async.core import (
|
|
|
7
7
|
DetectorControl,
|
|
8
8
|
DetectorTrigger,
|
|
9
9
|
)
|
|
10
|
-
|
|
11
|
-
from ..drivers.ad_base import (
|
|
12
|
-
DEFAULT_GOOD_STATES,
|
|
13
|
-
ADBase,
|
|
14
|
-
DetectorState,
|
|
15
|
-
ImageMode,
|
|
16
|
-
start_acquiring_driver_and_ensure_status,
|
|
17
|
-
)
|
|
18
|
-
from ..utils import stop_busy_record
|
|
10
|
+
from ophyd_async.epics import adcore
|
|
19
11
|
|
|
20
12
|
|
|
21
|
-
class
|
|
13
|
+
class SimController(DetectorControl):
|
|
22
14
|
def __init__(
|
|
23
|
-
self,
|
|
15
|
+
self,
|
|
16
|
+
driver: adcore.ADBaseIO,
|
|
17
|
+
good_states: Set[adcore.DetectorState] = set(adcore.DEFAULT_GOOD_STATES),
|
|
24
18
|
) -> None:
|
|
25
19
|
self.driver = driver
|
|
26
20
|
self.good_states = good_states
|
|
@@ -40,13 +34,13 @@ class ADSimController(DetectorControl):
|
|
|
40
34
|
frame_timeout = DEFAULT_TIMEOUT + await self.driver.acquire_time.get_value()
|
|
41
35
|
await asyncio.gather(
|
|
42
36
|
self.driver.num_images.set(num),
|
|
43
|
-
self.driver.image_mode.set(ImageMode.multiple),
|
|
37
|
+
self.driver.image_mode.set(adcore.ImageMode.multiple),
|
|
44
38
|
)
|
|
45
|
-
return await start_acquiring_driver_and_ensure_status(
|
|
39
|
+
return await adcore.start_acquiring_driver_and_ensure_status(
|
|
46
40
|
self.driver, good_states=self.good_states, timeout=frame_timeout
|
|
47
41
|
)
|
|
48
42
|
|
|
49
43
|
async def disarm(self):
|
|
50
44
|
# We can't use caput callback as we already used it in arm() and we can't have
|
|
51
45
|
# 2 or they will deadlock
|
|
52
|
-
await stop_busy_record(self.driver.acquire, False, timeout=1)
|
|
46
|
+
await adcore.stop_busy_record(self.driver.acquire, False, timeout=1)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from bluesky.protocols import HasHints, Hints
|
|
2
2
|
|
|
3
3
|
from ophyd_async.core import PathProvider, StandardDetector
|
|
4
|
-
from ophyd_async.epics
|
|
5
|
-
|
|
6
|
-
from
|
|
7
|
-
from
|
|
4
|
+
from ophyd_async.epics import adcore
|
|
5
|
+
|
|
6
|
+
from ._vimba_controller import VimbaController
|
|
7
|
+
from ._vimba_io import VimbaDriverIO
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class VimbaDetector(StandardDetector, HasHints):
|
|
@@ -13,7 +13,7 @@ class VimbaDetector(StandardDetector, HasHints):
|
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
_controller: VimbaController
|
|
16
|
-
_writer:
|
|
16
|
+
_writer: adcore.ADHDFWriter
|
|
17
17
|
|
|
18
18
|
def __init__(
|
|
19
19
|
self,
|
|
@@ -23,16 +23,16 @@ class VimbaDetector(StandardDetector, HasHints):
|
|
|
23
23
|
hdf_suffix="HDF1:",
|
|
24
24
|
name="",
|
|
25
25
|
):
|
|
26
|
-
self.drv =
|
|
27
|
-
self.hdf =
|
|
26
|
+
self.drv = VimbaDriverIO(prefix + drv_suffix)
|
|
27
|
+
self.hdf = adcore.NDFileHDFIO(prefix + hdf_suffix)
|
|
28
28
|
|
|
29
29
|
super().__init__(
|
|
30
30
|
VimbaController(self.drv),
|
|
31
|
-
|
|
31
|
+
adcore.ADHDFWriter(
|
|
32
32
|
self.hdf,
|
|
33
33
|
path_provider,
|
|
34
34
|
lambda: self.name,
|
|
35
|
-
ADBaseShapeProvider(self.drv),
|
|
35
|
+
adcore.ADBaseShapeProvider(self.drv),
|
|
36
36
|
),
|
|
37
37
|
config_sigs=(self.drv.acquire_time,),
|
|
38
38
|
name=name,
|
ophyd_async/epics/{areadetector/controllers/vimba_controller.py → advimba/_vimba_controller.py}
RENAMED
|
@@ -2,17 +2,9 @@ import asyncio
|
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
4
|
from ophyd_async.core import AsyncStatus, DetectorControl, DetectorTrigger
|
|
5
|
-
from ophyd_async.epics
|
|
6
|
-
start_acquiring_driver_and_ensure_status,
|
|
7
|
-
)
|
|
5
|
+
from ophyd_async.epics import adcore
|
|
8
6
|
|
|
9
|
-
from
|
|
10
|
-
VimbaDriver,
|
|
11
|
-
VimbaExposeOutMode,
|
|
12
|
-
VimbaOnOff,
|
|
13
|
-
VimbaTriggerSource,
|
|
14
|
-
)
|
|
15
|
-
from ..utils import ImageMode, stop_busy_record
|
|
7
|
+
from ._vimba_io import VimbaDriverIO, VimbaExposeOutMode, VimbaOnOff, VimbaTriggerSource
|
|
16
8
|
|
|
17
9
|
TRIGGER_MODE = {
|
|
18
10
|
DetectorTrigger.internal: VimbaOnOff.off,
|
|
@@ -32,7 +24,7 @@ EXPOSE_OUT_MODE = {
|
|
|
32
24
|
class VimbaController(DetectorControl):
|
|
33
25
|
def __init__(
|
|
34
26
|
self,
|
|
35
|
-
driver:
|
|
27
|
+
driver: VimbaDriverIO,
|
|
36
28
|
) -> None:
|
|
37
29
|
self._drv = driver
|
|
38
30
|
|
|
@@ -47,9 +39,9 @@ class VimbaController(DetectorControl):
|
|
|
47
39
|
) -> AsyncStatus:
|
|
48
40
|
await asyncio.gather(
|
|
49
41
|
self._drv.trigger_mode.set(TRIGGER_MODE[trigger]),
|
|
50
|
-
self._drv.
|
|
42
|
+
self._drv.exposure_mode.set(EXPOSE_OUT_MODE[trigger]),
|
|
51
43
|
self._drv.num_images.set(num),
|
|
52
|
-
self._drv.image_mode.set(ImageMode.multiple),
|
|
44
|
+
self._drv.image_mode.set(adcore.ImageMode.multiple),
|
|
53
45
|
)
|
|
54
46
|
if exposure is not None and trigger not in [
|
|
55
47
|
DetectorTrigger.variable_gate,
|
|
@@ -57,10 +49,10 @@ class VimbaController(DetectorControl):
|
|
|
57
49
|
]:
|
|
58
50
|
await self._drv.acquire_time.set(exposure)
|
|
59
51
|
if trigger != DetectorTrigger.internal:
|
|
60
|
-
self._drv.
|
|
52
|
+
self._drv.trigger_source.set(VimbaTriggerSource.line1)
|
|
61
53
|
else:
|
|
62
|
-
self._drv.
|
|
63
|
-
return await start_acquiring_driver_and_ensure_status(self._drv)
|
|
54
|
+
self._drv.trigger_source.set(VimbaTriggerSource.freerun)
|
|
55
|
+
return await adcore.start_acquiring_driver_and_ensure_status(self._drv)
|
|
64
56
|
|
|
65
57
|
async def disarm(self):
|
|
66
|
-
await stop_busy_record(self._drv.acquire, False, timeout=1)
|
|
58
|
+
await adcore.stop_busy_record(self._drv.acquire, False, timeout=1)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
|
-
from ophyd_async.epics
|
|
4
|
-
|
|
5
|
-
from .ad_base import ADBase
|
|
3
|
+
from ophyd_async.epics import adcore
|
|
4
|
+
from ophyd_async.epics.signal import epics_signal_rw_rbv
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class VimbaPixelFormat(str, Enum):
|
|
@@ -46,18 +45,22 @@ class VimbaExposeOutMode(str, Enum):
|
|
|
46
45
|
trigger_width = "TriggerWidth" # Expose for length of high signal
|
|
47
46
|
|
|
48
47
|
|
|
49
|
-
class
|
|
48
|
+
class VimbaDriverIO(adcore.ADBaseIO):
|
|
49
|
+
"""This mirrors the interface provided by ADVimba/db/vimba.template."""
|
|
50
|
+
|
|
50
51
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
51
52
|
# self.pixel_format = epics_signal_rw_rbv(PixelFormat, prefix + "PixelFormat")
|
|
52
|
-
self.
|
|
53
|
+
self.convert_pixel_format = epics_signal_rw_rbv(
|
|
53
54
|
VimbaConvertFormat, prefix + "ConvertPixelFormat"
|
|
54
55
|
) # Pixel format of data outputted to AD
|
|
55
|
-
self.
|
|
56
|
+
self.trigger_source = epics_signal_rw_rbv(
|
|
56
57
|
VimbaTriggerSource, prefix + "TriggerSource"
|
|
57
58
|
)
|
|
58
59
|
self.trigger_mode = epics_signal_rw_rbv(VimbaOnOff, prefix + "TriggerMode")
|
|
59
|
-
self.
|
|
60
|
-
|
|
60
|
+
self.trigger_overlap = epics_signal_rw_rbv(
|
|
61
|
+
VimbaOverlap, prefix + "TriggerOverlap"
|
|
62
|
+
)
|
|
63
|
+
self.exposure_mode = epics_signal_rw_rbv(
|
|
61
64
|
VimbaExposeOutMode, prefix + "ExposureMode"
|
|
62
65
|
)
|
|
63
66
|
super().__init__(prefix, name)
|
|
@@ -1,145 +1,22 @@
|
|
|
1
1
|
"""Demo EPICS Devices for the tutorial"""
|
|
2
2
|
|
|
3
|
-
import asyncio
|
|
4
3
|
import atexit
|
|
5
4
|
import random
|
|
6
5
|
import string
|
|
7
6
|
import subprocess
|
|
8
7
|
import sys
|
|
9
|
-
from enum import Enum
|
|
10
8
|
from pathlib import Path
|
|
11
9
|
|
|
12
|
-
import
|
|
13
|
-
from
|
|
10
|
+
from ._mover import Mover, SampleStage
|
|
11
|
+
from ._sensor import EnergyMode, Sensor, SensorGroup
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
observe_value,
|
|
23
|
-
)
|
|
24
|
-
from ophyd_async.core.async_status import AsyncStatus
|
|
25
|
-
from ophyd_async.core.utils import (
|
|
26
|
-
DEFAULT_TIMEOUT,
|
|
27
|
-
CalculatableTimeout,
|
|
28
|
-
CalculateTimeout,
|
|
29
|
-
WatcherUpdate,
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
from ..signal.signal import epics_signal_r, epics_signal_rw, epics_signal_x
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class EnergyMode(str, Enum):
|
|
36
|
-
"""Energy mode for `Sensor`"""
|
|
37
|
-
|
|
38
|
-
#: Low energy mode
|
|
39
|
-
low = "Low Energy"
|
|
40
|
-
#: High energy mode
|
|
41
|
-
high = "High Energy"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class Sensor(StandardReadable):
|
|
45
|
-
"""A demo sensor that produces a scalar value based on X and Y Movers"""
|
|
46
|
-
|
|
47
|
-
def __init__(self, prefix: str, name="") -> None:
|
|
48
|
-
# Define some signals
|
|
49
|
-
with self.add_children_as_readables(HintedSignal):
|
|
50
|
-
self.value = epics_signal_r(float, prefix + "Value")
|
|
51
|
-
with self.add_children_as_readables(ConfigSignal):
|
|
52
|
-
self.mode = epics_signal_rw(EnergyMode, prefix + "Mode")
|
|
53
|
-
|
|
54
|
-
super().__init__(name=name)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
class SensorGroup(StandardReadable):
|
|
58
|
-
def __init__(self, prefix: str, name: str = "", sensor_count: int = 3) -> None:
|
|
59
|
-
with self.add_children_as_readables():
|
|
60
|
-
self.sensors = DeviceVector(
|
|
61
|
-
{i: Sensor(f"{prefix}{i}:") for i in range(1, sensor_count + 1)}
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
super().__init__(name)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class Mover(StandardReadable, Movable, Stoppable):
|
|
68
|
-
"""A demo movable that moves based on velocity"""
|
|
69
|
-
|
|
70
|
-
def __init__(self, prefix: str, name="") -> None:
|
|
71
|
-
# Define some signals
|
|
72
|
-
with self.add_children_as_readables(HintedSignal):
|
|
73
|
-
self.readback = epics_signal_r(float, prefix + "Readback")
|
|
74
|
-
with self.add_children_as_readables(ConfigSignal):
|
|
75
|
-
self.velocity = epics_signal_rw(float, prefix + "Velocity")
|
|
76
|
-
self.units = epics_signal_r(str, prefix + "Readback.EGU")
|
|
77
|
-
self.setpoint = epics_signal_rw(float, prefix + "Setpoint")
|
|
78
|
-
self.precision = epics_signal_r(int, prefix + "Readback.PREC")
|
|
79
|
-
# Signals that collide with standard methods should have a trailing underscore
|
|
80
|
-
self.stop_ = epics_signal_x(prefix + "Stop.PROC")
|
|
81
|
-
# Whether set() should complete successfully or not
|
|
82
|
-
self._set_success = True
|
|
83
|
-
|
|
84
|
-
super().__init__(name=name)
|
|
85
|
-
|
|
86
|
-
def set_name(self, name: str):
|
|
87
|
-
super().set_name(name)
|
|
88
|
-
# Readback should be named the same as its parent in read()
|
|
89
|
-
self.readback.set_name(name)
|
|
90
|
-
|
|
91
|
-
@WatchableAsyncStatus.wrap
|
|
92
|
-
async def set(
|
|
93
|
-
self, new_position: float, timeout: CalculatableTimeout = CalculateTimeout
|
|
94
|
-
):
|
|
95
|
-
self._set_success = True
|
|
96
|
-
old_position, units, precision, velocity = await asyncio.gather(
|
|
97
|
-
self.setpoint.get_value(),
|
|
98
|
-
self.units.get_value(),
|
|
99
|
-
self.precision.get_value(),
|
|
100
|
-
self.velocity.get_value(),
|
|
101
|
-
)
|
|
102
|
-
if timeout is CalculateTimeout:
|
|
103
|
-
assert velocity > 0, "Mover has zero velocity"
|
|
104
|
-
timeout = abs(new_position - old_position) / velocity + DEFAULT_TIMEOUT
|
|
105
|
-
# Make an Event that will be set on completion, and a Status that will
|
|
106
|
-
# error if not done in time
|
|
107
|
-
done = asyncio.Event()
|
|
108
|
-
done_status = AsyncStatus(asyncio.wait_for(done.wait(), timeout))
|
|
109
|
-
# Wait for the value to set, but don't wait for put completion callback
|
|
110
|
-
await self.setpoint.set(new_position, wait=False)
|
|
111
|
-
async for current_position in observe_value(
|
|
112
|
-
self.readback, done_status=done_status
|
|
113
|
-
):
|
|
114
|
-
yield WatcherUpdate(
|
|
115
|
-
current=current_position,
|
|
116
|
-
initial=old_position,
|
|
117
|
-
target=new_position,
|
|
118
|
-
name=self.name,
|
|
119
|
-
unit=units,
|
|
120
|
-
precision=precision,
|
|
121
|
-
)
|
|
122
|
-
if np.isclose(current_position, new_position):
|
|
123
|
-
done.set()
|
|
124
|
-
break
|
|
125
|
-
if not self._set_success:
|
|
126
|
-
raise RuntimeError("Motor was stopped")
|
|
127
|
-
|
|
128
|
-
async def stop(self, success=True):
|
|
129
|
-
self._set_success = success
|
|
130
|
-
status = self.stop_.trigger()
|
|
131
|
-
await status
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
class SampleStage(Device):
|
|
135
|
-
"""A demo sample stage with X and Y movables"""
|
|
136
|
-
|
|
137
|
-
def __init__(self, prefix: str, name="") -> None:
|
|
138
|
-
# Define some child Devices
|
|
139
|
-
self.x = Mover(prefix + "X:")
|
|
140
|
-
self.y = Mover(prefix + "Y:")
|
|
141
|
-
# Set name of device and child devices
|
|
142
|
-
super().__init__(name=name)
|
|
13
|
+
__all__ = [
|
|
14
|
+
"Mover",
|
|
15
|
+
"SampleStage",
|
|
16
|
+
"EnergyMode",
|
|
17
|
+
"Sensor",
|
|
18
|
+
"SensorGroup",
|
|
19
|
+
]
|
|
143
20
|
|
|
144
21
|
|
|
145
22
|
def start_ioc_subprocess() -> str:
|