Skip to content

Allow multiple hatch colors in same figure #7901

Closed

Description

@Zaharid

In version 2.0 the hatching defaults have changed. In particular, the color is always black by default and it is now inconvenient to restore the old way in which the colors are set (based on the artist line color at least for fill_between).

I'd like to request a hatchcolor parameter for the functions that accept hatches.

Activity

  1. Zaharid commented on Jan 23, 2017

    @Zaharid
    Author

    To make matters worse, it looks to me that the hatch color is hardcoded in the backend in such a way that it's not possible to have more than one hatch color. Therefore I don't know how to produce a figure like this with mpl2:
    http://pcteserver.mi.infn.it/~nnpdf/validphys-reports/X-vnmR5BSRygX3qoK9NtFQ==/figures/norm_plot_pdfs_bard.pdf

  2. modified the milestones: , on Jan 26, 2017
  3. added
    Release criticalFor bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.
    on Jan 26, 2017
  4. tacaswell commented on Jan 26, 2017

    @tacaswell
    Member

    #7059 is roughly related

  5. andim commented on Jan 28, 2017

    @andim
    Contributor

    I've also encountered the same problem. It seems that PR #7415 broke what I believe should be a supported functionality, i.e. using hatching with different colors within one figure. I want to add further support for the Zaharid's suggestion of adding a kw argument for addressing this issue.

    Otherwise I think it might even be preferable to revert the PR. There is a slight gain of convenience from being able to set a global default hatching color, but a net loss in functionality. (Plotting with hatch color != edgecolor could also be achieved before by plotting the artist twice once with hatching and once without.)

  6. tacaswell commented on Jan 28, 2017

    @tacaswell
    Member

    That #7415 fixed #7166 which was hatches not showing up in the legend so it can not be reverted.

    The fix for 2.0.1 could be:

    • add a set_hatch_color method to gc base with semantics of None -> get the rcParam, else use the color
    • add private _hatchcolor to the artists that know about hatches
    • when we set edge color also set _hatchcolor
    • ever place with call set_hatch we also call set_hatch_color

    This will give the behavior of:

    • by default use the rcParam
    • if user explicitly set edge color use it for hatch

    I want to hold off adding the hachcolor kwarg until 2.1, as that also implies adding get_hatchcolor/set_hatchcolor which is a bit much for a micro-release. There would also need to be a couple decisions made for how to 'latch' 'color', 'edgecolor', and 'hatchcolor' together

  7. ImportanceOfBeingErnest commented on Jan 30, 2017

    @ImportanceOfBeingErnest
    Member

    I fully endorse this request to have an interface to the hatch's color, linestyle, linewidth, alpha etc. The feature to control those parameters has been present in previous versions (at least color and linewidth) and it was a big mistake to change this.

    Let me elaborate a bit on the necessity of controling the hatch.
    Historically hatch has been mainly used to provide an option to distinguish shapes in black/white documents, which makes it somehow understandable to tie it to the backend and hardcode the properties.
    However, today most information is shared online, viewable in color and expectations for visually appealing figures is ever growing. On the other hand, figures are still printed in black and white and there is a growing awareness of the problems of limited color vision, such that at least in some areas institutions are forced to provide their information in an accessible way. As I understand it, some of the features introduced with matplotlib 2.0 were highly motivated by those requirements.
    How does this relate to hatching? Hatching makes it incredibly easy to produce visually appealing and yet accessible figures.

    text8119-1

    Another point is of course that different styled hatching allows to add a new dimension to a figure. What is linecolor, linestyle and linewidth in 1D is patchcolor and hatch in 2D. Controlling the hatch is therefore utterly important.

  8. tacaswell commented on Feb 1, 2017

    @tacaswell
    Member

    @ImportanceOfBeingErnest Can you open a new issue with that? That sort of effect maybe beyond the scope of what the hatching can currently do (or maybe we only need linewidth?). I think a MEP (https://github.com/matplotlib/matplotlib/tree/master/doc/devel/MEP) proposing an API for what this would look like and how to implement it across all of the backends would be well received. Given that you have clearly thought about this, can you take a crack at that?

  9. ImportanceOfBeingErnest commented on Feb 1, 2017

    @ImportanceOfBeingErnest
    Member

    I don't think we need a new issue here, it is exactly what @Zaharid is asking for:
    Getting control over hatchcolor and hatchlinewidth.
    I'm saying that extending this to include alpha and hatch density would be good.

    The plot from above can actually be reproduced in matplotlib 2.0 in a very hacky way. The only thing really missing here is the ability to change hatchcolor, hatchlinewidth and density via the api.

    import matplotlib.pyplot as plt
    import matplotlib.hatch
    plt.rcParams['hatch.color'] = '#aa007d'
    plt.rcParams['hatch.linewidth'] = 25
    
    class MyHatch(matplotlib.hatch.NorthEastHatch):
        def __init__(self, hatch, density):
            # chose some parameter that give desired result
            self.num_lines = 2 
            self.num_vertices = 6
    
    matplotlib.hatch._hatch_types.append(MyHatch)
    
    plt.bar([1], [3], color="#000177", edgecolor="#000177",  linewidth=10)
    plt.bar([2], [2], color=None, edgecolor="#770058",  linewidth=10)
    # using the fact, that if hatch is not recognized, last list item is chosen.
    plt.bar([2], [2], color="#770058", hatch="unknown" )
    
    plt.savefig(__file__+".png")
    plt.show()
    

    so_hatch2_small py

  10. changed the title [-]Add API to manage hatches[/-] [+]Allow multiple hatch colors in same figure[/+] on Feb 2, 2017
  11. tacaswell commented on Feb 2, 2017

    @tacaswell
    Member

    Fair, I had not grasped how useful the hatch.linewidth parameter was or hacking at the underyling hatch mechanism like that. I have been working on this project for ~4 years and I still am learning more details about how it works :-p

    However, your comment about how hatch selection works is not quite correct, see https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/hatch.py#L194 . It creates hatch objects for all of the hatch types it know about and merges them. It happens that MyHatch does not correctly return a null-hatch when it should. Also, your example does not work for me

    hatch_test py

    I would like to significantly narrow the scope of this issue to be fixing the no-multi-color-hatch regression in 2.0 and am asking for a new issue to work through all of the hatch-related knobs that will need to be added and which bits of configuration that are currently hard-coded or global parameters need to be pulled up to artist-level configuration.

  12. mangecoeur commented on Feb 14, 2017

    @mangecoeur

    Just to chime in, there is a nice example of setting per-patch hatching color here under the 'Colors' section, which worked in 1.5 but doesn't in 2.0 .

    As others have pointed out, if you want a plot that works both in color and in black and white it's critical to be able to adjust the hatch color for each patch (and eventually all sorts of other things too like width and spacing etc)

  13. tacaswell commented on Feb 14, 2017

    @tacaswell
    Member

    @mangecoeur This should work again in 2.0.1 (fixed by #7976)

  14. tacaswell commented on Feb 14, 2017

    @tacaswell
    Member

    (that is when we release 2.0.1)

  15. hughperkins commented on Apr 1, 2017

    @hughperkins

    Hi. What is preferred way to achieve colored hatch currently? Currently my graph looks like:

    hatching_all_black

    From reading above, it looks like:

    • colored hatching used to work, in some versoin in the past, and
    • colored hatching works again, in not-yet-released 2.0.1

    Should I better:

    • rollback to an older version of matplotlib (which version?), eg using pip? , or
    • somehow install matplotlib from github master branch?
  16. hughperkins commented on Apr 1, 2017

    @hughperkins

    (Ok, I rolled back to 1.5.3. That has its own issues, ie bar positioning, but fixes the hatch colors:

    hatch_colored

    (edit: and a quick align='center' fixes the positioning change:

    aligned_and_colored

  17. tacaswell commented on Apr 2, 2017

    @tacaswell
    Member

    @hughperkins Your understanding is correct and those are the two options. 2.0.1 should be very soon.

  18. kasekun commented on May 20, 2017

    @kasekun

    Hi,
    I've been dabbling with the changes to hatching as of 2.0.2. While we now have much better control of the hatch colour (Thanks!). Currently, the only way I can find to remove the background colour and allow different coloured hatching is to set color = None, alpha = 0 in the fill_between args.

    The problem with this is that the legends become useless. Is there something we can use instead to mimic this behaviour without using alpha?

       # Basic example
    from matplotlib import pyplot as plt
    import numpy as np
    
    h1 = '//'
    d1 = np.random.rand(130)
    lab1 = 'Rand1'
    h2 = '\\\\'
    d2 = np.random.rand(200)
    lab2 = 'Rand2'
    
    fig, ax = plt.subplots(1)
    
    def plt_hist(axis, data, hatch, label):
    	counts, edges = np.histogram(data, bins=int(len(data)**.5))
    	edges = np.repeat(edges, 2)
    	hist = np.hstack((0, np.repeat(counts, 2), 0))
    
    	outline, = ax.plot(edges,hist,linewidth=1.3)		
    	axis.fill_between(edges,hist,0,
    				edgecolor=outline.get_color(), hatch = hatch, label=label, 
    				color = None, alpha = 0)  ## < removes facecolor
    
    plt_hist(ax,d1,h1,lab1)
    plt_hist(ax,d2,h2,lab2)
    ax.legend()
    ax.set_ylim(0,ax.get_ylim()[1])
    

    fill_between

  19. QuLogic commented on May 20, 2017

    @QuLogic
    Member

    Use facecolor='none'; don't mess with alpha.

  20. kasekun commented on May 20, 2017

    @kasekun

    Ugh.... Thanks. I had futilely tried facecolor = None

  21. kamraaan1997 commented on Apr 11, 2022

    @kamraaan1997

    (Ok, I rolled back to 1.5.3. That has its own issues, ie bar positioning, but fixes the hatch colors:

    hatch_colored

    (edit: and a quick align='center' fixes the positioning change:

    aligned_and_colored

    Can you please help in this plot to generate the legends where edgecolor and hatch color are different in the unfilled bar plot?

  22. tacaswell commented on Apr 11, 2022

    @tacaswell
    Member

    @kamraaan1997 Please open a new issue with a minimal example that shows a bug or if you are looking for support on how to use Matplotlib please post your question to https://discourse.matplotlib.org . Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Release criticalFor bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions