[Bug]: contour plot across a level works better than one that merely touches it #20807
Comments
I don't see how such an algorithm would be possible. In order to place a contour between two data points the contour level must be intermediate to them. If they are both bigger than the level the algorithm won't put a contour there. I'm going to close this but few free to request a reopen if you have a suggestion for how this would be possible, or if you like continue discussion at discourse.matplotlib.org. Thanks! |
Sure, but you don't need to apply the intermediate value theorem if the intermediate value (up to FP tolerance) is already part of your data =) In this case, the zeros are in your data set, so you don't need to infer them from a positive/negative pair: >>> import numpy
>>> x = numpy.arange(-1, 1, 0.1)
>>> y = x.reshape(-1,1)
>>> f2 = numpy.abs(x - y)
>>> zeros = numpy.where(f2 == 0)
>>> print(list(zip(zeros[0],zeros[1])))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10), (11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (16, 16), (17, 17), (18, 18), (19, 19)] For contrast, I would not expect you to draw the contour if all of the values were strictly positive (again, up to some tolerance). |
The basic algorithm is described at https://en.wikipedia.org/wiki/Marching_squares As described saddles are particularly troublesome to contour. I really don't think this is a practical limitation of the contouring algorithm for real data. |
@orlitzky In your z-values within quads are essentially bilinearly interpolated by the contouring algorithm. Consider a quad that lies along your diagonal of interest in the grid; two opposite corners of this quad have You are assigning special significance to your particular diagonal of interest when it is not special at all. All quads are treated the same. You could obtain the result you want by using |
Thanks for the extra information! For what it's worth, I've arrived here by way of two SageMath bug reports / use cases, the most compelling of which implicitly plots a complex Maybe in this case we can simply preprocess the data, though, and see if all of the z points lie above or below zero (inclusive). If so, the points where it touches zero (up to some tolerance...) should be the nodes of a polygon that describe the contour. I will play around a bit. |
Bug summary
Sorry for the incomprehensible summary; an example best illustrates the problem. When creating a (contour) plot of the zeros of e.g.
f(x,y) = x - y
, you get what you'd expect: the liney=x
in the plane. But if instead you plot the zeros ofabs(x - y)
, which has the exact same zero set, then you get an empty plot.You can try perturb the
levels=[0]
to something likelevels=[-1e-4,1e-4]
to work around the problems inherent with comparing floating point numbers... but no matter what you do, the result still looks worse than the plot ofx-y
. (And the choice of1e-4
depends on the function.)Code for reproduction
Actual outcome
Expected outcome
If I'm being extremely optimistic, then the expected outcome of the second (and third?) plot is the same as the first.
Operating system
Gentoo linux
Matplotlib Version
3.4.2
Matplotlib Backend
TkAgg
Python version
3.9.6
Jupyter version
N/A
Other libraries
No response
Installation
Linux package manager (Debian/Fedora/etc.)
Conda channel
No response
The text was updated successfully, but these errors were encountered: