tango-controls/pytango

[Question] HL DS synchronized with another DS

hayg25 opened this issue · 7 comments

Dear All,
I would like to create a DS (DS1) with 2 attributes (Att11, Att12).
This DS should be build from another existing DS (DS0) with 2 Attributes (Att01, Att02)
like : `

  • Att11 = K1*Att01
  • Att12 = K2*Att02
    K1 and K2 are some scaling factors in this case but the arithmetic operation for Att11, Att12, could be more complicated (polynomial, ... etc)
    I would like to do it for each event.

Do you have an example showing how to do this using PyTango.

Many thanks in advance

@hayg25 this looks very close to what has been implemented in the Facade device at MaxIV. Vincent Michel, one of the authors, gave a great talk on this topic at ICALEPCS 2017: https://accelconf.web.cern.ch/icalepcs2017/talks/mobpl06_talk.pdf

There are links in there to the code. Hopefully someone from MaxIV can help you try it out.

Cheers

this looks very close to what has been implemented in the Facade device at MaxIV.

Exactly! :)

Here's a link to the documentation:
https://tango-facadedevice.readthedocs.io/en/latest/

Dear @andygotz, dear @vxgmichel ,
thanks a lot for the solution, that's exactly what I need.
I tried using a DS I created for testing :

from tango import DispLevel, AttrWriteType
from tango.server import run
from tango.server import Device, DeviceMeta
from tango.server import attribute, command
from tango import DevState
from numpy.random import random_sample


class DS_TEST(Device):
	__metaclass__ = DeviceMeta

# List of high level variables

	def init_device(self):
		Device.init_device(self)
		self._amplitude   = 0
		self._delay       = 0

		self.set_state(DevState.ON)

	amplitude  = attribute(label="Amplitude",   dtype=float,  access = AttrWriteType.READ_WRITE)
	delay      = attribute(label="Delay",       dtype=float,  access = AttrWriteType.READ_WRITE)

	def read_amplitude(self): 
		return self._amplitude			
	def write_amplitude(self,amplitude):
		self._amplitude = amplitude

	def read_delay(self):
		return self._delay
	def write_delay(self,delay):
		self._delay = delay


if __name__ == "__main__":
    run((DS_TEST,))

and I modified the example you gave :

from facadedevice import Facade, proxy_attribute, logical_attribute
from tango.server import run


class DS_REC(Facade):
    
    Width = proxy_attribute(
        dtype=float,
        property_name='WidthAttribute')
    
    Height = proxy_attribute(
        dtype=float,
        property_name='HeightAttribute')
    
    @logical_attribute(
        bind=['Width', 'Height'])
    def Sum(width, height):
        return width + height
    
if __name__ == '__main__':
    DS_REC.run_server()

so I set the properties for the new DS_REC.
And when I start the device,

  1. It stays in Unknown state
  2. none of the value is updated ...

Thanks

Hello @hayg25

It missing self in Sum arguments:

    @logical_attribute(
        bind=['Width', 'Height'])
    def Sum(self, width, height):
        return width + height

The two attributes Width and else Height are bind to the attribute defined in the properties:
WidthAttribute
WidthAttribute

This attribute can be set a tango attribute like domain/family/member/attribute (The tango attribute change/periodic event channel has to be enabled) or to a raw value.

The device state has to be managed manually (like a standard tango device). The state can also be bind to some facade attribute (https://tango-facadedevice.readthedocs.io/en/latest/tutorial.html#state-attribute)

You can always use the command GetInfo to get more details about the device.

Hi @AntoineDupre ,
thanks for your help, indeed I missed the self argument !
It Works now. But still the DS status is in unknown mode : any idea ?

The device state and status are not changed to ON automatically, UNKNOWN will stay until you change it.
In normal Tango devices, I just use self.set_state() and self.set_status() in the appropriate places (e.g. at the end of init_device() or after some action failed inside a command). Remember to always update both (*) to keep them in sync.
I'm not familiar with this facadedevice, but the tutorial Antoine linked shows you how to do it easily with @state_attribute. Also, the section Adding extra logic at initialization shows how to add something similar to init_device() if you want to set the state there.

(*) If you only want to update state and keep status as the default "The device is in [STATE] state", you need to set_status to empty or 'Not initialised' I believe, since that is the default value and Tango will insert the right STATE always.

Hi @hayg25

As Idoyle mention, the state needs to be managed manually. It can be set in the safe_init_device function (function called after facade initialization):
More documentation there: https://tango-facadedevice.readthedocs.io/en/latest/tutorial.html#adding-extra-logic-at-initialization