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

Hatching color in contourf function. #2789

Closed
guziy opened this issue Feb 4, 2014 · 10 comments
Closed

Hatching color in contourf function. #2789

guziy opened this issue Feb 4, 2014 · 10 comments

Comments

@guziy
Copy link

guziy commented Feb 4, 2014

It is possible to do hatching of regions using contourf function in matplotlib. Below is a working example I took from the matplotlib website. What I would like to do is to change the color of the hatching if it is possible. I tried to specify edgecolor, color and facecolor but it does not seem to work.. Thanks

import matplotlib.pyplot as plt
import numpy as np
# invent some numbers, turning the x and y arrays into simple
# 2d arrays, which make combining them together easier.
x = np.linspace(-3, 5, 150).reshape(1, -1)
y = np.linspace(-3, 5, 120).reshape(-1, 1)
z = np.cos(x) + np.sin(y)

# we no longer need x and y to be 2 dimensional, so flatten them.
x, y = x.flatten(), y.flatten()

# a plot of hatches without color with a legend
plt.figure()
n_levels = 6
plt.contour(x, y, z, n_levels, colors='black', linestyles='-')
cs = plt.contourf(x, y, z, n_levels, colors='none',
                  hatches=['.', '/', '\\', None, '\\\\', '*'],
                  extend='lower', edgecolor = "r", facecolor="blue", color = "red"
                  )

# create a legend for the contour set
artists, labels = cs.legend_elements()
plt.legend(artists, labels, handleheight=2)

plt.savefig("mpl_test.jpeg")
@pelson
Copy link
Member

pelson commented Feb 10, 2014

Afraid not. It can obviously be controlled by drawing the contour twice, but that doesn't answer your question. This is high on my personal TODO list, but then my personal TODO is pretty large 😄...

Anyway, I hope having an answer (even if it is a negative) is helpful. I'm going to go ahead and close the issue as it is the kind of feature which I'd love to see, but isn't a bug so to speak.

Cheers!

@pelson pelson closed this as completed Feb 10, 2014
@guziy
Copy link
Author

guziy commented Feb 10, 2014

Thank you Phil)) Cheers

@fmaussion
Copy link
Contributor

Hi @pelson , what about renaming the issue to a Feature Request and leave it open, just in case someone feels like implementing it? ;-)

Would it be difficult to do? I have only a superficial knowledge of mpl internals...

@WeatherGod
Copy link
Member

Hatching gets a bit hairy because it is implemented differently in the
vector backends than it is in the AGG-based backends. This might be more
accessible now, though, than it was previously now that the macosx backend
has been reworked to be AGG based (there were all sorts of inconsistencies
with hatches in the macosx backend before).

On Fri, May 27, 2016 at 10:23 AM, Fabien Maussion notifications@github.com
wrote:

Hi @pelson https://github.com/pelson , what about renaming the issue to
a Feature Request and leave it open, just in case someone feels like
implementing it? ;-)

Would it be difficult to do? I have only a superficial knowledge of mpl
internals...


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#2789 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AARy-E6j_vWzcYXSIrx9-x_GaVAyjAKmks5qFv5PgaJpZM4BfIv5
.

@hughperkins
Copy link

Hi. How can I change the color of hatching? I see like it might be possible by drawing twic,e but couldnt understand how. currently my graph looks like:

hatching_all_black

@HenryDayHall
Copy link

HenryDayHall commented Mar 26, 2020

So I needed to plot hatched, coloured, contourf areas to denote an excluded region. This was the first hit that google gave me and it set me in the right direction. In case anyone else comes here looking for the same here is how I added colour to the hatching of contourf;

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


