Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Mathias Guijarro committed Nov 1, 2024
1 parent 37725d5 commit 59fd4ff
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 41 deletions.
85 changes: 45 additions & 40 deletions ophyd/signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,10 @@
DEFAULT_EPICSSIGNAL_VALUE = UNSET_VALUE


class ReadTimeoutError(TimeoutError):
...
class ReadTimeoutError(TimeoutError): ...


class ConnectionTimeoutError(TimeoutError):
...


class UndeterminedDataType(Exception):
def __init__(self, dtype=None, shape=None):
self.dtype = np.dtype(dtype).name if dtype is not None else ""
self.shape = shape
class ConnectionTimeoutError(TimeoutError): ...


class Signal(OphydObject):
Expand Down Expand Up @@ -104,7 +96,7 @@ def __init__(
self,
*,
name,
value=UNSET_VALUE,
value=0.0,
dtype=None,
shape=None,
timestamp=None,
Expand All @@ -128,37 +120,48 @@ def __init__(
self._dispatcher = cl.get_dispatcher()
self._metadata_thread_ctx = self._dispatcher.get_thread_context("monitor")

# try to apply good default, if possible
try:
if dtype is None:
if value is UNSET_VALUE:
if shape is None:
value = 0.0
raise UndeterminedDataType()
else:
raise UndeterminedDataType(shape=shape)
self._value_dtype_str = (
"" if dtype in (None, "string") else np.dtype(dtype).name
)
self._value_shape = shape if not dtype == "string" else ()
# check if value corresponds to specified info (or if it is compatible)
if dtype not in (None, "string") and value is not UNSET_VALUE:
value_array = np.asanyarray(value)

try:
value_array.astype(dtype, casting="same_kind")
except TypeError:
dtype_ok = False
# check if conversion between signed int to unsigned int would be fine
if value_array.dtype.kind == "i" and np.dtype(dtype).kind == "u":
bounds = np.iinfo(dtype)
if np.all(value_array >= bounds.min) and np.all(
value_array <= bounds.max
):
dtype_ok = True
else:
dtype_ok = True

if not dtype_ok:
if np.isscalar(value) and value == 0.0:
# default is not ok, change to UNSET_VALUE
# (value will be read via .get() - it does not mean it will correspond
# to the desired dtype, though...)
value = UNSET_VALUE
else:
try:
inferred_type = data_type(value)
except ValueError:
raise UndeterminedDataType()
else:
if inferred_type == "integer":
dtype = int
elif inferred_type == "number":
dtype = float
else:
raise UndeterminedDataType()
if shape is None:
shape = data_shape(value)
except UndeterminedDataType as exc:
self._value_dtype_str = exc.dtype
self._value_shape = exc.shape
self._readback = value
raise TypeError(
f"The value {value} does not match the required dtype {dtype}."
)
else:
self._value_dtype_str = "" if dtype == "string" else np.dtype(dtype).name
self._value_shape = () if shape is None else shape
self._readback = value
if dtype == "string" and np.isscalar(value) and value == 0.0:
value = UNSET_VALUE
if shape is not None and value is not UNSET_VALUE:
if np.asanyarray(value).shape != shape:
raise TypeError(
f"The value {value} does not have the required shape {shape}."
)

self._readback = value

if timestamp is None:
timestamp = time.time()
Expand Down Expand Up @@ -1018,6 +1021,8 @@ def __init__(

if string:
kwargs["dtype"] = "string"
kwargs.setdefault("value", UNSET_VALUE) # no default

super().__init__(name=name, metadata=metadata, **kwargs)

validate_pv_name(read_pv)
Expand Down
2 changes: 1 addition & 1 deletion ophyd/tests/test_signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ def test_signal_dtype_shape_info(fake_motor_ioc, cleanup):
original = Signal(name="original", value=1)
original_desc = original.describe()["original"]
assert original_desc["dtype"] == "integer"
assert original_desc["dtype_numpy"] == "int64"
assert original_desc["dtype_numpy"] == ""
assert original_desc["shape"] == []
assert original.get() == 1
original = Signal(name="original", value="On")
Expand Down

0 comments on commit 59fd4ff

Please sign in to comment.