ophyd
ophyd copied to clipboard
SoftPositioner is not identified as device or signal using walk_components()
While exploring a resolution to https://github.com/BCDA-APS/apstools/issues/641, tested the proposed solution there to a diffractometer instance from hklpy, such as:
import hkl
sim4c = hkl.SimulatedE4CV("", name="sim4c")
Using the walk_components()
method, it is possible to print a small table showing if a Component is either a device or a signal:
import pyRestTable
table = pyRestTable.Table()
table.labels = "dotted_name is_device is_signal".split()
for item in sim4c.walk_components():
table.addRow((item.dotted_name,item.item.is_device, item.item.is_signal))
print(table.reST(fmt="md"))
This table is printed:
dotted_name | is_device | is_signal |
---|---|---|
energy | False | True |
energy_units | False | True |
energy_offset | False | True |
energy_update_calc_flag | False | True |
geometry_name | False | True |
class_name | False | True |
sample_name | False | True |
lattice | False | True |
lattice_reciprocal | False | True |
U | False | True |
UB | False | True |
reflections | False | True |
reflections_details | False | True |
ux | False | True |
uy | False | True |
uz | False | True |
diffractometer_name | False | True |
_hklpy_version | False | True |
_pseudos | False | True |
_reals | False | True |
_constraints | False | True |
_mode | False | True |
orientation_attrs | False | True |
max_forward_iterations | False | True |
h | True | False |
h.readback | False | True |
h.setpoint | False | True |
k | True | False |
k.readback | False | True |
k.setpoint | False | True |
l | True | False |
l.readback | False | True |
l.setpoint | False | True |
omega | False | False |
chi | False | False |
phi | False | False |
tth | False | False |
Note that omega, chi, phi, and tth that both columns are False
. It is expected that each of these SoftPositioner
s would be identified as is_device=True
.
For reference: SoftPositioner
, walk_components()
, is_device
, and is_signal
Looking at PositionerBase
, it is not clear whether this might be used as a Device or as a Signal, so the test: https://github.com/bluesky/ophyd/blob/ac6251131b4638c715ce8b90478a0d714cb857d3/ophyd/device.py#L215-L218
returns False
since it is not a subclass of Device
. Similarly, this cannot be a Signal
since it is not subclass: https://github.com/bluesky/ophyd/blob/ac6251131b4638c715ce8b90478a0d714cb857d3/ophyd/device.py#L220-L223
Perhaps the test for is_device
could consider if the object in question as Component
attributes. Wouldn't this determine whether the object is or is not a Device
? And the test for is_signal
would verify that the class does not have Component
attributes.
In [130]: dir(sim4c.omega)
Out[130]:
['SUB_DONE',
'SUB_READBACK',
'SUB_START',
'_OphydObject__any_instantiated',
'_OphydObject__instantiation_callbacks',
'_OphydObject__register_instance',
'_SUB_REQ_DONE',
'__annotations__',
'__class__',
'__copy__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getnewargs_ex__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'_args_cache',
'_attr_name',
'_callbacks',
'_cb_count',
'_cid_to_event_mapping',
'_default_sub',
'_done_moving',
'_egu',
'_kind',
'_limits',
'_mark_as_instantiated',
'_moving',
'_name',
'_ophyd_labels_',
'_parent',
'_position',
'_repr_info',
'_reset_sub',
'_run_subs',
'_set_position',
'_settle_time',
'_setup_move',
'_started_moving',
'_timeout',
'_unwrapped_callbacks',
'_validate_kind',
'add_instantiation_callback',
'attr_name',
'check_value',
'clear_sub',
'connected',
'control_layer_log',
'describe',
'describe_configuration',
'destroy',
'dotted_name',
'egu',
'event_types',
'high_limit',
'hints',
'kind',
'limits',
'log',
'low_limit',
'move',
'moving',
'name',
'parent',
'position',
'read',
'read_configuration',
'report',
'root',
'set',
'settle_time',
'source',
'stop',
'subscribe',
'subscriptions',
'timeout',
'unsubscribe',
'unsubscribe_all']
Does not look like a Device
to me since it has no Component
attributes. Also:
In [131]: sim4c.omega.read()
Out[131]: OrderedDict([('sim4c_omega', {'value': 0, 'timestamp': 1677266815.4288268})])
Perhaps, leave is_device
as-is and make is_signal
be not _is_device
. Such as:
@property
def is_signal(self):
"Does this Component contain a Signal?"
return isinstance(self.cls, type) and not self.is_device