Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Update art3d.py to address strange behavior of depthshading on 3D scatterplots with close points #23085

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 18 commits into from

Conversation

nhansendev
Copy link
Contributor

@nhansendev nhansendev commented May 21, 2022

PR Summary

This update changes the depthshade behavior from the original normalization method to an improved version that behaves well even when points are closely spaced. This addresses issue 22861

I'm not clear on how to run the appropriate pytest unit tests for this file (if any), so I would appreciate some guidance there.

PR Checklist

Tests and Styling

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (install flake8-docstrings and run flake8 --docstring-convention=all).

Documentation

  • New features are documented, with examples if plot related.
  • New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).

This update changes the depthscale behavior from the original Normalize method to an improved version that behaves well even when points are closely spaced.
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a while, please feel free to ping @matplotlib/developers or anyone who has commented on the PR. Most of our reviewers are volunteers and sometimes things fall through the cracks.

You can also join us on gitter for real-time discussion.

For details on testing, writing docs, and our review process, please see the developer guide

We strive to be a welcoming and open project. Please follow our Code of Conduct.

Obliman added 2 commits May 21, 2022 00:44
Fixed line lengths, added handling of zero-length datasets when computing the data scale.
Added a small value to the denominator of the "sats" calculation to avoid division by zero error when plot is empty (scale is zero).
Removed trailing whitespace.
@nhansendev
Copy link
Contributor Author

I think I've addressed the other issues, but am still getting image comparison failures. Is this to be expected when making changes related to how plots are displayed?

@oscargus
Copy link
Member

Is this to be expected

Yes, it is expected. The RMS numbers are quite small, so only a number of pixels.

I will let someone else have a proper say on this, but I believe that we should provide a fallback method for persons relying on the previous appearance. Unless it is obvious that the previous was always incorrect.

@oscargus
Copy link
Member

If you please can provide the resulting figures from e.g. #22861 after applying the changes here, it would simplify the review.

Obliman added 3 commits May 21, 2022 04:13
Renamed get_data_scale and dscl to indicate that they are private, added description of function's purpose, and replaced np.power with np.sqrt.
Forgot this portion of the update earlier. Fixes the alpha draw order flipping as the point depth inverts even though the alpha should not change per point.
Missed the update to _dscl after re-adding code. Updated now.
@nhansendev
Copy link
Contributor Author

If you please can provide the resulting figures from e.g. #22861 after applying the changes here, it would simplify the review.

I've attached some screenshots below showing the updated behavior.

This is with no alpha input, with depth-shading on. You can see how the alpha becomes uniform when depth is uniform (1st image), then fades proportionally to draw depth, including when draw depth reverses (2nd vs 3rd image):
S2
S1
S3

When there is an alpha input (with depthshading on or off), the result is that the slight rotation of the plot no longer results in a sudden flip of alpha values as the depth order reverses:
S4
S5

Note that this behavior is only implemented for Path3DCollection since the bug is related to 3D scatterplots, but may be applicable to other collections if needed.

@nhansendev
Copy link
Contributor Author

nhansendev commented May 21, 2022

I feel like I should explain the comment "# Solid near, transparent far, solid default" further: depending on the equation used for calculating "sats" you can change the behavior of the depth-shading.

The meaning is as follows:
Solid near: shallower datapoints are more/completely opaque
Transparent far: deeper datapoints become increasingly transparent
Solid default: if everything is near equal depth then everything will be opaque

I felt that the other three versions were further from the desireable/existing depth-shading behavior, but could be interesting to include as alternative modes.

Please let me know if you think "mode selection" is a worthwhile inclusion. Mode selection could also allow the old depth-shading behavior to be selected if desired.

@tacaswell tacaswell added this to the v3.7.0 milestone Jun 1, 2022
Only one dataset of (X, Y, Z) needs to be checked for zero length assuming all have the same length.
Instead of using a small constant in the denominator it's cleaner to just check for '_dscl==0' and return ones instead.
This applies for datasets with no datapoints, all the same datapoint such that no scale can be estimated.
Copy link
Member

@QuLogic QuLogic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find some of the comments redundant (as noted); they should describe why, not what.

Fixed some word wrapping, made get_data_scale more compact, replaced _dscl with the more descriptive _data_scale, removed redundant comments, added clearer comments for implementation of shading modes
@airalcorn2
Copy link

Thanks for this. This behavior was driving me crazy.

@tacaswell tacaswell modified the milestones: v3.7.0, v3.8.0 Dec 16, 2022
@tacaswell
Copy link
Member

This is cool work! A couple of requests:

  • can we use an enum (or strings) rather than integers for the modes?
  • can you add a whats_new to show this off?
  • can you add tests?

I have pushed this to the 3.8 milestone.

@nhansendev
Copy link
Contributor Author

  • can we use an enum (or strings) rather than integers for the modes?

Definitely, though I'm not sure what appropriate string representations would be. My previous convention was to summarize behavior as follows: "STS": Solid when shallow, Transparent when deep, Solid default, "STT": Solid when shallow, Transparent when deep, Transparent default, etc.

  • can you add a whats_new to show this off?
  • can you add tests?

Are there guidelines for these/examples I could reference?

Thanks for the suggestions.

@melissawm
Copy link
Member

Hi @Obliman - For the tests, you can take a look at this file which contains the tests for art3d.py. For the what's new, here's the documentation. Let me know if you have other questions. Cheers!

@jklymak jklymak marked this pull request as draft February 6, 2023 20:51
@nhansendev
Copy link
Contributor Author

nhansendev commented Nov 29, 2023

Hi @nhansendev, are you still interested in finishing up this bugfix/feature? Thanks!

Thanks for the reminder, I've made some updates.

I've thought about the changes I had proposed and the whole "different modes" thing was just unnecessarily complicated/probably not that useful. I've since simplified it to be three kwargs:

  1. inverted: whether to progress from opaque to transparent (default) or the opposite
  2. min_alpha: the smallest allowable alpha value (highest transparency)
  3. legacy: whether to use the old algorithm

I've added the "what's new" document and updated other classes to provide access to the user when creating scatter plots or otherwise interacting with Patch3DCollection/Path3DCollection objects.

Edit: one thing I'm still unsure about is whether there are any tests that need to be set up for this. Can anyone provide guidance, please?

@oscargus
Copy link
Member

Yes, I think that there should be some tests for this to make sure that possible later changes does not break the behavior.

One suggestion is to add an image comparison test with a number of subplots, each subplot illustrating some combination of the new behavior.

Looking at the code coverage, I can imagine a 2 x 2 subplot where each combination of legacy/new and inverted/non-inverted is plotted. (Right now, only new and non-inverted seems to be tested.)

For min-alpha one can consider something similar or simply checking the alphas in the resulting collection to confirm that they are as expected (if one can avoid image tests that is slightly better since storing images leads to a rather large repo...).

@oscargus
Copy link
Member

Oh, and for "completeness", one can also call the new get_* methods as part of some test. Simply confirming that they return the expected value.

@tacaswell
Copy link
Member

This is breaking tests that were expecting the old behavior. We either need to manually set the legacy behavior in the tests and add an API change note or we need to set the default to set the default value of depthshade_legacy to True.

Rather than adding a bunch of parameters named depthshade_XXX, we should think of ways to collapse them (either bool + dict or relying on the type of depthshade (suggeted by @ksunden ).

Moving this to 3.10 and should talk about this on the call as soon as 3.9 is branched.

@QuLogic QuLogic modified the milestones: v3.9.0, v3.10.0 Mar 13, 2024
@ksunden ksunden modified the milestones: v3.10.0, v3.11.0 Oct 9, 2024
@scottshambaugh
Copy link
Contributor

Hi @nhansendev, are you still interested in finishing up this PR?

@nhansendev
Copy link
Contributor Author

Hi @nhansendev, are you still interested in finishing up this PR?

Hey, sorry for the delay in response. If someone else wants to tackle the last steps I would appreciate it.

@scottshambaugh
Copy link
Contributor

Sounds good @nhansendev, thank you for the work getting it to this point! I'll finish up the remaining items in #29287

@scottshambaugh
Copy link
Contributor

scottshambaugh commented Dec 13, 2024

Commenting on this PR to notify original authors - what is the use case behind the inverted method? I don't immediately see where it would be desired.

My personal leaning here is to consider the current / legacy behavior a bug that is appropriate to change without backwards compatibility rather than part of the "visual API" we should not break. Removing both those options would simplify the implementation. If there is a reason to have these, I would favor implementing as a rcParam instead of a kwarg.

@nhansendev
Copy link
Contributor Author

Commenting on this PR to notify original authors - what is the use case behind the inverted method? I don't immediately see where it would be desired.

This was trivial to implement, so was added in case someone finds it useful. If it's just adding more work then I think it can be removed.

My personal leaning here is to consider the current / legacy behavior a bug that is appropriate to change without backwards compatibility

I agree that the legacy behavior represents an undesirable visual bug. Keeping backwards compatibility was suggested earlier, but it's probably not going to significantly affect generated plots given it was barely failing the old image tests.

@scottshambaugh
Copy link
Contributor

Fix is merged in, thank you again for the initial work on this!

@nhansendev
Copy link
Contributor Author

Fix is merged in, thank you again for the initial work on this!

Thank you for finishing it 🥇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Waiting for author
Development

Successfully merging this pull request may close these issues.

[Bug]: 3D scatter plot flips alpha order depending on depth relative to camera
9 participants