def contourf_hatch(*args, data=None, ax=None, hatch_color=None, **kwargs):
    if ax is None:
        ax = plt.gca()
    if hatch_color is None:  # call without modification
        print(f"You did not provide a hatch_color, so no hatch-colouring will be done")
        ax.contourf(*args, data=data, **kwargs)
    elif 'hatches' not in kwargs:  # call without modification
        print(f"You did not provide a hatches argument, so no a normal contourf plot will be made")
        ax.contourf(*args, data=data, **kwargs)
    else:  # everything is avalible to hatch the contours
        invisible_kws = {name: kwargs[name] for name in kwargs}
        invisible_kws['alpha'] = 0.
        invisible_kws.pop('hatches', None)
        contours = plt.contourf(*args, data=None, **invisible_kws)
        hatches = kwargs['hatches']
        for collection in contours.collections:
            path = collection.get_paths()[0]
            path_patch = matplotlib.patches.PathPatch(path,
                                                      edgecolor=hatch_color, hatch=hatches,
                                                      facecolor=(1.,1.,1.,0.), lw=0)
            ax.add_patch(path_patch)
            



if __name__ == '__main__':
    x = [1,2,3,4]
    y = [1,2,3,4]
    m = [[15,14,13,12],[14,12,10,8],[13,10,7,4],[12,8,4,0]]
    contourf_hatch(x, y, m, hatch_color=(0.1, 0.1, 0.8, 0.6), hatches='//', levels=[0., 12.])
    plt.show()

Clearly you will need to adapt it if you want more than one hatch style, or more than one colour.

@scottclowe
Copy link

scottclowe commented Mar 26, 2020

Funnily enough, I was also trying to do coloured hatching with contourf at the same time as @HenryDayHall, and he posted to this 3 year old issue while I was composing my own reply.

Here is how I got contourf with different colour hatching for each level. To do it, you run contourf once, and then loop over all the levels in the output to change the colour of the hatches. This means you can have a different colour for the hatches in each level.

# Content as in example
# ------------------------------
import matplotlib.pyplot as plt
import numpy as np
# invent some numbers, turning the x and y arrays into simple
# 2d arrays, which make combining them together easier.
x = np.linspace(-3, 5, 150).reshape(1, -1)
y = np.linspace(-3, 5, 120).reshape(-1, 1)
z = np.cos(x) + np.sin(y)

# we no longer need x and y to be 2 dimensional, so flatten them.
x, y = x.flatten(), y.flatten()

# a plot of hatches without color with a legend
plt.figure()
n_levels = 6
plt.contour(x, y, z, n_levels, colors='black', linestyles='-')
cs = plt.contourf(
    x, y, z, n_levels, colors='none',
    hatches=['.', '/', '\\', None, '\\\\', '*'],
    extend='lower',
)

plt.title('Before')
plt.savefig("mpl_test_before.jpeg")

# ------------------------------
# New bit here that handles changing the color of hatches
colors = ['maroon', 'red', 'darkorange', 'gold', 'forestgreen',
          'darkturquoise', 'dodgerblue', 'darkviolet']
# For each level, we set the color of its hatch 
for i, collection in enumerate(cs.collections):
    collection.set_edgecolor(colors[i % len(colors)])
# Doing this also colors in the box around each level
# We can remove the colored line around the levels by setting the linewidth to 0
for collection in cs.collections:
    collection.set_linewidth(0.)
# ------------------------------

plt.title('After')
plt.savefig("mpl_test_after.jpeg")

mpl_test_before
mpl_test_after

@annemoree
Copy link

@scottclowe this works for me, thank you! I did notice however that these colors do not show up in the colorbar if you add one. Any suggestions for that?

@scottclowe
Copy link

@annemoree How about this?

It's using legend, like in the original post, instead of colorbar. I wasn't able to get colorbar to work for the base case, so please share example code if it's important to you that it is with a colarbar instead of legend.

# ------------------------------
# Original code like in example
import matplotlib.pyplot as plt
import numpy as np
# invent some numbers, turning the x and y arrays into simple
# 2d arrays, which make combining them together easier.
x = np.linspace(-3, 5, 150).reshape(1, -1)
y = np.linspace(-3, 5, 120).reshape(-1, 1)
z = np.cos(x) + np.sin(y)

# we no longer need x and y to be 2 dimensional, so flatten them.
x, y = x.flatten(), y.flatten()

# a plot of hatches with color with a legend
fig = plt.figure()
n_levels = 6
ax = plt.contour(x, y, z, n_levels, colors='black', linestyles='-')
cs = plt.contourf(
    x, y, z, n_levels, colors='none',
    hatches=['.', '/', '\\', None, '\\\\', '*'],
    extend='lower',
)

