FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Arc patch ignoring theta1/theta2 when added to Axes via PatchCollection · Issue #11266 · matplotlib/matplotlib · GitHub

Repository navigation

Arc patch ignoring theta1/theta2 when added to Axes via PatchCollection #11266

Closed

Description

Bug report

Bug summary

With matplotlib=2.1.2, when I add an Arc patch to an Axes instance via a PatchCollection, the arc always appear as a complete ellipse, regardless of values I set for theta1 and theta2. When I add the Arc directly via Axes.add_patch, I don't have this problem.

Last time I checked (matplotlib 1.4.0), this wasn't an issue. I haven't bisected to figure out when the problem started.

Code for reproduction

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
import matplotlib.collections as mcol
arc = mpatches.Arc([.5,.5], .5, 1, theta1=0, theta2=60, angle=20)
col = mcol.PatchCollection(patches=[arc])
col_style = mcol.PatchCollection(patches=[arc], facecolors='none', edgecolors='k')

fig, (ax1,ax2,ax3) = plt.subplots(1,3, figsize=(15,4))
ax1.set_title('add_patch')
ax1.add_patch(arc)
ax2.set_title('add_collection')
ax2.add_collection(col)
ax3.set_title('add_collection, style')
ax3.add_collection(col_style)
plt.show()

Actual outcome

Expected outcome

The arc in all three figures should be a 60deg arc, not a complete ellipse.

Matplotlib version

  • Operating system: CentOS 7
  • Matplotlib version: 2.1.2
  • Matplotlib backend (print(matplotlib.get_backend())): module://ipykernel.pylab.backend_inline
  • Python version: 2.7.14 |Anaconda, Inc.| (default, Dec 7 2017, 17:05:42) [GCC 7.2.0]
  • Jupyter version (if applicable): 4.4.0

I installed matplotlib via conda: conda create -n py2 python=2 anaconda

