Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

CreateInsetIndicator artist#27996

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
tacaswell merged 1 commit intomatplotlib:mainfromrcomer:indicate-inset-patch
Sep 18, 2024

Conversation

rcomer
Copy link
Member

@rcomerrcomer commentedMar 30, 2024
edited
Loading

PR summary

#19768 (comment) suggested that we should have some kind of container for the output ofindicate_inset[_zoom].#23424 (comment) suggested that it should be drawn as a single path to avoid double-alpha where the box and connectors overlap. This PR is my attempt to implement that.

The new artist has convenience methods to update colour/linestyle/etc for the whole thing, but the user can also get hold of individual patches and update styles on those. The current doctrings ofindicate_inset[_zoom] specifically mention updating the visibility of the connectors, but a user might also reasonably want a different colour or linestyle for the connectors than for the box.

The logic fromindicate_inset_zoom that decided where the box should be is now methodInsetIndicator._bounds_from_inset_ax so we can reuse it. Whenever theconnectors 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 thereforecloses#19768 and we can do things like

importmatplotlib.pyplotaspltimportmatplotlib.animationasanimationimportnumpyasnpx=np.arange(100)y=x+np.sin(x)*5fig,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)forconninind.connectors:# In this example all the connectors are invisible by default - I'm unclear why that is.conn.set_visible(True)defanimate(i):ax_ins.set_xlim([i,i+10])ax_ins.set_ylim([i-5,i+15])returnax_ins,ani=animation.FuncAnimation(fig,animate,interval=100,frames=90)plt.show()

inset

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

This also inadvertentlyfixes#23425 since I haven't implementedget_window_extent orget_tight_bbox, so constrained layout will get a null tight bbox. I would like advice on whether I should implement one or both of these and what it should include. For the purposes of layout engines is does not seem useful to include the connectors, but maybe there are other uses for these methods?

PR checklist

@rcomerrcomer added this to thev3.10.0 milestoneMar 30, 2024
@rcomer
Copy link
MemberAuthor

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

@rcomerrcomer changed the titlePOC: createIndicateInset patchPOC: createInsetIndicator patchApr 22, 2024
@rcomerrcomerforce-pushed theindicate-inset-patch branch 2 times, most recently fromfce57eb to3d725eaCompareMay 12, 2024 19:18
@rcomer
Copy link
MemberAuthor

Perhaps instead of inheriting fromRectangle, this should be a container artist with both the rectangle and the connectors as children. Then users who want more control could get hold of the child artists and update colours, etc. on them individually 🤔

story645 reacted with thumbs up emoji

@story645
Copy link
Member

story645 commentedJul 28, 2024
edited
Loading

Then users who want more control could get hold of the child artists and update colours, etc. on them individually

That sounds like a fairly common use case to me so I think that'd be awesome. Is there an advantage to the rectangle approach/downside to making it a container?

rcomer reacted with thumbs up emoji

@rcomer
Copy link
MemberAuthor

Is there an advantage to the rectangle approach/downside to making it a container?

Not that I can think of. I think I just had in mind from#23424 (comment) that the new object should be aPatch and inheriting fromRectangle seemed like the obvious way to do that. Having said that, I'm not sure what defines aPatch and maybe that fact that the connectors are already children that you can configure separately from the whole thing means it doesn't really fit the definition.

@story645
Copy link
Member

story645 commentedJul 28, 2024
edited
Loading

I'm not sure what defines a Patch 

Technicallyartist w/ face color + edgecolor & for the most part I've always thought of it as roughly the MPL abstraction of an area mark b/c that's basically the space of visual encodings we allow/can apply to most of our patch artists:
Six-visual-variables-proposed-by-Bertin-and-their-capacity-in-representing-graphical.png

Where size and shape are controlled by the drawing of the shape, while for example the choice of marker determines shape and marker size controls the size.

So for what it's worth, I agree w/ your intuition that a container Artist is probably a better abstraction for what's actually going on here.

rcomer reacted with thumbs up emojircomer reacted with eyes emoji

@github-actionsgithub-actionsbot added the Documentation: APIfiles in lib/ and doc/api labelAug 11, 2024
@rcomerrcomer changed the titlePOC: createInsetIndicator patchPOC: createInsetIndicator artistAug 11, 2024
@rcomer
Copy link
MemberAuthor

rcomer commentedAug 11, 2024
edited
Loading

OK, theInsetIndicator is now a container artist instead of a patch. I couldn't see which module it would obviously fit in, so made a new one.

One side-effect of this is that we no longer get the axes limits updated around the artist, which is done inadd_patch here:

self._update_patch_limits(p)

So my test image changed from
zoom_inset_connector_styles

to
zoom_inset_connector_styles

I guess it would be pretty easy to re-instate that but I'm not sure if it matters. Most of the time there will be a bunch of other artists that this one isindicating.

Still to do:

  • Add changenotes
  • Decide what, if anything, to do aboutget_window_extent/get_tightbbox

@github-actionsgithub-actionsbot removed the Documentation: APIfiles in lib/ and doc/api labelAug 12, 2024
@rcomer
Copy link
MemberAuthor

Added changenotes and directives, though I'm not sure if the behaviour change documentation forindicate_inset[_zoom] is really needed since these methods were marked as experimental...?

@rcomerrcomer marked this pull request as ready for reviewAugust 12, 2024 10:57
@pawjast

This comment was marked as resolved.

@rcomer

This comment was marked as resolved.

@story645

This comment was marked as resolved.