# create a legend for the contour set
artists, labels = cs.legend_elements()
# Set the bbox so the legend appears outside the axes
plt.legend(artists, labels, handleheight=2, bbox_to_anchor=(1.04, 1), loc="upper left")

plt.title('Before')
plt.savefig("mpl_test_before.jpeg", bbox_inches="tight")

# ------------------------------
# New code that handles changing the color of hatches

colors = ['maroon', 'red', 'darkorange', 'gold', 'forestgreen',
          'darkturquoise', 'dodgerblue', 'darkviolet']
# For each level, we set the color of its hatch
for i, collection in enumerate(cs.collections):
    collection.set_edgecolor(colors[i % len(colors)])
# Doing this also colors in the box around each level
# We can remove the colored line around the levels by setting the linewidth to 0
for collection in cs.collections:
    collection.set_linewidth(0.)

# ---------------
# Handle creating legend with colors of hatches as in the figure

# create a legend for the contour set
artists, labels = cs.legend_elements()
# For each level, we set the color of its hatch in the legend too
for i, artist in enumerate(artists):
    artist.set_edgecolor(colors[i % len(colors)])
plt.legend(artists, labels, handleheight=2, bbox_to_anchor=(1.04, 1), loc="upper left")
# This fixes the color of the hatch in the legend, but unfornutately also changes
# the color of the bounding box around it

# ---------------
plt.title('After')
plt.savefig("mpl_test_after.jpeg", bbox_inches="tight")

mpl_test_before
mpl_test_after

@scottclowe
Copy link

How foolish of me! We can of course fix the appearance of the bounding boxes in the legend using the same set_linewidth(0.) trick as used before for the hatches.

# ------------------------------
# Original code like in example
import matplotlib.pyplot as plt
import numpy as np
# invent some numbers, turning the x and y arrays into simple
# 2d arrays, which make combining them together easier.
x = np.linspace(-3, 5, 150).reshape(1, -1)
y = np.linspace(-3, 5, 120).reshape(-1, 1)
z = np.cos(x) + np.sin(y)

# we no longer need x and y to be 2 dimensional, so flatten them.
x, y = x.flatten(), y.flatten()

# a plot of hatches with color with a legend
fig = plt.figure()
n_levels = 6
ax = plt.contour(x, y, z, n_levels, colors='black', linestyles='-')
cs = plt.contourf(
    x, y, z, n_levels, colors='none',
    hatches=['.', '/', '\\', None, '\\\\', '*'],
    extend='lower',
)

# create a legend for the contour set
artists, labels = cs.legend_elements()
# Set the bbox so the legend appears outside the axes
plt.legend(artists, labels, handleheight=2, bbox_to_anchor=(1.04, 1), loc="upper left")

plt.title('Before')
plt.savefig("mpl_test_before.jpeg", bbox_inches="tight")

# ------------------------------
# New code that handles changing the color of hatches

colors = ['maroon', 'red', 'darkorange', 'gold', 'forestgreen',
          'darkturquoise', 'dodgerblue', 'darkviolet']
# For each level, we set the color of its hatch
for i, collection in enumerate(cs.collections):
    collection.set_edgecolor(colors[i % len(colors)])
# Doing this also colors in the box around each level
# We can remove the colored line around the levels by setting the linewidth to 0
for collection in cs.collections:
    collection.set_linewidth(0.)

# ---------------
# Handle creating legend with colors of hatches as in the figure

# create a legend for the contour set
artists, labels = cs.legend_elements()
# For each level, we set the color of its hatch in the legend too
for i, artist in enumerate(artists):
    artist.set_edgecolor(colors[i % len(colors)])
    # Doing this also colors in the bounding box around each level in the legend
    # We can remove the colored line in the legend by setting the linewidth to 0
    artist.set_linewidth(0.)
plt.legend(artists, labels, handleheight=2, bbox_to_anchor=(1.04, 1), loc="upper left")

# ---------------
plt.title('After')
plt.savefig("mpl_test_after.jpeg", bbox_inches="tight")

mpl_test_before
mpl_test_after

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

8 participants