taurus-org / taurus

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

TaurusLabel: Display value without unit #1148

Closed vallsv closed 3 years ago

vallsv commented 3 years ago

Hi,

I would like to know if there is a way to setup TaurusLabel with QtDesigner in order to display the value (with tango formating) but without the unit.

I use to put the units on a dedicated column of my layout in order to align all the values.

I have tried fgRole=rvalue.magnitude but i am afraid it have created exception sometimes.

Is that safe?

And i feel like i lose the Tango format?

Thanks a lot

vallsv commented 3 years ago

Sorry, it sounds like the Tango formatting is always lost, anyway the configuration. I just checked a device with taurus form.

We are using Keighley to measure a current. The range can be very big, so without a scientific notation, the display mostly always shows 0.00, while we expect something like for example 2.12 e-11.

Any idea how i could trick here? Is that something i can do with fgRole?

cpascual commented 3 years ago

Hi, have a look at the fragments API and the formatters API.

For example, this would do what you want:

from taurus.qt.qtgui.application import TaurusApplication
from taurus.qt.qtgui.display import TaurusLabel
from taurus.core.tango.util import tangoFormatter

import sys
app = TaurusApplication()

w = TaurusLabel()

# select the magnitude only (using a fragment in the model name)
w.setModel("sys/tg_test/1/double_scalar#rvalue.magnitude")

# use the format string provided by the tango config
w.setFormat(tangoFormatter)

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

If you do not want to use the tango formatter (for example, if your models are not always tango attributes), you use a explicit format string, as in:

w.setModel("eval:Q(0.00000000123,'mm')#rvalue.magnitude")
w.setFormat("{:.3e}")
cpascual commented 3 years ago

Also note that, in the case of a TaurusLabel you can also use the setFgRole instead of the fragment API:

w.setModel("sys/tg_test/1/double_scalar")
w.setFgRole("rvalue.magnitude")
w.setFormat(tangoFormatter)
vallsv commented 3 years ago

Very nice. I will use that tangoFormater. Thanks a lot.

But just a question? Why don't you use it by default in case of Tango device? I close this issue.

cpascual commented 3 years ago

But just a question? Why don't you use it by default in case of Tango device?

That's a very good question and I get it often.

The reason is that, in the Model-View pattern that we follow in taurus, the formatter (and the format itself) belongs to the view (the label widget in this case), which should be as model-agnostic as possible (i.e., a generic label should not act differently for different types of models).

That said, if in your application you are certain that you are only using tango models (e.g., no eval), then it is fine to set the format at class level for TaurusForm or for TaurusLabel, and then you already get what you want. Still, in general I recommend to be more selective and do this explicitly at instance level, not class level.

cpascual commented 3 years ago

Note, that IMHO, it is a design flaw in tango to include format specification as part of an attribute. It may seem convenient, but it mixes the data and visualization. Consider for example that 2 client apps may have very valid reasons to use different formats for the same tango attribute. That's why in taurus the format is strictly responsibility of the view, and not part of the model

vallsv commented 3 years ago

tango to include format specification

I can't agree. You can call it accuracy if you prefer for most cases. This information is part of the data (basically it's the amount of significant digit).

In my case this data have to be displayed in scientific else it is not readable. So no, it's not matter of preference.

So i agree with you that the view could have specific settings (but in this case setFormat could be exposed to QtDesigner), but i see no reason to not use the one proposed by the model by default.

vallsv commented 3 years ago

I will try to use the tango formatter at class level, sounds a good idea in my case. Thanks for the answer.

cpascual commented 3 years ago

I can't agree. You can call it accuracy if you prefer for most cases.

I fully agree in that the accuracy belongs to the model (and in fact that is exactly the case for generic taurus models, which have a precision attribute). But strictly, what tango defines is "format", not accuracy, and format is about the representation, not a characteristic of the data itself. The use of both overlaps in many common situations, but not always and that is why I say that tango got it wrong there (in contrast, e.g., epics does define the precision).

In fact, in taurus Tango models, a best effort is done to infer the precision by parsing the format. And the default taurus formatter actually uses the precision to adjust the display. You can test it by opening a taurus form with a tango attribute for which you have set the format to "%.1f" (precision -->1) in jive and then repeat after changing the format to "%.6f" (precision-->6). The problem is that this parsing won't work for formats such as "%.3e" because these formats do not contain information about the absolute precision.

In summary:

I hope this makes things clearer about the rationale behind the design decision in this matter

vallsv commented 3 years ago

Still i don't fully agree, cause what you call "at widget level" only make sense if you do not switch from model to another. But i understand the idea, it's always better to have kind of universal information. This make me think you could call %.5g relative precision.

Thanks for the answer. I have cleaned up the my code using the tangoFormatter.

cpascual commented 3 years ago

"at widget level" only make sense if you do not switch from model to another.

You are right, but note that this is one of the reasons why I recommend to do it at widget instance level, and not at widget class level.

For example, the Taurus Form recreates new instances of all its contained items when you change the model. This, coupled with the fact that the form allows to dynamically choose the formatter for each item (via the GUI context menu) and that the choice is stored as part of the widget configuration settings (and thus restored on subsequent executions), allows to be very selective and just customize the formatter for those items which really need it (as opposed to just make everything use the tango formatter via a class customization)

This make me think you could call %.5g relative precision.

The %g specifier is very tricky, because it behaves like %e sometimes and like %f in some other (see note below)

But yes, I also considered introducing a "relative precision" in the attribute models... but I postponed it because I reasoned that the increased complexity (e.g. managing conflicting settings of absolute and relative precision) was not justified by the advantages (it would just help automating a few corner cases which can already be handled with the formatter API anyway)

Note regarding %g: %.2f can be interpreted as "absolute precision is 1e-2", while %.2e can be translated as "relative precision is 1e-2", but %.2g is ambiguous since it depends on the actual value: for a value like 123.456 it is absolute and for a value like 0.00000123 it is relative.