@pawjast

This comment was marked as resolved.

@rcomer

This comment was marked as resolved.

@story645

This comment was marked as resolved.

@pawjast

This comment was marked as resolved.

@rcomer
Copy link
MemberAuthor

I hid the alpha discussion because that was addressed by#28710 and is not needed for the reviewers of this PR.

@story645story645 self-assigned thisAug 15, 2024
@tacaswell
Copy link
Member

Decide what, if anything, to do about get_window_extent/get_tightbbox

It is also used byfig.savefig(..., bbox_inches='tight') so if we do not implement it then there is a high risk that people using the inline backend may be able to drive them selves to a state where we clip something we should not have, however as both the host and inset axes do implement those methods, I'm struggling to come up with an arangement of the two axes that would result in the connector getting clipped...

When you said "container" I was worried you were following what we do with e.g. error bar where we return atuple subclass, but I think what you implemented is the right way to go.

rcomer reacted with thumbs up emoji

@story645
Copy link
Member

why did the lower left and upper right segments disappear?

@jklymak
Copy link
Member

I don’t know about dragging but if you pan/zoom it can end up outside the axes.

yeah, that is all a bit tricky. The rectangle would ideally clip to the parent axes; probably easy. The connectors would ideally clip the parent axes as well, but only on the side that links to the rectangle. I'm not aware that we have a way to do that and I'm not sure it's worth the hassle to make it. Either you are doing this for data exploration, in which case a little mess is OK, or you are doing it for a final plot, in which case you can clean up the positions then.

rcomer reacted with thumbs up emoji

@rcomer
Copy link
MemberAuthor

why did the lower left and upper right segments disappear?

You mean the connectors? Only 2 of those are visible by default.
https://matplotlib.org/stable/gallery/subplots_axes_and_figures/zoom_inset_axes.html

@story645
Copy link
Member

why did the lower left and upper right segments disappear?

You mean the connectors? Only 2 of those are visible by default.
https://matplotlib.org/stable/gallery/subplots_axes_and_figures/zoom_inset_axes.html

Thanks! Sorry for not checking the docs 🤦‍♀️
Am clearly confused by that API choice but is out of scope here.

@story645story645 removed their assignmentAug 16, 2024
for conn in self.connectors or []:
if conn.get_visible():
drawn = False
for s in _shared_properties:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Isn't it also the case that if the non-shared properties differ, then you can't merge the paths? For example,zorder isn't listed as shared, but might make a difference.

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Yeah, I wasn't super-happy about doing this with a hard-coded list, but so far haven't thought of a better way. Very happy to take suggestions/pointers.

... oh I just realised I could useArtistInspector.get_setters to make a complete list - maybe that's part of the solution, though we'd have to actively skip comparing some properties liketransform 🤔

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I also just realised that I currently have thezorder going toRectangle in the__init__ when it should be getting applied toInsetIndicator. So I need a better way to keep the properties straight at that end too.

@rcomerrcomerforce-pushed theindicate-inset-patch branch 4 times, most recently from6e106e9 to143a228CompareAugust 18, 2024 13:16
Comment on lines +476 to +485
inset_indicator.rectangle : `.Rectangle`
The indicator frame.

inset_indicator.connectors : 4-tuple of `.patches.ConnectionPatch`
The four connector lines connecting to (lower_left, upper_left,
lower_right upper_right) corners of *inset_ax*. Two lines are
set with visibility to *False*, but the user can set the
visibility to True if the automatic choice is not deemed correct.

Copy link
Member

@story645story645Aug 22, 2024
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

would it make sense to make this an interpolated doc, even if it's only used in like two places? That way it can be defined in the module? Only thinking about this b/c of how it's being done for colorizer:

mpl._docstring.interpd.update(
colorizer_doc="""\
colorizer : `~matplotlib.colorizer.Colorizer` or None, default: None
The Colorizer object used to map color to data. If None, a Colorizer
object is created base on *norm* and *cmap*.""",
)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Possibly can do something even more direct but I do not follow this example at allhttps://matplotlib.org/devdocs/devel/document.html#keyword-arguments

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Do we have any general guidance about when it makes sense to do this rather than copy/paste? As you say it's only in two places and I am keenly aware that I have a lot more copy/paste going on in the artist'sset_* docstrings.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Trying to figure that out w/#28746 and probably a@timhoffm question?

Comment on lines 105 to 109
if conn.get_visible():
# Make one visible connector a different style
conn.set_linestyle('dashed')
conn.set_color('blue')
break
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

shouldn't you know which connector this is b/c this is deterministic? basically why loop?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I was just too lazy to figure out which index it would be...

@QuLogic
Copy link
Member

Is this no longer PoC (as in title)?

@rcomerrcomer changed the titlePOC: createInsetIndicator artistCreateInsetIndicator artistSep 12, 2024
@rcomer
Copy link
MemberAuthor

I just noticed I forgot to update the deprecation warning when the patch became an artist. Nowfixed.

@tacaswelltacaswell merged commitea78e25 intomatplotlib:mainSep 18, 2024
43 checks passed
@rcomerrcomer deleted the indicate-inset-patch branchSeptember 18, 2024 19:43
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@story645story645story645 left review comments

@QuLogicQuLogicQuLogic approved these changes

Assignees
No one assigned
Projects
None yet
Milestone
v3.10.0
6 participants
@rcomer@story645@pawjast@tacaswell@jklymak@QuLogic

[8]ページ先頭

©2009-2025 Movatter.jp