Activity

  1. ImportanceOfBeingErnest commented on May 18, 2018

    Member

    The problem is that the Arc is essentially an Ellipse; it just has two additional attributes theta1 and theta2 and a completely different draw method. So the Arc only becomes an arc at drawtime.
    The PatchCollection does not use the individual patches' draw method, but its own (which draws the paths of the patches).

    Possibly it's easier to find a sufficient workaround for this problem than to create a new PatchCollectionWhichAllowsForArcs.
    @dyf What is the motivation to use a PatchCollection instead adding the arcs individually?

  2. dyf commented on May 18, 2018

    Author

    @ImportanceOfBeingErnest Thanks for the quick response.

    I can certainly add the patches individually. I used a pattern in my code where I create a collection of elements and style them all at once via a PatchCollection, e.g.:

    https://github.com/AllenInstitute/AllenSDK/blob/master/allensdk/brain_observatory/circle_plots.py#L574

    but I can just as easily do this in a loop if that's the current preferred route. Not a big deal.

    That said, I wanted to let y'all know that a) this used to work, and b) I think the current behavior is surprising. If you need/want to keep it this way, you might want to update the docs.

    Thanks!

  3. jklymak commented on May 18, 2018

    Member

    I think it’s worth chasing down why it changed.

  4. ImportanceOfBeingErnest commented on May 19, 2018

    Member

    You're right. My explanation comes short of explaining the issue. The code works as expected in matplotlib 2.0.2.

    Version 2.0.2 (released on 5 May 2017) contains the line:

    self._path = Path.arc(self.theta1, self.theta2)

    This line was removed in #8047 (on 11 Mar 2017). Not sure how it can have been removed before the release but still be in it?!

    In any case, reintroducing this line into master will indeed produce arcs instead of ellipses in a PatchCollection; however the bug that #8047 fixed (or at least some other problem that produces wrong arc length) would be reintroduced into the code base.

    attn: @dstansby who removed this line in question and @tacaswell who confirmed that "pushing this down into Path.arc is not right".

  5. dstansby commented on May 21, 2018

    Member

    Does putting that line back in fix this problem, and pass all the tests? Might be worth trying. (sorry, I don't have time to look at this at the moment 😦 )

  6. ImportanceOfBeingErnest commented on May 21, 2018

    Member

    I did not run any tests, but as said, simply putting self._path = Path.arc(self.theta1, self.theta2) back into the __init__ has two effects:

    • it would produce an arc with the code above (desired)
    • the length of the arc is wrong (undesired)
  7. ImportanceOfBeingErnest commented on May 22, 2018

    Member

    To be more precise here, I'm considering the following code which should add an Arc between theta1=0 and theta2=60 as a standalone patch as well as inside a PatchCollection.

        arc = mpatches.Arc([.5,.5], .5, .8, theta1=0, theta2=60, angle=0, lw=1.5)
        col = mcol.PatchCollection(patches=[arc],
                                   facecolors='none', edgecolors='turquoise', lw=3)
        ax1.add_patch(arc)
        ax1.add_collection(col)
    
    Full code here Full Code:
       import numpy as np
       import matplotlib
       matplotlib.use("Qt5Agg")
       import matplotlib.pyplot as plt
       import matplotlib.patches as mpatches
       import matplotlib.collections as mcol
    
    
       def angular_grid(ax, cntr=(0,0)):
           for ang in [0,30,60,90]:
               x = np.cos(np.deg2rad(ang))
               y = np.sin(np.deg2rad(ang))
               l = plt.Line2D([cntr[0],cntr[0]+x],[cntr[1],cntr[1]+y], color="0.8", 
                              ls="--", zorder=0)
               ax.add_artist(l)
               ax.text(cntr[0]+x/2.3, cntr[1]+y/2.3, "{}°".format(ang), color="0.6")
    
       def func():
           fig1, ax1 = plt.subplots(figsize=(3.2,2.8))
           
           arc = mpatches.Arc([.5,.5], .5, .8, theta1=0, theta2=60, angle=0, lw=1.5)
           col = mcol.PatchCollection(patches=[arc],
                                      facecolors='none', edgecolors='turquoise', lw=3)
           ax1.add_patch(arc)
           ax1.add_collection(col)
           
           
           ax1.legend([plt.Line2D([],[],color='k'),plt.Line2D([],[],color='turquoise')], 
                       ["Arc", "PatchCollection([Arc])"], loc=3)
           angular_grid(ax1, [.5,.5])
           ax1.set_title("matplotlib {}".format(matplotlib.__version__), fontsize=10)
           ax1.set_aspect(1)
           
    
       func()
       plt.show()
    

    I'm running this code in several versions:

    Matplotlib 2.0.2

    • Arc can be used in a PatchCollection.
    • Arc as well as Arc inside collection have the wrong angle.

    Matplotlib 2.2.2
    after fix #8047

    • Arc cannot be used in a PatchCollection.
    • Arc has the correct angle.

    Matplotlib development version + added self._path in __init__
    Adding the line

    self._path = Path.arc(self.theta1, self.theta2)

    back into master produces:

    • Arc used in a PatchCollection has the wrong angle.
    • standalone Arc has the correct angle.

  8. jklymak commented on May 22, 2018

    Member

    I think we can just move the logic in the diff for #8047 into into the init rather than the draw. I can’t really think why this would have to be done at draw time, but maybe I’ve not thought it through.

  9. ImportanceOfBeingErnest commented on May 22, 2018

    Member

    There are two reasons the arc is calculated at drawtime and not in the __init__:

    1. Efficiency: Only calculate the points to draw once it is clear where to draw them.
    2. Units: Only calculate the points once the arc is given an axes with units to live in.

    I think it would be possible to sacrifice efficiency (1) and let the total arc be calculated at init; but I have no idea how to do that as long as it's not in an axes (2). I think this second point is what @dstansby stumbled upon when doing the fix, so I thought he might be able to tell a bit more on the reasoning here.

  10. jklymak commented on May 22, 2018

    Member

    Well, units + PatchCollections bite us again.... This should stay open as something the units MEP should address: How can we pre-specify patches when the final axes will have units?

  11. chibai commented on Jan 20, 2022

    Is this bug fixed?
    The version of Matplotlib is 3.5.1 now~

  12. timhoffm commented on Jan 25, 2022

    Member

    No, it's unchanged. This is a fundamental design problem, which nobody has taken the effort to dive into and find a solution.

  13. added this to the v3.6.0 milestone on Aug 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL