Skip to content

contourf with custom colormap #16629

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

Closed
Skillmon opened this issue Mar 2, 2020 · 9 comments
Closed

contourf with custom colormap #16629

Skillmon opened this issue Mar 2, 2020 · 9 comments

Comments

@Skillmon
Copy link

Skillmon commented Mar 2, 2020

Bug report

Using a custom colormap created with LinearSegmentedColormap.from_list, contourf doesn't seem to use the correct colours for every value.

Code for reproduction

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap


def color_grid(xx, classes):
    x = xx.ravel()
    Z = np.zeros(x.shape)
    dx = (x.max() - x.min())/classes
    for i in range(classes):
        Z[(i * dx <= x) & ((i + 1) * dx >= x)] = i
    return Z.reshape(xx.shape)


colors = ['b',
          'r',
          'm',
          'c',
          'g',
          'xkcd:orange',
          'xkcd:peach',
          'xkcd:bright pink',
          'xkcd:crimson']


xx, yy = np.meshgrid(np.arange(0, 10, 0.02), np.arange(0, 10, 0.02))
fig, sub = plt.subplots(len(colors)-1, 1)

for i, ax in enumerate(sub.flatten()):
    cm = LinearSegmentedColormap.from_list('foo', colors[0:i+2], i+2)
    Z = color_grid(xx, i+2)
    ax.contourf(xx, yy, Z, cmap=cm)
plt.show()

Actual outcome

mwe

Expected outcome

I expected the colours to be correctly picked, meaning an increasing number of different colours in each subplot from top to bottom with each bar in a row roughly the same size (since that's what Z should look like).

Matplotlib version

  • Operating system: Arch Linux
  • Matplotlib version: 3.1.3
  • Matplotlib backend (print(matplotlib.get_backend())): PGF with PDF output, GTK3Agg
  • Python version: 3.8.1
  • Other libraries: numpy

Installed from Arch Linux repositories.

@Skillmon
Copy link
Author

Skillmon commented Mar 3, 2020

Oh, and even with levels=i+2 the colours aren't set reliably.

@ImportanceOfBeingErnest
Copy link
Member

There is a beating of two different discretisations, the manual one and the one from contour, right?

So if you create an image plot, i.e. replace ax.contourf(xx, yy, Z, cmap=cm) by ax.imshow(Z, aspect="auto", cmap=cm) it will show the expected colors

image

If using a contour plot, the contours will only be at the discretization levels if exactly those levels are chosen when calling it (else it wouldn't know about that explicit desire).

ax.contourf(xx, yy, Z, levels=np.linspace(0,Z.max(),i+2+1), cmap=cm)

image

Closing this, as there is no bug apparent here, but feel free to discuss further if I'm misunderstanding.

@Skillmon
Copy link
Author

Skillmon commented Mar 3, 2020

Well, I only used that data to simplify the MWE, in my actual use case I'm trying to visualise the results of an SVM. And I beg you pardon but if I have data with $n$ distinct $Z$ values and say there will be $n$ levels, the results of contourf should show $n$ differently coloured areas.

@ImportanceOfBeingErnest
Copy link
Member

The colored areas are in between the levels. So to get n colors one needs n+1 levels. But if an integer, the levels argument will only determine an approximate number, provided by the output of a MaxNLocator. See issue #12729 and PR #16534 for the corresponding docstring fix.

@Skillmon
Copy link
Author

Skillmon commented Mar 3, 2020

Ok, specifying as a list does work, still I find the behaviour with levels=<int> weird when $Z$ has exactly $n$ distinct levels.

@timhoffm
Copy link
Member

timhoffm commented Mar 3, 2020

Just as a remark, a similar plot can be created in a single axes using a horizontal bar chart:
See https://matplotlib.org/gallery/lines_bars_and_markers/horizontal_barchart_distribution.html

@ImportanceOfBeingErnest
Copy link
Member

The reason for this is that you rarely want some odd levels like

image

but rather some nice levels like

image

@Skillmon
Copy link
Author

Skillmon commented Mar 3, 2020

@timhoffm this is just an oversimplification for the sake of an MWE, I need contourf as it is used to show the class borders of an SVM.

@Skillmon
Copy link
Author

Skillmon commented Mar 3, 2020

@ImportanceOfBeingErnest Thank you very much for your patience with me and the explanations where I misunderstood the documentation. Everything seems clear to me now :)

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

No branches or pull requests

3 participants