<h3 dir="auto">Problem</h3>
<p dir="auto">(A follow-up on <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="933456597" data-permission-text="Title is private" data-url="https://github.com/matplotlib/matplotlib/issues/20548" data-hovercard-type="issue" data-hovercard-url="/matplotlib/matplotlib/issues/20548/hovercard" href="https://github.com/matplotlib/matplotlib/issues/20548">#20548</a>.)</p>
<p dir="auto">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:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="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=&quot;k&quot;)
plt.show()"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-k">import</span> <span class="pl-s1">matplotlib</span>.<span class="pl-s1">pyplot</span> <span class="pl-k">as</span> <span class="pl-s1">plt</span>

<span class="pl-s1">xmin</span>, <span class="pl-s1">xmax</span> <span class="pl-c1">=</span> <span class="pl-c1">-</span><span class="pl-c1">3.0</span>, <span class="pl-c1">3.0</span>
<span class="pl-s1">ymin</span>, <span class="pl-s1">ymax</span> <span class="pl-c1">=</span> <span class="pl-c1">-</span><span class="pl-c1">3.0</span>, <span class="pl-c1">3.0</span>
<span class="pl-s1">nx</span>, <span class="pl-s1">ny</span> <span class="pl-c1">=</span> <span class="pl-c1">500</span>, <span class="pl-c1">500</span>

<span class="pl-k">def</span> <span class="pl-en">f</span>(<span class="pl-s1">z</span>):
    <span class="pl-k">return</span> <span class="pl-s1">np</span>.<span class="pl-en">angle</span>(<span class="pl-s1">z</span>)

<span class="pl-s1">x</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">linspace</span>(<span class="pl-s1">xmin</span>, <span class="pl-s1">xmax</span>, <span class="pl-s1">nx</span>)
<span class="pl-s1">y</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">linspace</span>(<span class="pl-s1">ymin</span>, <span class="pl-s1">ymax</span>, <span class="pl-s1">ny</span>)
<span class="pl-v">X</span>, <span class="pl-v">Y</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">meshgrid</span>(<span class="pl-s1">x</span>, <span class="pl-s1">y</span>)
<span class="pl-s1">fZ</span> <span class="pl-c1">=</span> <span class="pl-en">f</span>(<span class="pl-v">X</span> <span class="pl-c1">+</span> <span class="pl-c1">1j</span> <span class="pl-c1">*</span> <span class="pl-v">Y</span>)

<span class="pl-s1">c</span> <span class="pl-c1">=</span> <span class="pl-s1">plt</span>.<span class="pl-en">contour</span>(<span class="pl-v">X</span>, <span class="pl-v">Y</span>, <span class="pl-s1">fZ</span>, <span class="pl-s1">levels</span><span class="pl-c1">=</span>[<span class="pl-c1">0.7853981633974483</span>], <span class="pl-s1">colors</span><span class="pl-c1">=</span><span class="pl-s">"k"</span>)
<span class="pl-s1">plt</span>.<span class="pl-en">show</span>()</pre></div>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/181628/136400404-756af36f-1441-420b-9708-1983bec5b31b.png"><img src="https://user-images.githubusercontent.com/181628/136400404-756af36f-1441-420b-9708-1983bec5b31b.png" alt="screenshot" style="max-width: 100%;"></a></p>
<p dir="auto">The left "arm" of the contour is wrong. Let's verify this by computing the values:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="for allseg in c.allsegs:
    for seg in allseg:
        x, y = seg.T
        z = x + 1j * y
        print(f(z))"><pre class="notranslate"><span class="pl-k">for</span> <span class="pl-s1">allseg</span> <span class="pl-c1">in</span> <span class="pl-s1">c</span>.<span class="pl-s1">allsegs</span>:
    <span class="pl-k">for</span> <span class="pl-s1">seg</span> <span class="pl-c1">in</span> <span class="pl-s1">allseg</span>:
        <span class="pl-s1">x</span>, <span class="pl-s1">y</span> <span class="pl-c1">=</span> <span class="pl-s1">seg</span>.<span class="pl-v">T</span>
        <span class="pl-s1">z</span> <span class="pl-c1">=</span> <span class="pl-s1">x</span> <span class="pl-c1">+</span> <span class="pl-c1">1j</span> <span class="pl-c1">*</span> <span class="pl-s1">y</span>
        <span class="pl-en">print</span>(<span class="pl-en">f</span>(<span class="pl-s1">z</span>))</pre></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[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]"><pre class="notranslate">[<span class="pl-c1">3.14109133</span> <span class="pl-c1">3.14108931</span> <span class="pl-c1">3.14108728</span> <span class="pl-c1">3.14108523</span> <span class="pl-c1">3.14108316</span> <span class="pl-c1">3.14108107</span>
<span class="pl-c"># ...</span>
 <span class="pl-c1">3.13344468</span> <span class="pl-c1">3.13287655</span> <span class="pl-c1">3.13222326</span> <span class="pl-c1">3.1314641</span>  <span class="pl-c1">3.13057109</span> <span class="pl-c1">3.1295054</span>
 <span class="pl-c1">3.12821158</span> <span class="pl-c1">3.12660761</span> <span class="pl-c1">3.12456683</span> <span class="pl-c1">3.12188272</span> <span class="pl-c1">3.1181943</span>  <span class="pl-c1">3.11280868</span>
 <span class="pl-c1">3.10420637</span> <span class="pl-c1">3.08829091</span> <span class="pl-c1">3.04901618</span> <span class="pl-c1">2.8198421</span>  <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span>
 <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span>
 <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span>
<span class="pl-c"># ...</span>
.<span class="pl-c1">78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span>
 <span class="pl-c1">0.78539816</span> <span class="pl-c1">0.78539816</span>]</pre></div>
<p dir="auto">Note that the specified level is <code class="notranslate">0.7853981633974483</code>, so the first half is completely off. <a href="https://github.com/matplotlib/matplotlib/issues/20548#issuecomment-871232335" data-hovercard-type="issue" data-hovercard-url="/matplotlib/matplotlib/issues/20548/hovercard">A previous comment</a> suggests that the contouring algorithm is right, though.</p>
<p dir="auto">To fix this, I manually set the corresponding segments to <code class="notranslate">np.nan</code> which prevents plotting. However, this does <em>not</em> work for tricontour as I don't have a function <code class="notranslate">f()</code> 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.</p>
<p dir="auto">I tried to get a contour plot of the complex angles of a particular function, but always got one level too many around zeros and infinities. Consider the following MWE which is supposed to plot the contour line for <code class="notranslate">pi / 4</code> only. It plots <code class="notranslate">pi / 4</code> alright, but also <code class="notranslate">pi</code>.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="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

x = np.linspace(xmin, xmax, nx)
y = np.linspace(ymin, ymax, ny)
X, Y = np.meshgrid(x, y)
fZ = np.angle(X + 1j * Y)

plt.contour(X, Y, fZ, levels=[0.25 * np.pi], colors=&quot;k&quot;)
plt.gca().set_aspect(&quot;equal&quot;)
plt.show()"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-k">import</span> <span class="pl-s1">matplotlib</span>.<span class="pl-s1">pyplot</span> <span class="pl-k">as</span> <span class="pl-s1">plt</span>

<span class="pl-s1">xmin</span>, <span class="pl-s1">xmax</span> <span class="pl-c1">=</span> <span class="pl-c1">-</span><span class="pl-c1">3.0</span>, <span class="pl-c1">3.0</span>
<span class="pl-s1">ymin</span>, <span class="pl-s1">ymax</span> <span class="pl-c1">=</span> <span class="pl-c1">-</span><span class="pl-c1">3.0</span>, <span class="pl-c1">3.0</span>
<span class="pl-s1">nx</span>, <span class="pl-s1">ny</span> <span class="pl-c1">=</span> <span class="pl-c1">500</span>, <span class="pl-c1">500</span>

<span class="pl-s1">x</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">linspace</span>(<span class="pl-s1">xmin</span>, <span class="pl-s1">xmax</span>, <span class="pl-s1">nx</span>)
<span class="pl-s1">y</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">linspace</span>(<span class="pl-s1">ymin</span>, <span class="pl-s1">ymax</span>, <span class="pl-s1">ny</span>)
<span class="pl-v">X</span>, <span class="pl-v">Y</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">meshgrid</span>(<span class="pl-s1">x</span>, <span class="pl-s1">y</span>)
<span class="pl-s1">fZ</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">angle</span>(<span class="pl-v">X</span> <span class="pl-c1">+</span> <span class="pl-c1">1j</span> <span class="pl-c1">*</span> <span class="pl-v">Y</span>)

<span class="pl-s1">plt</span>.<span class="pl-en">contour</span>(<span class="pl-v">X</span>, <span class="pl-v">Y</span>, <span class="pl-s1">fZ</span>, <span class="pl-s1">levels</span><span class="pl-c1">=</span>[<span class="pl-c1">0.25</span> <span class="pl-c1">*</span> <span class="pl-s1">np</span>.<span class="pl-s1">pi</span>], <span class="pl-s1">colors</span><span class="pl-c1">=</span><span class="pl-s">"k"</span>)
<span class="pl-s1">plt</span>.<span class="pl-en">gca</span>().<span class="pl-en">set_aspect</span>(<span class="pl-s">"equal"</span>)
<span class="pl-s1">plt</span>.<span class="pl-en">show</span>()</pre></div>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/181628/123930099-b5e27500-d98f-11eb-8339-0864d5f80e7d.png"><img src="https://user-images.githubusercontent.com/181628/123930099-b5e27500-d98f-11eb-8339-0864d5f80e7d.png" alt="screenshot" style="max-width: 100%;"></a></p>
<p dir="auto">This is with mpl 3.4.2.</p>
<p dir="auto"><em>Edit:</em> A very similar report is <a href="https://stackoverflow.com/q/16197171/353337" rel="nofollow">on stackoverflow</a>.</p>