das-developers / das2java

The original das2 library. Provides interactive publication-ready 2-D plotting
https://das2.org
GNU Lesser General Public License v3.0
4 stars 0 forks source link

Default DatumFormatter does not keep enough digits #104

Open DiamondJim87 opened 3 months ago

DiamondJim87 commented 3 months ago

We are trying to make a DasPlot where one of the axes has Mission Elapsed Time (MET). These are sequences of 8 digit integer numbers of seconds, that differ by sometimes as little as 1 second. We are for sure supplying valid double values to create the axis range, because we can display these plots just fine. However, the DatumFormatter that gets set up by default displays them in scientific notation with 6 significant figures. If one opens the property editor for the axis, one sees a datumRange of (for example):

3.67090E8 to 3.67090E8 seconds

If such a DatumRange is ever set for the axis, an exception gets thrown because the range has 0 width. This causes problems, first of all for the user, who may not easily be able to tell how to tweak the range to get the desired plot range. Even if the user does correct the range to use 8 digits, so that the range should once again be valid, the property editor immediately resets the string field back to the 6 digit value it had before (along with throwing an exception).

A secondary problem is that we have a framework that programmatically uses reflection to capture all the properties of all DasPlot and DasAxis instances, and saves and restores these settings under various circumstances. It is basically not possible for the framework to capture the formatter in use -- this assumes it would even be possible for us reliably to inject a custom formatter that would behave as we need it to.

By far the easiest thing (for us of course!) would be if the default formatter could determine the necessary number of significant figures to retain to represent its actual Datum double values -- at least in the context of DatumRange. Or it could also just make it always retain 17 digits (the number of decimal digits for doubles) rather than 6 (closer to the float limit) when using scientific notation. That would of course annoy/inconvenience users that (most of the time) don't need all those digits. It would be easy to truncate trailing 0s, but more problematic would be numbers like 4.7777777777777777E24, which will come up with real life rounding.

Incidentally, according to the Wikipedia entry on single and double precision, to capture even single precision reliably 100% of the time, one needs to keep NINE digits, and for double precision the number of digits is 17. (Frequently one can get away with fewer, but only with 9/17 is one guaranteed to get back the original single/double precision number).

jbfaden commented 3 months ago

Do you have any control of the data passed in to the plot? I think you could specify the formatter to use. Also there's a format property for the DasAxis, which could be "%18.1f", which I would expect to address this.

jbfaden commented 3 months ago

Also it sounds like the DatumFormatter in the DatumRange used to describe the range needs work, and I'll check on that too.

DiamondJim87 commented 3 months ago

Yes we do control the data passed to the plot. So I would set the formatter for the DasAxis?

jbfaden commented 3 months ago

The xtags can have a FORMAT property. So if you can get at the data's xtags (DEPEND_0 property typically), something like xtags.putProperty( QDataSet.FORMAT, '%19.1f' ) should work.

jbfaden commented 3 months ago

(I think... I know the axis format works for sure. See https://github.com/autoplot/dev/blob/master/demos/2024/20240328/demoDasAxisFormat.jy)

jbfaden commented 3 months ago

Also I verified that the formatter used for the editor does not use sufficient resolution. I'll see if I can fix this, but also you should know that's just the string representation of the datum range model, which does have sufficient resolution.

DiamondJim87 commented 3 months ago

I got it to accept a custom DatumFormatter and that seems to work when I display the plot. However, the property editor still rounds to 6 digits.

DiamondJim87 commented 3 months ago

Oh, that's what you just said...

jbfaden commented 3 months ago

Yep, I'll have a look at that now.

DiamondJim87 commented 3 months ago

Just checking to see if you've learned anything about this one.

jbfaden commented 3 months ago

Ugh--completely forgot! I should be able to look at this more tomorrow.

jbfaden commented 3 months ago

DatumRange.java has a toString method which I've changed. It now parses the result of the two formatted Datums and compares their value. If they are equal then the resolution on the two formatted Datums is set to 1/100th of the width and the Datums are reformatted. Also an extraneous space when Units.dimensionless are used is removed.

DiamondJim87 commented 3 months ago

This looks good in general, but unfortunately, it does not help the current problem. The axis in question is plotting units of time, so I think it takes the other branch in the toString, which does what it used to do. The new code is not getting called in our case.

I assume that this can eventually be made to do what you intended and it would be helpful for sure. But I foresee another problem that changing DatumRange.toString() would not help. The code we have that saves and restores the state of plots uses reflection to store the state of the whole bean. This includes datumRange, but also includes dataMinimum and dataMaximum. Fixing the formatting for DatumRange will not prevent duplicate numbers being stored for dataMinimum and dataMaximum separately. Depending on the order in which properties are restored, which I don't think I can easily control, the minimum and maximum could each be restored separately after the datum range has been set, which would re-introduce the 0-length range problem.

In other words, I think I need a solution that works at the Datum level as well as DatumRange.

jbfaden commented 3 months ago

Yes, let's meet up next week. If you can send a screenshot or the text it has in the editor, that would help me to understand what we're talking about.

jbfaden commented 2 months ago

Jim, I think this is fixed. Would you close this if you agree?

DiamondJim87 commented 2 months ago

No, we never did Zoom about it. I do think the new formatter Is on the right track, but in my case I still don't get enough digits. My question above stands. I need isolated Datum instances to keep enough digits as well as DatumRange instances. I have an obligation here from 12:00 to 1:00 EDT (11-12 CDT) but I could Zoom sometime in the afternoon.

jbfaden commented 2 months ago

Kind of a busy day, but maybe I can meet up. I'll see if I can demo the bug you mean and we can go from there.

DiamondJim87 commented 2 months ago

Should have said, this is important but not urgent, could easily wait until tomorrow or next week, but I don't want to forget about it...

jbfaden commented 2 months ago

I wonder if you are using a PropertyEditor to edit the two datums which define the range of the axis, using the dataMaximum and dataMinimum properties. Or, where are you running into this problem when Datums are formatted? The following Autoplot script may demo the problem, too:

d= Units.deg.parse('90.000001')
print d    # 90.000 deg

d= datum('2024-04-18T00:00:00.000001')
print d    # 2024-04-18T00:00:00.000Z
DiamondJim87 commented 2 months ago

Yes, this is in the context of a property editor, but it is not limited to that. But yes, a user edits the property to tweak the range and there are not enough digits present for the user to know what to type. (See original description at the top of the page -- there is a little more detail there that we've lost track of as our conversation has evolved).

jbfaden commented 2 months ago

Datums are a bit more challenging than the DatumRanges. The new code there is to look at the formatted min and max and if they are the same, then the resolution is increased. With Datums, I can keep track of the resolution (1.000±0.002), but I would have to infer the resolution when the datum is entered, which I can imagine might cause problems. I'll play with it.

DiamondJim87 commented 2 months ago

Right, I totally get why that's harder. It would just be nice for users if, in the property editor, they could see useful numbers of digits for the individual min and max, not just for the range field. However, as long as they could see and/or edit useful values in the range field, we can live with that. Also, I thought of a way I can work around my other problem (restoring the state of the axis), so please don't go too far down any rabbit holes.

jbfaden commented 2 months ago

I came across these tickets on the Autoplot Sourceforge site: https://sourceforge.net/p/autoplot/bugs/2550/ and https://sourceforge.net/p/autoplot/bugs/143/