← 返回首页
Remove threshold from SubPlot.auto_scale by cassiersg · Pull Request #810 · fastplotlib/fastplotlib · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus

Remove threshold from SubPlot.auto_scale#810

Open
cassiersg wants to merge 1 commit into
fastplotlib:mainfrom
cassiersg:auto_scale
Open

Remove threshold from SubPlot.auto_scale#810
cassiersg wants to merge 1 commit into
fastplotlib:mainfrom
cassiersg:auto_scale

Conversation

Copy link
Copy Markdown

From what I could see, the threshold was arbitrary. It is also not clear that any non-zero value should be a threshold, since all computations should work over the full range of a 32-bit float.

Copy link
Copy Markdown
Member

I'm pretty sure this was due to floating point error where the width and height can be very close to zero after extensive panning and zooming.

Copy link
Copy Markdown
Author

That seems likely indeed, but it seems like a quick fix that does not work in general, since it is reasonable for an axis to have very small values when showing scientific data (a nice plot would often benefit from proper units like ns instead of showing 1e-9 values, but in practice the latter is very common).

If this is an error caused by ill-conditioning after zooming and panning, I think that it should be possible to find better fixes. I also encountered some issues with extensive zooming (see pygfx/pygfx#1081), so I'm interested in finding a proper solution to that problem. Do you have a testcase for the bug that motivated the introduction of this threshold?

Copy link
Copy Markdown
Member

very small values

Ah good point, we'll have to think of a better fix

a nice plot would often benefit from proper units like ns instead of showing 1e-9 values, but in practice the latter is very common.

pint would be a good way to do this, see #729 , setting units on a reference frame (see #772) would probably be a good way to do this.

Copy link
Copy Markdown
Member

np.isclose might be a good way to check

Copy link
Copy Markdown
Author

When comparing to 0.0, that would amount to abs(x) < atol, and the question becomes what atol should be. numpy's default is close to the machine epsilon for 32-bit floats, which is reasonable in some cases, but not applicable in others. It's hard to say what the comparison should be without knowing what it expected. I don't know what are the edge cases to consider. One example would be a scatter plot with a single point: what is the expected behavior in that case?

Copy link
Copy Markdown
Member

Perhaps anything that is 1 bit above float32 0 could work as a threshold? The issue arises when the scene bbox [w, h] = 0, which results in a camera matrix which is unusable.

Copy link
Copy Markdown
Author

By "1 bit above 0", if you mean the smallest non-zero positive float32, this is about 1.175494e-38, and I believe that the check "> 0.0" or ">= 1.175494e-38` are equivalent (ignoring denormals and such).

I can update the PR to go from != 0.0 to > 0.0 (that should be more robust w.r.t. pathological cases like negative values and NaNs).

Copy link
Copy Markdown
Member

Sounds like that should work, hardcoding the binary value should work, 0b0000...1 or something I think, do you want to test it or should I?

Copy link
Copy Markdown
Member

BTW looking at your actual use-case repo, I think your SplitXYController should be possible with the existing pygfx controllers?

And from this example it looks like you're just trying to create a LineCollection, but in a very roudabout way?

https://github.com/cassiersg/scaviz/blob/main/examples/traces_plot.ipynb

If you describe what you're trying to do we can help better.

Copy link
Copy Markdown
Author

Sounds like that should work, hardcoding the binary value should work, 0b0000...1 or something I think, do you want to test it or should I?

I switched to np.finfo(np.float32).smallest_normal (which is approx np.float32(1.1754944e-38)), I think that is it a reasonable value (at that order of magnitude, we keep full precision when computing on GPU).

If you describe what you're trying to do we can help better.

Thanks for the suggestion. I started a discussion here to not derail this thread. (This PR is not discussed there, I noticed this issue when my code was buggy, I don't have a plot with scales below 0.01 anymore - but I expect to have it in the future.)

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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.

2 participants

Footer

© 2026 GitHub, Inc.