Skip to content

Shadow applied to a simple patch does not show #9377

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
clintval opened this issue Oct 11, 2017 · 7 comments
Closed

Shadow applied to a simple patch does not show #9377

clintval opened this issue Oct 11, 2017 · 7 comments
Milestone

Comments

@clintval
Copy link
Contributor

clintval commented Oct 11, 2017

Bug report

Bug summary

Adding a shadow to a patch as described in the documentation does nothing. From the documentation it appears as if matplotlib.patches.Shadow accepts a patch object. I am also not clear on the units of the required ox and oy properties.

Code for reproduction

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

fig, ax = plt.subplots(1, 1, figsize=(5, 5))

rectangle = mpatches.Rectangle(
    xy=(0.25, 0.25),
    width=1/2,
    height=1/2)

shadow = mpatches.Shadow(
    rectangle,
    ox=0.5,
    oy=0.5)

ax.add_patch(rectangle)
ax.add_patch(shadow)

Actual outcome

download

Expected outcome

A shadow of the blue rectangle patch nearby.

Matplotlib version

  • Operating system: Manjaro 17.0.5
  • Matplotlib version: (2.0.2)
  • Matplotlib backend: module://ipykernel.pylab.backend_inline
  • Python version: 3.6.2

I installed matplotlib via the Arch package repositories at sudo pacman -S python-matplotlib.

Edit: added a missing import to make the example self-sufficient. (afvincent)

@afvincent
Copy link
Contributor

Apparently, you have to add the patch to an Axes instance before creating an instance of Shadow. Otherwise, something is undefined in the transforms pipeline (but this starts to be beyond my understanding...).

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

fig, ax = plt.subplots()

rectangle = mpatches.Rectangle(xy=(1.0, 1.0), width=1.0, height=0.50)
ax.add_patch(rectangle)

ax.set_xlim([0, 3])
ax.set_ylim([0, 3])

shadow = mpatches.Shadow(rectangle, ox=0.20, oy=-0.10)
shadow.set_zorder(rectangle.get_zorder() - 1)  # draw *shadow* below *rectangle* 
ax.add_patch(shadow)

fig.savefig("shadow.png")

produces
shadow

@afvincent
Copy link
Contributor

afvincent commented Oct 12, 2017

@clintval I am not sure that anything is really wrong with mpatches.Shadow except an unclear docstring, especially concerning the units of the offset and the underlying transform. While waiting for somebody, who really understands the “transform pipeline”, you may want to have a look at mtransforms.ScaledTranslation which seems to be a bit more explicit about its units.

@tacaswell tacaswell added this to the 2.2 (next feature release) milestone Oct 12, 2017
@tacaswell
Copy link
Member

The z-order issue should probably be correct by default.

Calling shadow._update will fix it.

I think the problem is that the Rectangle is not associated with the transfroms from the Axes until it is added but the Shadow copies the transform from the Rectangle and sets the flag that the tranform on the Shadow object has been set. This means that when you add the Shadow to the Axes later it does not set the transform to default (ax.transData) and the artist does not show up in the correct place.

@clintval
Copy link
Contributor Author

I had to set the zorder directly in @afvincent's example. The Shadow patch inherited the same zorder as the rectangle and a call to shadow._update() did nothing to fix this.

Interestingly, calling shadow._update() in my initial example was another solution to binding the ax.transData to the patch.

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

fig, ax = plt.subplots(1, 1, figsize=(5, 5))

rectangle = mpatches.Rectangle(
    xy=(0.25, 0.25),
    width=1/2,
    height=1/2)

shadow = mpatches.Shadow(
    rectangle,
    ox=0.25,
    oy=0.25)

ax.add_patch(rectangle)
ax.add_patch(shadow)

shadow._update()

download

What would you all suggest as an enhancement?

Shadow transform

Minimally, I would like to contribute a message to the docstring of matplotlib.patches.Shadow which would describe the limitations of using patch not yet bound to an ax.

Shadow zorder

The default shadow behavior is to have the same zorder as the selected patch. It would be nice to have the shadow set a smaller zorder by default. Having the patches in the same plane is confusing.


Thanks for the time! this is my first time reaching out the matplotlib team!

@tacaswell
Copy link
Member

@clintval I think that both of those are great ideas!

@anntzer
Copy link
Contributor

anntzer commented Oct 16, 2017

#9426 should fix the "incorrect transform" part. A zorder fix would still be worthwhile, before anyone writes orig.zorder - 0.001, I'd suggest using np.nextafter(orig.zorder, -np.inf) :-)

@clintval
Copy link
Contributor Author

I just submitted #9435. Along with #9426 this issue could be considered solved after merge.

I did not think editing the documentation was necessary as the two PRs address the odd behavior I was observing.

Thanks and do let me know if I missed anything!

@QuLogic QuLogic modified the milestones: needs sorting, v2.2.0 Feb 12, 2018
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

5 participants