Description
Problem
(A follow-up on #20548.)
The purpose of contour and tricontour is to draw contour lines along given levels. The algorithm tries to close the contour loops, but sometimes that's not possible or useful. Example:
import numpy as np
import matplotlib.pyplot as plt
xmin, xmax = -3.0, 3.0
ymin, ymax = -3.0, 3.0
nx, ny = 500, 500
def f(z):
return np.angle(z)
x = np.linspace(xmin, xmax, nx)
y = np.linspace(ymin, ymax, ny)
X, Y = np.meshgrid(x, y)
fZ = f(X + 1j * Y)
c = plt.contour(X, Y, fZ, levels=[0.7853981633974483], colors="k")
plt.show()
The left "arm" of the contour is wrong. Let's verify this by computing the values:
for allseg in c.allsegs:
for seg in allseg:
x, y = seg.T
z = x + 1j * y
print(f(z))
[3.14109133 3.14108931 3.14108728 3.14108523 3.14108316 3.14108107
# ...
3.13344468 3.13287655 3.13222326 3.1314641 3.13057109 3.1295054
3.12821158 3.12660761 3.12456683 3.12188272 3.1181943 3.11280868
3.10420637 3.08829091 3.04901618 2.8198421 0.78539816 0.78539816
0.78539816 0.78539816 0.78539816 0.78539816 0.78539816 0.78539816
0.78539816 0.78539816 0.78539816 0.78539816 0.78539816 0.78539816
# ...
.78539816 0.78539816 0.78539816 0.78539816 0.78539816 0.78539816
0.78539816 0.78539816]
Note that the specified level is 0.7853981633974483
, so the first half is completely off. A previous comment suggests that the contouring algorithm is right, though.
To fix this, I manually set the corresponding segments to np.nan
which prevents plotting. However, this does not work for tricontour as I don't have a function f()
that I can evaluate at the segments. The contouring algorithm itself must compute the values somewhere, so my suggestion would be to expose those values to the user.