taurus-org / taurus

Moved to https://gitlab.com/taurus-org/taurus
http://taurus-scada.org
43 stars 46 forks source link

TaurusLabel and TaurusWheelEdit How to set format and unit for a Sardana MotorController Position #1115

Open marouanebj opened 4 years ago

marouanebj commented 4 years ago

Hello,

I want to display the position of a motor with TaurusLabel and control it with TaurusWheelEdit. I want to see a precision of 3 (exemple: 50.123) but I see only 2.

I have my Sardana MotorController, and I see the position perfectly using spock.

Door_ipadiffx_1 [12]: p.rvalue
    Result [12]: 50.071016 <Unit('dimensionless')>

Here after the description of what Info I managed to get using spock. I see format, format_spec, precision but I have no clue how to set these.

I did not find how to set the format, and also the Unit.

I'm still with python-taurus/stable,now 4.5.0+dfsg-1 all [installé].

Do I have to do it in the Sardana Controller, if yes how ? Can I do it in the GUI code ?

Thanks, Marouane

Door_ipadiffx_1 [1]: from taurus import Device, Attribute

Door_ipadiffx_1 [2]: mtrx = Device("mottrx")

Door_ipadiffx_1 [3]: mtrx
    Result [3]: TangoDevice(tango://gaston.ipanema.cnrs.fr:10000/motor/hydraxyzoctrl/1)

Door_ipadiffx_1 [4]: mtrx.getAttribute("Position")
    Result [4]: TangoAttribute(tango://gaston.ipanema.cnrs.fr:10000/motor/hydraxyzoctrl/1/Position)

Door_ipadiffx_1 [5]: p = mtrx.getAttribute("Position")

Door_ipadiffx_1 [6]: p
    Result [6]: TangoAttribute(tango://gaston.ipanema.cnrs.fr:10000/motor/hydraxyzoctrl/1/Position)

Door_ipadiffx_1 [10]: p.getAttrDict()
    Result [10]: 
{'_TangoAttribute__already_warned_unit': None,
 '_TangoAttribute__attr_err': None,
 '_TangoAttribute__attr_value': TangoAttrValue{'_TangoAttrValue__attrName': 'tango://gaston.ipanema.cnrs.fr:10000/motor/hydraxyzoctrl/1/Position', 'wvalue': <Quantity(50.071013, 'dimensionless')>, '_attrRef': <weakproxy at 0x7fadae05d1b0 to TangoAttribute at 0x7fadb4eb7f50>, 'rvalue': <Quantity(50.071013, 'dimensionless')>, '_TangoAttrValue__attrType': 1, '_pytango_dev_attr': DeviceAttribute(data_format = tango._tango.AttrDataFormat.SCALAR, dim_x = 1, dim_y = 0, has_failed = False, is_empty = False, name = 'Position', nb_read = 1, nb_written = 1, quality = tango._tango.AttrQuality.ATTR_VALID, r_dimension = AttributeDimension(dim_x = 1, dim_y = 0), time = TimeVal(tv_nsec = 0, tv_sec = 1590671979, tv_usec = 362692), type = tango._tango.CmdArgType.DevDouble, value = 50.071013, w_dim_x = 1, w_dim_y = 0, w_dimension = AttributeDimension(dim_x = 1, dim_y = 0), w_value = 50.071013), 'time': TimeVal(tv_nsec = 0, tv_sec = 1590671979, tv_usec = 362692), 'error': None, 'config': <weakproxy at 0x7fadae05d1b0 to TangoAttribute at 0x7fadb4eb7f50>, 'quality': <AttrQuality.ATTR_VALID: 0>},
 '_TangoAttribute__cfg_evt_id': 25,
 '_TangoAttribute__chg_evt_id': None,
 '_TangoAttribute__dev_hw_obj': Motor(motor/hydraxyzoctrl/1),
 '_TangoAttribute__read_lock': <_RLock owner=None count=0>,
 '_TangoAttribute__subscription_event': <threading._Event at 0x7fadae059a10>,
 '_TangoAttribute__subscription_state': 0,
 '_TaurusAttribute__activate_polling': False,
 '_TaurusAttribute__enable_polling': True,
 '_TaurusAttribute__forced_polling': False,
 '_TaurusAttribute__polled': False,
 '_TaurusAttribute__polling_period': 3000,
 '_alarm': [-inf <Unit('dimensionless')>, inf <Unit('dimensionless')>],
 '_full_name': 'tango://gaston.ipanema.cnrs.fr:10000/motor/hydraxyzoctrl/1/Position',
 '_label': 'Position',
 '_listeners': [],
 '_norm_name': 'motor/hydraxyzoctrl/1/Position',
 '_parentObj': TangoDevice(tango://gaston.ipanema.cnrs.fr:10000/motor/hydraxyzoctrl/1),
 '_pytango_attrinfoex': AttributeInfoEx(alarms = AttributeAlarmInfo(delta_t = 'Not specified', delta_val = 'Not specified', extensions = [], max_alarm = 'Not specified', max_warning = 'Not specified', min_alarm = 'Not specified', min_warning = 'Not specified'), data_format = tango._tango.AttrDataFormat.SCALAR, data_type = tango._tango.CmdArgType.DevDouble, description = 'No description', disp_level = tango._tango.DispLevel.OPERATOR, display_unit = 'No display unit', enum_labels = [], events = AttributeEventInfo(arch_event = ArchiveEventInfo(archive_abs_change = 'Not specified', archive_period = 'Not specified', archive_rel_change = 'Not specified', extensions = []), ch_event = ChangeEventInfo(abs_change = '1', extensions = [], rel_change = 'Not specified'), per_event = PeriodicEventInfo(extensions = [], period = '1000')), extensions = [], format = '%6.2f', label = 'Position', max_alarm = 'Not specified', max_dim_x = 1, max_dim_y = 0, max_value = 'Not specified', memorized = tango._tango.AttrMemorizedType.NOT_KNOWN, min_alarm = 'Not specified', min_value = 'Not specified', name = 'Position', root_attr_name = '', standard_unit = 'No standard unit', sys_extensions = [], unit = '', writable = tango._tango.AttrWriteType.WT_UNKNOWN, writable_attr_name = 'position'),
 '_range': [-inf <Unit('dimensionless')>, inf <Unit('dimensionless')>],
 '_serialization_mode': 2,
 '_simp_name': 'Position',
 '_units': <Unit('dimensionless')>,
 '_warning': [-inf <Unit('dimensionless')>, inf <Unit('dimensionless')>],
 'data_format': 0,
 'display_level': 0,
 'format_spec': '6.2f',
 'log_children': {},
 'log_full_name': 'gaston.ipanema.cnrs.fr:10000.mottrx.Position',
 'log_handlers': [],
 'log_name': 'Position',
 'log_obj': <logging.Logger at 0x7fadae059bd0>,
 'log_parent': <weakref at 0x7fadb4d50ba8; to 'TangoDevice' at 0x7fadb4f45b10>,
 'max_dim': (1, 0),
 'precision': 2,
 'tango_writable': tango._tango.AttrWriteType.WT_UNKNOWN,
 'type': 1,
 'writable': True}

Door_ipadiffx_1 [12]: p.rvalue
    Result [12]: 50.071016 <Unit('dimensionless')>
marouanebj commented 4 years ago

Hi, For TaurusLabel:

here after my current code

        self.positionTaurusLabel = TaurusLabel(self)
        # self.positionTaurusLabel.setFormat('{:.3f}')
        self.positionTaurusLabel.setModel(model + "/position")
        self.positionTaurusLabel.modelObj.precision = 3
        self.positionTaurusLabel.setBgRole('parentObj.stateObj.rvalue')

        self.positionTaurusWheelEdit = TaurusWheelEdit(self)
        self.positionTaurusWheelEdit.setModel(model + "/position")
        # self.positionTaurusWheelEdit.modelObj.precision = 3
marouanebj commented 4 years ago

I just see one problem here when I use self.positionTaurusLabel.modelObj.precision = 3 if the Sardana server is OFF when I start the GUI it does not work.

marouanebj commented 4 years ago

For the TaurusWheelEdit I use

self.positionTaurusWheelEdit.setModel(model + "/position")
self.positionTaurusWheelEdit.setDigitCount(3, 3)

and i have the same pb if the Sardana server is OFF when I start the GUI it does not work. the setModel does reset the stuff i guess

cpascual commented 4 years ago

Hi, first just the obvious question: since you are using sardana, have you considered just using a PoolMotorTV in a TaurusForm?

See: https://sardana-controls.org/users/taurus/index.html

marouanebj commented 4 years ago

Hi, first just the obvious question: since you are using sardana, have you considered just using a PoolMotorTV in a TaurusForm?

See: https://sardana-controls.org/users/taurus/index.html

I'm using an old version 2.6.2 of Sardana I know I should move to new one and I do not know if PoolMotorTV is there and how to use it. The problem is that there are to much layers to understand I have to dig a lot more to make my GUI. So I code in Python my Qt GUI with Taurus and with Sardana I code my Controllers. Using the taurusdesigner does not work for me when I want to tune my GUI Its always hard. Thanks

cpascual commented 4 years ago

Now, to reply your questions:

Regarding how to remove the "dimensionless": since https://github.com/hgrecco/pint/pull/303 was integrated in pint, the "abbreviation" for "dimensionless" is an empty string. Therefore it is just a matter of using the "~" char in the format to tell pint to use the abbreviated unit (taurus does this by default, but you need to do it explicitly if you set your own format).

So, just use '{:~.3f}' as your format.

If by any chance you are using a very old pint, then you can work around this by using:

'{0.magnitude:.3f}

See the following snippet as a demo:

from taurus.qt.qtgui.application import TaurusApplication
from taurus.qt.qtgui.display import TaurusLabel

if __name__ == "__main__":
    import sys
    app = TaurusApplication(cmd_line_parser=None)
    w = TaurusLabel()
    # w.setFormat('{:.1f}')  # <-- with this it shows "dimensionless"
    # w.setFormat('{0.magnitude:.1f}')  #  <-- with this it does not, but it is ugly
    w.setFormat('{:~.1f}')  # <-- this does the trick too and is more robust
    w.setModel("eval:Q(123.456)")
    w.show()
    w.resize(200, 50)
    sys.exit(app.exec_())
cpascual commented 4 years ago

I'm using an old version 2.6.2 of Sardana I know I should move to new one and I do not know if PoolMotorTV is there and how to use it. The problem is that there are to much layers to understand I have to dig a lot more to make my GUI. So I code in Python my Qt GUI with Taurus and with Sardana I code my Controllers. Using the taurusdesigner does not work for me when I want to tune my GUI Its always hard. Thanks

The PoolMotorTV is also available in sardana 2.x

My recommendation (unless you are using the latest taurus from develop, in which case, see #1108 ) is that you do something like the following snippet:

from taurus.qt.qtgui.application import TaurusApplication
from taurus.qt.qtgui.panel import TaurusForm

if __name__ == "__main__":
    import sys
    app = TaurusApplication(cmd_line_parser=None)

    w = TaurusForm()

    cwmap = {
        'SimuMotor': ('sardana.taurus.qt.qtgui.extra_pool.PoolMotorTV', (), {}),
        'Motor': ('sardana.taurus.qt.qtgui.extra_pool.PoolMotorTV', (), {}),
        'PseudoMotor': ('sardana.taurus.qt.qtgui.extra_pool.PoolMotorTV', (), {}),
        'PseudoCounter': ('sardana.taurus.qt.qtgui.extra_pool.PoolChannelTV', (), {}),
        'CTExpChannel': ('sardana.taurus.qt.qtgui.extra_pool.PoolChannelTV', (), {}),
        'ZeroDExpChannel': ('sardana.taurus.qt.qtgui.extra_pool.PoolChannelTV', (), {}),
        'OneDExpChannel': ('sardana.taurus.qt.qtgui.extra_pool.PoolChannelTV', (), {}),
        'TwoDExpChannel': ('sardana.taurus.qt.qtgui.extra_pool.PoolChannelTV', (), {}),
        'IORegister': ('sardana.taurus.qt.qtgui.extra_pool.PoolIORegisterTV', (), {}),
    }

    w.setCustomWidgetMap(cwmap)
    w.setModel(['your/poolmotor/device'])  # <--put your motor **device** name here

    w.show()
    sys.exit(app.exec_())
cpascual commented 4 years ago

I just see one problem here when I use self.positionTaurusLabel.modelObj.precision = 3

This is monkey-patching and as such is expected not to work in many situations.

and i have the same pb if the Sardana server is OFF when I start the GUI it does not work. the setModel does reset the stuff i guess

... like this one, for the reason that you mention ;-)

marouanebj commented 4 years ago

Thanks a lot for the infos and the Format that worked. I might try the TaurusForm that you send me if I find some time.

If you have an idea for the Digits I would be happy to here it. self.positionTaurusWheelEdit.setDigitCount(3, 3) # does not work when Sardana server restart

And the unit too. Do you think I should ask in the github sardana issues or it is ok here.

Thanks Again.

cpascual commented 4 years ago

Sorry @marouanebj , I missed the last question, and just saw it now.

If you have an idea for the Digits I would be happy to here it. self.positionTaurusWheelEdit.setDigitCount(3, 3) # does not work when Sardana server restart And the unit too.

I haven't looked at it in detail, and maybe the behavior that you describe is actually a bug in the Wheel Edit. If you think so, could you please create a snippet with a simple demo?

In any case you can probably work around the issues by subclassing the wheel edit widget to force your desired settings after setModel

Do you think I should ask in the github sardana issues or it is ok here.

For "pure taurus"-related widgets it is fine here. If you have questions regarding PoolMotorTV and alike, then the sardana issues tracker is the right place