Hi!
I would like to have a working non conflicting example for event subscription for real motors which have Sardana controllers.
The task is the following, if Sardana motor has a TangoDevice attribute with motor address, I take this motor address and subscribe for its events, state change or position change. If I subscribe to Sardana motor, the updates happen not frequent enough, I want to have a more frequent updates. I want to have it for GUI.
Why I want to do that:
Current implementation of Taurus - TaurusAttribute is not robust enough (debian wheezy python-taurus 3.4.0-1.3). If I set Attribute polling by 100ms by attr.activatePolling(100), CPU load gets to 10-20% which is unacceptable if I want to use more than 1 attribute. 500ms polling takes 3-6% of CPU time. Even our simple hand made python.threading scripts running on the same PC with simultaneous polling of 10-20 attributes take much less CPU power (100ms + threading in normal regime, not idle).
The problem I have encountered with Sardana:
As long as I subscribe for event polling for state or position for a real Motor instance (OMS or TangoAttribute motor, etc) using threaded version of the following simplified code:
def setPolling(self, device_path):
d = PyTango.DeviceProxy(device_path)
self.device = d
attr = 'state'
if not d.is_attribute_polled(attr):
d.poll_attribute(attr, poll_time)
else:
# save polling state
self._state_polled = True
self.__idstate = d.subscribe_event(attr, PyTango.EventType.CHANGE_EVENT, self.actionStateChange)
def cleanup(self):
if isinstance(self.device, PyTango.DeviceProxy):
try:
attr = 'state'
self.device.unsubscribe_event(self.__idstate)
if not self._state_polled:
d.stop_poll_attribute(attr)
except DevFailed:
pass
I can start and run my code with low CPU load on the machine running the client.
Sardana macros like umvr work flawless even for large motor distances, but not the scans - dscan and ascan miserably fail, not always, but usual
So, Sardana scans stop to work with the following error messages - see below.
In my understanding Sardana is intended to be a general package working with Tango devices but not conflicting with other packages using somewhat similar or extended functionality. For instance I would like to have event subscription working inside my Sardana scripts running on Sardana MacroServer + GUI, I would also like to understand the errors I have made in my code (if any) and general logic I should follow. May be I have missed some important points in documentation.
In addition - it would be also nice like to have a Sardana bug fix (moving scripts mvr, umvr) seem to be unaffected in contrast to scans).
I will also forward this mail to Tereza from DESY, it was simpler for me to submit a direct bug request. I would like of course to have this bug fix as soon as possible since PETRA-III at DESY will start user operation and we would really appreciate to have major some bugs to be fixed soon.
The complete test code I have used is attached.
Thanks for your hard work!
Cheers,
Konstantin
BUG REPORT from a SPOCK session
Report: Stopped at step #325 with:
ceny_gp:
State: Moving
Status: ceny_gp is Moving (external)
STATE(MOVING) LIM+(0) LIM-(0)
Position: -0.9539 [CHANGING]
Returning to start positions...
An error occurred while running Macro 'dscan(ceny_gp, -1, 1, 1000, 0.05)':
state is not 'ON'
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/msmacromanager.py", line 1135, in runMacro
for step in macro_obj.exec_():
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/macro.py", line 2193, in exec_
for i in it:
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/macros/scan.py", line 250, in run
for step in self._gScan.step_scan():
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/scan/gscan.py", line 799, in step_scan
for i in self.scan_loop():
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/scan/gscan.py", line 855, in scan_loop
self.stepUp(i, step, lstep)
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/scan/gscan.py", line 888, in stepUp
state, positions = motion.move(step['positions'])
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/motion.py", line 373, in move
ret = moveable.move(new_pos, timeout=timeout)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 733, in go
PoolElement.go(self, args, kwargs)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 247, in new_fn
return fn(args, kwargs)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 446, in go
eid = self.start(*args, kwargs)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 247, in new_fn
return fn(args, kwargs)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 416, in start
self._start(args, kwargs)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 722, in _start
self.write_attribute('position', new_pos)
File "/usr/lib/python2.7/dist-packages/PyTango/green.py", line 165, in greener
ret = submit(fn, self, *args, kwargs)
File "/usr/lib/python2.7/dist-packages/PyTango/green.py", line 81, in synch_submit
return get_synch_executor().submit(fn, args, kwargs)
File "/usr/lib/python2.7/dist-packages/PyTango/green.py", line 73, in submit
return fn(args, kwargs)
File "/usr/lib/python2.7/dist-packages/PyTango/device_proxy.py", line 964, in __DeviceProxy__write_attribute
return self._write_attribute(*args, kwargs)
DevFailed: DevFailed[
DevError[
desc = state is not 'ON'
origin = OmsVme58::setup_unit_move
reason = OmsVme58 error
severity = ERR]
DevError[
desc = Failed to write_attribute on device p02/motor/eh2b.42, attribute Position
origin = DeviceProxy::write_attribute()
reason = API_AttributeFailed
severity = ERR]
DevError[
desc = Failed to write_attribute on device motor/omsvme58_eh2b/42, attribute position
origin = DeviceProxy::write_attribute()
reason = API_AttributeFailed
severity = ERR]
]
p02/door/door.01 [27]: dscan ceny_gp -.1 .1 10 0.05
Operation will be saved in /tmp/scan_01166.nxs (nxs)
Scan #1166 started at Wed Apr 15 14:53:19 2015. It will take at least 0:00:00.550750
Moving to start positions...
petra
globals
keyword
#Pt No ceny_gp eh2b_t01 eh2b_vfc01 eh2b_vfc02 eh2b_vfc03 eh2b_vfc04 BeamCurrent dt
0 -0.7019 0.05 76.5 74.5 64.5 0 0.00836048 8.18461
1 -0.7017 0.05 76 74.5 63.5 0 0.00836048 8.45843
Report: Stopped at step #2 with:
ceny_gp:
State: Moving
Status: ceny_gp is Moving (external)
STATE(MOVING) LIM+(0) LIM-(0)
Position: -0.6852 [CHANGING]
Returning to start positions...
Failed to execute macro 'do_restore'
An error occurred while running Macro 'dscan(ceny_gp, -.1, .1, 10, 0.05)':
state is not 'ON'
p02/door/door.01 [28]: www
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/msmacromanager.py", line 1135, in runMacro
for step in macro_obj.exec_():
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/macro.py", line 2193, in exec_
for i in it:
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/macros/scan.py", line 250, in run
for step in self._gScan.step_scan():
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/scan/gscan.py", line 799, in step_scan
for i in self.scan_loop():
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/scan/gscan.py", line 855, in scan_loop
self.stepUp(i, step, lstep)
File "/usr/lib/python2.7/dist-packages/sardana/macroserver/scan/gscan.py", line 888, in stepUp
state, positions = motion.move(step['positions'])
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/motion.py", line 373, in move
ret = moveable.move(new_pos, timeout=timeout)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 733, in go
PoolElement.go(self, args, kwargs)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 247, in new_fn
return fn(args, kwargs)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 446, in go
eid = self.start(*args, kwargs)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 247, in new_fn
return fn(args, kwargs)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 416, in start
self._start(args, kwargs)
File "/usr/lib/python2.7/dist-packages/sardana/taurus/core/tango/sardana/pool.py", line 722, in _start
self.write_attribute('position', new_pos)
File "/usr/lib/python2.7/dist-packages/PyTango/green.py", line 165, in greener
ret = submit(fn, self, *args, kwargs)
File "/usr/lib/python2.7/dist-packages/PyTango/green.py", line 81, in synch_submit
return get_synch_executor().submit(fn, args, kwargs)
File "/usr/lib/python2.7/dist-packages/PyTango/green.py", line 73, in submit
return fn(args, kwargs)
File "/usr/lib/python2.7/dist-packages/PyTango/device_proxy.py", line 964, in __DeviceProxy__write_attribute
return self._write_attribute(*args, kwargs)
DevFailed: DevFailed[
DevError[
desc = state is not 'ON'
origin = OmsVme58::setup_unit_move
reason = OmsVme58 error
severity = ERR]
DevError[
desc = Failed to write_attribute on device p02/motor/eh2b.42, attribute Position
origin = DeviceProxy::write_attribute()
reason = API_AttributeFailed
severity = ERR]
DevError[
desc = Failed to write_attribute on device motor/omsvme58_eh2b/42, attribute position
origin = DeviceProxy::write_attribute()
reason = API_AttributeFailed
severity = ERR]
]
Hi Konstantin,
Only a quick hint regarding your first issue: have you considered pushing events from the tango motor device instead of relying on polling?
If I understand your setup correctly, you have a tango DS for your motor, and the Sardana controller uses the Tango interface to provide a pool motor device.
Ideally, your TangoDevice should be implemented to push events on its attributes for position, state, velocity, etc...
This way, the Sardana controller would update the position much more frequently (and cheaply) and then you could use a TaurusForm with PoolMotorTV widget (from sardana.taurus.qt.qtgui.extra_pool) to interact with your motor in a GUI by giving it the model of the Sardana pool motor device (not the Tango one).
About the rest of your question, I let the experts (Zibi, Teresa,...) reply
I hope this helps
Carlos
Hi!
I am a newbee with PyTango, there is no doubt about that.
Could you please comment on pushing and provide a code example.
I see push_event for event subscription documented in DeviceProxy.subscribe_event, however before calling the subscribe_events function of device proxy, I have to start attribute polling, otherwise I get error message from PyTango - I have tried that.
Can you please provide an example or a link with an example?
I have found this
http://www.tango-controls.org/resources/howto/how-pytango/
but there is again nothing new about the event pushing.
I know I am not in a position to complain, simple operations in PyTango are well described, but a little more advanced topics in PyTango, Sardana and Taurus are somewhat vague for people who are not professionals and do not have time to look inside the real code.
best,
Konstantin
Hi Konstantin,
First of all, sorry for the late answer. I have took a look to your problem. Probably I will not give you a straight answer, cause I will start with some assumptions, and they may be wrong. Furthermore I have to say it is not an easy problem, but let’s start…
I do not know which, Sardana motor controller do you use. But from what is available in the repository, I assume that it could be this one:
http://sourceforge.net/p/sardana/controllers.git/ci/master/tree/python/motor/HasyMotorCtrl.py
If it is not this one, please provide me a link to the problematic controller, or attach me the code.
From now on, I will answer in between lines of your message:
The position updates coming from the Sardana motor, happens only during the motion and depends on several factors:
I think that the last point does not cause problems in your case. I would start tuning your configuration with the change event configuration. I attach you a simple script (update_move.py) which demonstrates how configuration of the absolute change of the position attribute can affect the frequency of updates.
I think that the problem of Taurus Polling, is not related with the frequency of updates coming from the Sardana motor position attribute. Sardana uses Tango events for the position attribute. I think it is better to open a separate ticket, regarding the Taurus performance issues.
If I understand well, by real motor, you refer to another Tango device completely independent to Sardana.
To start debugging your problems with scans, could you confirm that scans using Sardana dummy motors work well?
At the first look, the problem with scans seems to be caused by inconsistency between states of Sardana motor, and the “real motor” (OMS in this case). But it requires further investigation.
I did not analyze all your program (test_qtpolling), but from what I see, it does not take a lot of profit from Sardana. In the main function it reads the “real motor” address, and continuous to work with the motor independent to Sardana.
Sardana should provide you many benefits, thanks to the common interfaces and abstracting the heterogenous hardware e.g. Motors, Experimental Channels… some examples could be:
With the further debugging, we should determine where this bug comes from: Sardana core, or the Motor controller and try to fix it.
Many thanks for pointing your problems, we will do the best to help you.
BUG REPORT from a SPOCK session