Skip to content

Gracefully handle non-finite z in tricontour (issue #10167) #14040

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

Merged
merged 5 commits into from
May 29, 2019

Conversation

ianthomas23
Copy link
Member

tricontour and tricontourf expect a z array containing finite values, so no np.nan, np.inf or masked values. Up until now this has not been checked and a non-finite value causes a segmentation fault in the underlying C++ code.

This bug was reported in issue #10167.

The fix is to explicitly check for non-finite values and raise an exception. The only complexity is that a triangulation may not include all the specified points and so we only need to check those points that are included in the triangulation.

Fix includes tests for np.inf, -np.inf, np.nan and np.mamasked values.

Copy link
Member

@jklymak jklymak left a comment

Choose a reason for hiding this comment

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

Does it make sense to just check the raw data so the expensive triangulation step is not performed first? I understand your point that a masked point may not end up in the triangulation, but that seems an edge case.

Second, I'd have thought NaN/masked values would just not get included in the algorithm rather than throwing an error.

Third, why are you calling min/max on data that isn't in the triangulation?

@ianthomas23
Copy link
Member Author

ianthomas23 commented Apr 25, 2019 via email


with pytest.raises(ValueError) as excinfo:
plt.tricontourf(triang, [0, 1, 2, np.inf])
excinfo.match(r'z array cannot contain non-finite values')
Copy link
Member

Choose a reason for hiding this comment

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

You can also pass the match string as a parameter to pytest.raises.

@tacaswell
Copy link
Member

Every time I visit tricontour.py I discover that there have been many modifications to the comparable code in contour.py without any consideration of tricontour.py, and I have to try to bring it back in line.

Will keep that in mind in future reviews, sorry about that.

@tacaswell tacaswell added this to the v3.2.0 milestone Apr 26, 2019
triang = mtri.Triangulation(x, y)
plt.figure()

with pytest.raises(ValueError) as excinfo:
Copy link
Member

Choose a reason for hiding this comment

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

To elaborate on the below comment, this can just be

with pytest.raises(ValueError, match='z array cannot contain non-finite values'):

and the match line below can be removed

Copy link
Member Author

Choose a reason for hiding this comment

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

@timhoffm and @dstansby Thanks for the info on the match parameter in pytest.raises. I've changed the test code to use this improved approach.

Copy link
Member

@efiring efiring left a comment

Choose a reason for hiding this comment

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

Just the two suggestions for more accurate error messages.

# in the triangulation.
z_check = z[np.unique(tri.get_masked_triangles())]
if np.ma.is_masked(z_check):
raise ValueError('z cannot be a masked array')
Copy link
Member

Choose a reason for hiding this comment

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

This might be misleading. Maybe, "z must not contain masked points within the triangulation".

if np.ma.is_masked(z_check):
raise ValueError('z cannot be a masked array')
if not np.isfinite(z_check).all():
raise ValueError('z array cannot contain non-finite values')
Copy link
Member

Choose a reason for hiding this comment

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

Similarly, maybe "z array must not contain non-finite values within the triangulation".

@efiring
Copy link
Member

efiring commented May 25, 2019

@ianthomas23 I would like to get this merged within a very few days so that it will be included in the release that @tacaswell is planning. Would you like to make the small error message changes I suggested? Or do you prefer that I do it? Or that they be left as they are?

@ianthomas23
Copy link
Member Author

@efiring I am happy to make your proposed changes and was intending to do so on Tuesday. If you would like to do so yourself before then that is fine by me. I think there will also need to be corresponding textual changes in the test code.

@efiring
Copy link
Member

efiring commented May 25, 2019

Thank you, Tuesday will be fine.

@ianthomas23
Copy link
Member Author

@efiring I've changed the error messages.

@timhoffm
Copy link
Member

Please placate flake8:

./lib/matplotlib/tri/tricontour.py:94:80: E501 line too long (80 > 79 characters)

@efiring efiring merged commit 765d452 into matplotlib:master May 29, 2019
@tacaswell
Copy link
Member

@meeseeksdev backport to v3.1.x

meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull request Jun 10, 2019
@tacaswell tacaswell modified the milestones: v3.2.0, v3.1.1 Jun 10, 2019
ivanov added a commit that referenced this pull request Jun 10, 2019
…040-on-v3.1.x

Backport PR #14040 on branch v3.1.x (Gracefully handle non-finite z in tricontour (issue #10167))
@ianthomas23 ianthomas23 deleted the 10167_tricontour_non_finite_z branch July 8, 2021 18:23
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.

6 participants