diff --git a/ophyd/signal.py b/ophyd/signal.py index f01180dbd..47e0db768 100644 --- a/ophyd/signal.py +++ b/ophyd/signal.py @@ -6,6 +6,7 @@ import weakref import numpy as np +from collections import namedtuple from . import get_cl from .ophydobj import Kind, OphydObject @@ -50,14 +51,19 @@ class ConnectionTimeoutError(TimeoutError): ... +ValueInfo = namedtuple( + "ValueInfo", ("dtype", "shape", "default"), defaults=(float, (), None) +) + + class Signal(OphydObject): r"""A signal, which can have a read-write or read-only value. Parameters ---------- name : string, keyword only - value : any, optional - The initial value + value : any acceptable value or a ValueInfo object, optional + The initial value, or the ValueInfo structure to characterize the value kind : a member the Kind IntEnum (or equivalent integer), optional Default is Kind.normal. See Kind for options. parent : Device, optional @@ -85,6 +91,7 @@ class Signal(OphydObject): rtolerance : any, optional The relative tolerance associated with the value """ + SUB_VALUE = "value" SUB_META = "meta" _default_sub = SUB_VALUE @@ -95,7 +102,7 @@ def __init__( self, *, name, - value=0.0, + value=DEFAULT_EPICSSIGNAL_VALUE, timestamp=None, parent=None, labels=None, @@ -116,7 +123,19 @@ def __init__( self.cl = cl self._dispatcher = cl.get_dispatcher() self._metadata_thread_ctx = self._dispatcher.get_thread_context("monitor") - self._readback = value + if isinstance(value, ValueInfo): + self._value_dtype_str = np.dtype(value.dtype).name + self._value_shape = value.shape + if value.default is None: + self._readback = DEFAULT_EPICSSIGNAL_VALUE + else: + # ensure default value corresponds to dtype and shape... + self._readback = np.asanyarray(value.default, value.dtype) + self._readback.shape = value.shape + else: + self._value_dtype_str = None + self._value_shape = None + self._readback = value if timestamp is None: timestamp = time.time() @@ -480,8 +499,10 @@ def describe(self): return { self.name: { "source": "SIM:{}".format(self.name), - "dtype": data_type(val), - "shape": data_shape(val), + "dtype": ( + data_type(val) if self._value_dtype_str is None else self._value_dtype_str + ), + "shape": data_shape(val) if self._value_shape is None else self._value_shape, } } except ValueError as ve: