Skip to content

Fix bound-detection in Axes3D.contour for different-length 1D coordinates #21322

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 415 commits into from

Conversation

DWesl
Copy link
Contributor

@DWesl DWesl commented Oct 8, 2021

PR Summary

Calling Axes3D.contour with 1D X and Y coordinates of different length crashed during bound detection, because that code-path assumed X.size == Y.size. The code added here detects whether the crash would occur, then calls np.meshgrid to make X and Y the same shape.

Fixes #21310.

Makes Axes3D.contour behave more like Axes.contour.

PR Checklist

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (run flake8 on changed files to check).
  • New features are documented, with examples if plot related. (Implied by Axes.contour; DOC Update description of ax.contour method, resolves #21310 #21321 would require changes if this is accepted)
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).
  • Conforms to Matplotlib style conventions (install flake8-docstrings and run flake8 --docstring-convention=all).
  • 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).

timhoffm and others added 30 commits September 16, 2021 23:36
Make rcParams["backend"] backend fallback check rcParams identity first.
Move colormap examples from userdemo to images_contours_and_fields.
DOC: Remove the index and module index pages
`make_norm_from_scale` can be used "inline", rather than as a class
decorator, to dynamically create norm classes.  However, in that case,
the second parameter (`base_norm_cls`) would normally be set to the root
base norm class (`mcolors.Normalize`).  In that case, we should
generate a new `__name__` for the dynamically generated class, to avoid
the slightly confusing situation of having two different classes both
called `mcolors.Normalize`.
in accordance what we've already done in the top-level menu.
- use a marker and no line for the data points
- hard-code yerr instead of using random with a fixed seed
- Slightly move y so that the data points don't always fall on the grid
- Remove "specialized" from section title. There are no more special
  than any other plots.
The original thumbnail margin in gallery.css is 5px. We reduce the
horizontal margin to 2px so that four columns fit within the available
width in the pydata-sphinx-theme.
…ypes

Improve errorbar plot types example
…arg-support-mplot3d

[ENH]: data kwarg support for mplot3d matplotlib#20912
Fix make_norm_from_scale `__name__` when used inline.
Rename section title Gallery -> Examples
Co-authored-by: Thomas A Caswell <tcaswell@gmail.com>
This has been the case since at least mpl2.0, so let's just fix the doc
for now.  Likely there was some confusion with zoom/pan mode, where CTRL
does fix the aspect.
- Most 2D data examples don't need Z.min() subtraction (the
  normalization adjusts itself as needed).
- Tweak spacing in the expression for Z to be the same everywhere.
- Use shorter .min(), .max() methods instead of free functions.
Capitalization fixes in example section titles.
Accepting to call _process_plot_format() (which is unlikely to be the
slowest step here) even in the default case makes the code logic much
simpler.
Simplify/uniformize sample data setup in plot_types examples.
When using the default padding and the pydata-sphinx-theme, the image
is shifted away from the center. While that should be fixed in
sphinx-gallery (and I will report it there), this serves as a workaround
on the matplotlib side, because I don't think they will have it fixed
ready for the 3.5 release.
…ding

DOC: Fix decenter of image in gallery thumbnails
…riented

DOC: clarify what we mean by object oriented in pyplot api
- remove contour plot for simplicity.
- don't set zorder.
- Z doesn't need to be made positive.
Add contour and tricontour plots to plot types
Tweak streamplot plot_types example.
greglucas and others added 21 commits October 5, 2021 19:50
DOC: Fix some lists in animation examples
Now that it's out, we don't need to depend on a random commit.
If it's passed as a keyword argument, then it needs to be removed from
`kwargs`, or not passed again explicitly. Other handling of `snap` uses
`setdefault`, so do that here too.
Allow macosx thread safety test on macOS11
- lut is never modified anymore, so we don't need to copy it.
- Preallocating rgba doesn't help.
- We can rely on np.clip to cast alpha to an array.
It is not possible to queue a draw for a subregion of a widget, so this
crashes. Since 3.5 is feature frozen, disable blitting for now to make
animations work.
cibuildwheel does not support macOS 11 for PyPy.
DOC: Clarify FigureBase.tight_bbox as different from all other artists.
Make `Path.__deepcopy__` interact better with subclasses, e.g. TextPath.
Doing out-of-tree builds makes a copy that breaks symlinks in the git
tree, causing PyPy wheels to get a version that signifies a dirty tree
when they shouldn't.

This will change in pip soon, but changing this will fix the version for
our release now.
Simplify `Colormap.__call__` a bit.
This currently crashes when trying to find the x and y limits.
The autodetection of data limits assumes `X.size == Y.size`.  For 1d X and Y of different length, 
this is the only part that fails.  Catching the exception and setting the limits manually works fine.

I'm not sure whether to fix this in Axes3D.contour or Axes3D.auto_scale_xyz.
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.

@@ -2130,6 +2130,9 @@ def contour(self, X, Y, Z, *args,
cset = super().contour(jX, jY, jZ, *args, **kwargs)
self.add_contour_set(cset, extend3d, stride, zdir, offset)

if np.ndim(X) == 1 and np.ndim(Y) == 1 and len(X) != len(Y):
Copy link
Member

Choose a reason for hiding this comment

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

We do the same thing in axes.pcolormesh and axes.contour. Is this the same logic as those methods? I expect we have a _cbook method to do this.

Copy link
Contributor Author

@DWesl DWesl Oct 9, 2021

Choose a reason for hiding this comment

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

I don't know about a _cbook method, but there's mpl.axes._axes.Axes._pcolorargs, available here as mpl_toolkits.mplot3d.axes3d.Axes._pcolorargs, as well as mpl.contour.QuadContourSet._contour_args, which calls mpl.contour.QuadContourSet._check_xyz. I'm not sure how to get results for the unprojected coordinate system from the QuadContourSet methods, so the simplest way to re-use existing code would probably be calling X, Y, Z, _ = self._pcolorargs("contour", X, Y, Z, shading="gouraud") just after the start of the function.

I misunderstood your message at first and checked Axes3D.contourf and Axes3D.pcolormesh. contourf could use the same fix. Axes3D.pcolormesh fails on render. Should Axes3D.pcolormesh give a more informative error sooner, perhaps pointing people at Axes3D.plot_surface?

Copy link
Member

Choose a reason for hiding this comment

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

I agree that its hard to extricate the contour checks. So the other approach is to simply make auto_scale_xyz accept 1-D arrays for x and y? Maybe by brute-forcing the meshgrid, or by finessing the dataLim update.

Finally if you are going to run a meshgrid, maybe just do at the beginning of contour rather than half way through? Then you save contour also having to make a meshgrid

Copy link
Contributor Author

@DWesl DWesl Oct 12, 2021

Choose a reason for hiding this comment

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

It looks like #21326 is trying to make auto_scale_xyz accept 1-D x and y.

Running meshgrid at the start of contour to avoid duplication of effort with QuadContourSet is a good idea; I'll move that.

@dstansby
Copy link
Member

Thanks for opening! I had a bit of a think, and #21326 is a nicer alternative because we don't end up having to duplicate any broadcasting (that currently lives in QuadContourSet). If #21326 gets merged I think we'll close this, but thanks for opening it and inspiring the alternative PR!

super().contour() will call meshgrid if jX and jY are still 1-D, so making X and Y 2-D before creating jX and jY avoids the duplicate meshgrid calls.
@tacaswell
Copy link
Member

This PR is affected by a re-writing of our history to remove a large number of accidentally committed files see discourse for details.

To recover this PR it will need be rebased onto the new default branch (main). There are several ways to accomplish this, but we recommend (assuming that you call the matplotlib/matplotlib remote "upstream"

git remote update
git checkout main
git merge --ff-only upstream/main
git checkout YOUR_BRANCH
git rebase --onto=main upstream/old_master
# git rebase -i main # if you prefer
git push --force-with-lease   # assuming you are tracking your branch

If you do not feel comfortable doing this or need any help please reach out to any of the Matplotlib developers. We can either help you with the process or do it for you.

Thank you for your contributions to Matplotlib and sorry for the inconvenience.

@QuLogic
Copy link
Member

QuLogic commented Oct 21, 2021

I think this was replaced by #21326.

Thanks for your contribution @DWesl; sorry we did not merge it. We hope this did not discourage you, and hope to hear from you again.

@QuLogic QuLogic closed this Oct 21, 2021
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.

[Bug]: contour on 3d plot fails if x and y are 1d and different lengths