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

POC: create InsetIndicator patch #27996

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

rcomer
Copy link
Member

@rcomer rcomer commented Mar 30, 2024

PR summary

#19768 (comment) suggested that we should have some kind of container for the output of indicate_inset[_zoom]. #23424 (comment) suggested that it should be its own patch, drawn as a single path to avoid double-alpha where the box and connectors overlap. This PR is my attempt to implement that. In draft for now because I want to get feedback on the approach before spending time on the documentation/typing side of things.

The new patch object inherits from Rectangle since that is the minimum that is always created. The connectors are no longer added to the axes directly but are children of this patch and available to the user via the connectors property. The user can therefore update properties of individual connectors: the current doctring specifically mentions updating the visibility of these, but a user might also reasonably want a different colour or linestyle for the connectors than for the box.

The logic from indicate_inset_zoom that decides where the box should be is now method InsetIndicator._bounds_from_inset_ax so we can reuse it. Whenever the connectors attribute is accessed (including at draw) the box bounds and position of connectors (if any) get updated using the current inset axes x- and y-limits. This therefore closes #19768 and we can do things like

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

x = np.arange(100)
y = x + np.sin(x) * 5

fig, ax = plt.subplots()
ax.plot(x, y)

ax_ins = ax.inset_axes([0.6, 0.1, 0.3, 0.3])
ax_ins.plot(x, y)
ax_ins.set_xlim([0, 10])
ax_ins.set_ylim([0, 10])
ind = ax.indicate_inset_zoom(ax_ins)
for conn in ind.connectors:
    # In this example all the connectors are invisible by default - I'm unclear why that is.
    conn.set_visible(True)

def animate(i):
    ax_ins.set_xlim([i, i+10])
    ax_ins.set_ylim([i-5, i+15])
    return ax_ins,

ani = animation.FuncAnimation(fig, animate, interval=100, frames=90)

plt.show()

inset

linewidth and linestyle for the connectors are now inherited from the parent patch when the connectors are created. Within the draw method, we check which connectors have the same style properties (currently four specific properties - maybe there is a better way). Those that do are drawn with the rectangle as a compound path. This therefore closes #23424.

This also inadvertently fixes #23425 since I haven't implemented get_window_extent or get_tight_bbox, so constrained layout will only get the tight bbox of the rectangle. I'm unclear where those methods get used outside of layout engines, so do they need to be implemented here?

Currently if I do e.g. set_edgecolor on the InsetIndicator patch, whether that affects the connectors depends on whether they have been accessed yet, and probably shouldn't. So that part needs a bit more thought/work.

PR checklist

Behaviour changes at this point
* return type for indicate_inset[_zoom]
* the connectors do not exist until draw because their position
  requires knowledge of the axes they are added to
* since get_window_extent/get_tightbbox is not yet implemented, this
  will likely not interact well with layout engines (though it already
  didn't - see matplotlib#23425)
@rcomer rcomer added this to the v3.10.0 milestone Mar 30, 2024
@rcomer
Copy link
Member Author

rcomer commented Mar 30, 2024

Added a __getitem__ method in an effort to provide a deprecation pathway. Although indicate_inset[_zoom] are still marked as experimental, I suspect the pattern box, connectors = ax.indicate_inset... is pretty common.

@rcomer rcomer changed the title POC: create IndicateInset patch POC: create InsetIndicator patch Apr 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment