Skip to content
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

plt.contour levels parameter don't work as intended if receive a single int #11913

Closed
eisterman opened this Issue Aug 22, 2018 · 5 comments

Comments

Projects
None yet
5 participants
@eisterman
Copy link

eisterman commented Aug 22, 2018

Bug report

Bug summary

The official documentation (https://matplotlib.org/api/_as_gen/matplotlib.pyplot.contour.html) says that the parameter levels of the pyplot.contour function is an integer will be calculated and shown a number of contours equal to the number passed as a parameter.
The reality of the facts, however, is that the outline associated with the past value is plotted.

Code for reproduction

I used the contour demo example from https://matplotlib.org/gallery/images_contours_and_fields/contour_demo.html#contour-demo adding the levels parameter as int.

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.pyplot as plt

delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
# the original demo had 2 here, but so most of the values would have been less than 5
Z = (Z1 - Z2) * 6

plt.contour(X, Y, Z, levels=5)
plt.show()

Actual outcome

Output_bug_1

Expected outcome

According to official documentation I should expect 5 outlines and not the boundary associated with the value 5.
Right_outcome_1

The expected output was obtained by modifying the penultimate line in:

plt.contour(X, Y, Z, levels=np.linspace(np.min(Z),np.max(Z),7))

Matplotlib version

  • Operating system: Arch Linux
  • Matplotlib version: 2.2.3
  • Matplotlib backend (print(matplotlib.get_backend())): Qt5Agg
  • Python version: 3.7.0
  • Other libraries: numpy

All libraries have been installed via the official ArchLinux repository

@jklymak

This comment has been minimized.

Copy link
Contributor

jklymak commented Aug 22, 2018

Yeah, this is a bit funky. It works fine if you do: plt.contour(X, Y, Z, 5). So if you specify levels as a kwarg, it assumes you have entered the actual levels you want contoured. Its debatable if this is desirable or not - I'd vote for it being undesirable, and levels=5 should behave as you expected it should (i.e. the same as if 5 was passed in as a positional argument), but maybe the original authors had a reason for this behaviour.

I would say that levels=[5] should only make one contour.

@jklymak jklymak added this to the v3.1 milestone Aug 22, 2018

@jklymak

This comment has been minimized.

Copy link
Contributor

jklymak commented Aug 22, 2018

Milestoning 3.1, since this behaviour has been present since at least 2.0.2

@tacaswell

This comment has been minimized.

Copy link
Member

tacaswell commented Aug 22, 2018

I think @efiring changed some of this for 3.0 already.

@jklymak

This comment has been minimized.

Copy link
Contributor

jklymak commented Aug 22, 2018

Well, yes. Its worse (?) on master:

Traceback (most recent call last):
  File "testCont.py", line 15, in <module>
    plt.contour(X, Y, Z, levels=5)
  File "/Users/jklymak/matplotlib/lib/matplotlib/pyplot.py", line 2544, in contour
    __ret = gca().contour(*args, data=data, **kwargs)
  File "/Users/jklymak/matplotlib/lib/matplotlib/__init__.py", line 1763, in inner
    return func(ax, *args, **kwargs)
  File "/Users/jklymak/matplotlib/lib/matplotlib/axes/_axes.py", line 6209, in contour
    contours = mcontour.QuadContourSet(self, *args, **kwargs)
  File "/Users/jklymak/matplotlib/lib/matplotlib/contour.py", line 887, in __init__
    kwargs = self._process_args(*args, **kwargs)
  File "/Users/jklymak/matplotlib/lib/matplotlib/contour.py", line 1499, in _process_args
    x, y, z = self._contour_args(args, kwargs)
  File "/Users/jklymak/matplotlib/lib/matplotlib/contour.py", line 1569, in _contour_args
    self._contour_level_args(z, args)
  File "/Users/jklymak/matplotlib/lib/matplotlib/contour.py", line 1255, in _contour_level_args
    if len(self.levels) > 1 and np.min(np.diff(self.levels)) <= 0.0:
TypeError: len() of unsized object
@efiring

This comment has been minimized.

Copy link
Member

efiring commented Aug 22, 2018

I see where the problem is.

@efiring efiring self-assigned this Aug 22, 2018

efiring added a commit to efiring/matplotlib that referenced this issue Aug 23, 2018

@QuLogic QuLogic modified the milestones: v3.1, v3.0 Aug 23, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.