Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SoftPositioner is not identified as device or signal using walk_components() #1095

Open
prjemian opened this issue Feb 24, 2023 · 4 comments
Labels

Comments

@prjemian
Copy link
Contributor

prjemian commented Feb 24, 2023

While exploring a resolution to BCDA-APS/apstools#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 SoftPositioners would be identified as is_device=True.

@prjemian prjemian added the bug label Feb 24, 2023
@prjemian
Copy link
Contributor Author

prjemian commented Feb 24, 2023

For reference: SoftPositioner, walk_components(), is_device, and is_signal

@prjemian
Copy link
Contributor Author

Looking at PositionerBase, it is not clear whether this might be used as a Device or as a Signal, so the test:

ophyd/ophyd/device.py

Lines 215 to 218 in ac62511

@property
def is_device(self):
"Does this Component contain a Device?"
return isinstance(self.cls, type) and issubclass(self.cls, Device)

returns False since it is not a subclass of Device. Similarly, this cannot be a Signal since it is not subclass:

ophyd/ophyd/device.py

Lines 220 to 223 in ac62511

@property
def is_signal(self):
"Does this Component contain a Signal?"
return isinstance(self.cls, type) and issubclass(self.cls, Signal)

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.

@prjemian
Copy link
Contributor Author

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})])

@prjemian
Copy link
Contributor Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant