Skip to content

Fix bounds handling when data is int16 or similar formats#2515

Merged
j9ac9k merged 8 commits intopyqtgraph:masterfrom
NilsNemitz:int16fix_squash
Mar 3, 2023
Merged

Fix bounds handling when data is int16 or similar formats#2515
j9ac9k merged 8 commits intopyqtgraph:masterfrom
NilsNemitz:int16fix_squash

Conversation

@NilsNemitz
Copy link
Copy Markdown
Contributor

We try to maintain the original format of the data passed to e.g. PlotDataItem. However, when this is something unconventional like np.int16 (#2513), we occasionally run into trouble when quantities derived from the data then have an unexpected data format.

This PR addresses the issue with reported bounds for data in short integer format, which are not accepted by QtCore.QRectF() later. It does so by simply casting the return of PlotCurveItem.dataBounds() to float. ScatterPlotItem.dataBounds() already performs floating points math on the bounds to account for spot sizes anyway, such that the returned data should be promoted automatically and no explicit cast is required..

A possible concern with the change in this PR is the existance of a test that checks that boolean data gets stored as np.uint8 and that the bounds are returned in the same format. However, the assertion in the test already fails when the tested PlotDataItem is set to draw a scatter plot (symbol='o', pen=None) and I tend to think the additional test for the bounds format simply reflected the expected behaviour at the time.

I have changed the test to reflect the new behaviour of float bounds, and added some additional test cases.

Closes #2513

@pijyoi
Copy link
Copy Markdown
Contributor

pijyoi commented Oct 30, 2022

which are not accepted by QtCore.QRectF() later.

While it is true that QRectF only has an overload that takes all float arguments, that is not the issue of #2513. The small integer arguments are automatically promoted to float.
The issue is that subtraction of the signed integers may create a value that exceeds the dynamic range of the signed type. Unsigned integers have no issue.

In [10]: du = np.array([0, 255], dtype=np.uint8)

In [11]: ds = np.array([-100, 100], dtype=np.int8)

In [12]: du[1] - du[0]
Out[12]: 255

In [13]: ds[1] - ds[0]
<ipython-input-13-d7287f596732>:1: RuntimeWarning: overflow encountered in byte_scalars
  ds[1] - ds[0]
Out[13]: -56

@NilsNemitz
Copy link
Copy Markdown
Contributor Author

Thank you for the clarification! I didn't look into the exact error in QRectF a lot, because the way I would see this problem is this:

In reality, we already treat the return of the bounds calculation as a float value. An example for this is the adjustments for ScatterPlot symbol size, where we don't make any attempt to maintain format. That we don't usually run into trouble with weird data types seems more of a coincidence (and a fundamentally good implementation on the Python and NumPy side) rather than purposeful design on our end. It probably helps that the majority of applications will just naturally feed data in numpy float types.

I switched the bounds data format to float rather than making the rectangle calculations handle the existing input better because I think that is the most robust solution here, helping to avoid problems with invalid developer assumptions in other/future parts of the code. I don't think there's ever a reason to handle this kind of meta-data in the user supplied data format. Support for higher resolution (Decimal?) might have been a motivation, but our plotting is fundamentally limited to what Qt uses internally.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jan 22, 2023

Looks like this PR should be merged, but leave #2513 open?

@pijyoi
Copy link
Copy Markdown
Contributor

pijyoi commented Jan 22, 2023

I realise that in the recently merged #2586 and #2587, I also didn't take care of this possibility when computing the bounding rectangle.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jan 23, 2023

I realise that in the recently merged #2586 and #2587, I also didn't take care of this possibility when computing the bounding rectangle.

A PR for those edge cases would be appreciated but it's hardly expected that a PR to cover edge cases on a calculation will cover all edge cases.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Mar 3, 2023

Thanks @NilsNemitz for the PR and thanks @pijyoi for the feedback on the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Overflow when computing data bounds for small signed integer data types

3 participants