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

ENH: addax kwarg to every pyplot function#9111

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

Draft
tacaswell wants to merge2 commits intomatplotlib:main
base:main
Choose a base branch
Loading
fromtacaswell:ENH_ax_into_pyplot

Conversation

tacaswell
Copy link
Member

This allows passingax=some_ax into all of the pyplot plotting
functions.

PR Checklist

  • Has Pytest style unit tests
  • Code is PEP 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)

phobson and scottshambaugh reacted with thumbs up emoji
@tacaswelltacaswell added this to the2.1 (next point release) milestoneAug 28, 2017
@anntzer
Copy link
Contributor

What's the benefit as opposed to just using the OO API, if you really want to specify the figure/axis?

@tacaswell
Copy link
MemberAuthor

This is the opening pass at something I have been thinking about for a while.

The very short version is that there is currently a major difference between 'built in' plotting (ax.foo(data, style)) and user / third-party plotting (foo(data, style, ax=ax)) and it would be better to reduce. As we do not want third-party tools to be monkey-patching methods on to Axes, we should rotate the main API to look more like functions to put everything on the same footing. The suggested API would then be

defmy_plotter(*data,ax,**style):   ...

This is bread-crumbs leading that direction.

@anntzer
Copy link
Contributor

This actually looks like a reasonable argument (as much as I would like not to admit it...)

@WeatherGod
Copy link
Member

WeatherGod commentedAug 28, 2017 via email

Yeah, this is pretty much the same proposal from a few years ago that gotsidelined to focus on getting the data kwarg into the v1.5 release, isn'tit?I totally get the argument, I just don't know how well I like that codingstyle. Feels very basemap-ish. Whatever happened to the idea of plottingobjects?
On Mon, Aug 28, 2017 at 11:37 AM, Antony Lee ***@***.***> wrote: This actually looks like a reasonable argument (as much as I would like not to admit it...) — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub <#9111 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AARy-N7mVbidz89QregvZ__Vt6Tz1ch1ks5sct6mgaJpZM4PEATz> .

@dopplershift
Copy link
Contributor

In general I'm ok with the idea. I do think we should think about the idea of plotting objects in this context before proceeding, though.

@anntzer
Copy link
Contributor

Also what's wrong with just using sca() in that case?
Or even

with plt.sca(ax): ...

which is probably going to be less repetitive that having to pass ax again and again.

Copy link
Contributor

@dopplershiftdopplershift left a comment

Choose a reason for hiding this comment

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

If for no other reason than that this allows using thepyplot interface with an explicit axes, I'm 💯 on this.

@tacaswell
Copy link
MemberAuthor

I think that this and more complex objects are orthogonal. The objects are about making more complex plots easier to update and work with (ex errorbars) and this is about letting third-party code, or code that takes in not-arrays as input feel like first class citizens next to the 'official'.

I expect there to be plotting functions that take in very non-array things (like a partial sql query!).

It also provides a smoother path to leaving the fully implicit world to the full OO world.

@tacaswelltacaswell added the Release criticalFor bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. labelAug 28, 2017
@tacaswell
Copy link
MemberAuthor

This is actually pass 2 at this, see#4488

@tacaswelltacaswellforce-pushed theENH_ax_into_pyplot branch 2 times, most recently fromb08714c tof26efd9CompareAugust 31, 2017 03:06
def test_explict_ax():
fig, (ax1, ax2) = plt.subplots(2)
plt.plot(range(5))
plt.plot(range(5)[::-1], ax=ax1)
Copy link
Contributor

Choose a reason for hiding this comment

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

I would just test that len(ax1.lines) == 2 instead of doing an image comp.

test name has typo ("explicit")

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

There should be one line per axes (gca() is surprising! ax2 was created last so it is 'current')

Copy link
Contributor

Choose a reason for hiding this comment

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

you got me :-)
but still you should be able to just test how many lines there are on each axis.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Done

@@ -316,12 +318,13 @@ def format_value(value):

# A gensym-like facility in case some function takes an
# argument named washold, ax, or ret
washold, ret, ax= 'washold', 'ret', 'ax'
washold, ret= 'washold', 'ret'
Copy link
Contributor

@anntzeranntzerAug 31, 2017
edited
Loading

Choose a reason for hiding this comment

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

the comment above needs to be updated
side point: I think we should just throw an exception in this case -- the parameter name is part of the API so renaming it seems silly

bad = set(args) | {varargs, varkw}
while washold in bad or ret in bad or ax in bad:
if 'ax' is set(args):
Copy link
Contributor

Choose a reason for hiding this comment

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

I was suggesting to do the same for washold and ret below.

@efiring
Copy link
Member

Even if this turns out to be the way to go, bringing in such a major strategic change with so little discussion and review is not good. Suggestion: leave this out of 2.1, and make it theproposed centerpiece of 2.2, with avery short release cycle--say, Nov. 1 as the target.

@tacaswell
Copy link
MemberAuthor

It was worth a shot!

I am taking@efiring 's comment as a veto of this going in for 2.1.

Delaying to 2.2 in Nov would give us time to write some collateral around this change, flesh out some of the other implications, and retroactively write a MEP which is probably for the best

afvincent reacted with thumbs up emoji

@tacaswelltacaswell modified the milestones:2.2 (next next feature release),2.1 (next point release)Aug 31, 2017
@anntzer
Copy link
Contributor

Having though a bit about this, right now I belive my preferred take on such an API ("to make pyplot and external functions more symmetrical") would be

with plt.sca(ax): # or a new function    plt.plot(...)    seaborn.somemethod(...)# when sca() is *exited* there is *no* current axes,# so plt.gca() would return None and plt.plot would error

which seems better than having to pass the same ax again and again.

@tacaswell
Copy link
MemberAuthor

However this means inside of every function there must be a call toplt.gca(). The other long term goal is to get away from the shared global state of pyplot (so everything GC's reasonable, etc).

Havingno current figure/ax is a non-starter.pyplot (and all of it's shared global state) exists as convince methods for people sitting in an interactive shell and I do not think we will ever be able to remove it, just make it possible for people to use without it.

Having a context manager that resets the current axes to what it was before would be a reasonable thing though.

XXX(..., ax=ax) is not that much more onerous thanax.XXX(...)

@dstansbydstansby removed the Release criticalFor bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. labelOct 14, 2017
@tacaswelltacaswell modified the milestones:needs sorting,v3.1Jul 7, 2018
@tacaswelltacaswell added the Release criticalFor bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. labelJul 7, 2018
Copy link
Member

@NelleVNelleV left a comment

Choose a reason for hiding this comment

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

In terms of code, this looks good, but the PR introduces a backward incompatible change.

On the documentation front, a lot of the docstrings need to be updated to reflect the addition of an optional keyword argument. I'm happy to push the missing documentation.

I'm also concerned about the unit tests. While indeed, this has been tested on one of the pyplot function, I think we should maybe write smoke tests coverage all pyplot functions concerned by this change.

@@ -928,7 +970,7 @@ def delaxes(*args):
if not len(args):
ax = gca()
else:
ax = args[0]
ax, = args
Copy link
Member

Choose a reason for hiding this comment

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

This will fail if args has more arguments than one. If args is can only be one optional argument, why not change *args into an actual optional keyword argument? That would make the code more readible, and more easily documentable than currently.

Note that because of this line we are currently introducing a backward compatible change with this PR.

@@ -1328,19 +1374,20 @@ def tight_layout(pad=1.08, h_pad=None, w_pad=None, rect=None):
coordinate that the whole subplots area (including
labels) will fit into. Default is (0, 0, 1, 1).
"""

fig = gcf()
if fig is None:
Copy link
Member

Choose a reason for hiding this comment

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

The docstring needs to be update to reflect the addition of an optional keyword argument.

fig.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect)


def box(on=None):
def box(on=None, ax=None):
Copy link
Member

Choose a reason for hiding this comment

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

The docstring needs to be update to reflect the addition of an optional keyword argument.

@@ -1376,6 +1423,9 @@ def title(s, *args, **kwargs):
loc : {'center', 'left', 'right'}, str, optional
Which title to set, defaults to 'center'

ax : matplotlib.axes.Axes, optional
Copy link
Member

Choose a reason for hiding this comment

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

👍

@@ -1389,7 +1439,7 @@ def title(s, *args, **kwargs):
properties.

"""
returngca().set_title(s, *args, **kwargs)
return_pop_or_gca(kwargs).set_title(s, *args, **kwargs)
Copy link
Member

Choose a reason for hiding this comment

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

The docstring needs to be update to reflect the addition of an optional keyword argument.

@tacaswelltacaswell modified the milestones:v3.3.0,v3.4.0May 13, 2020
@jklymakjklymak marked this pull request as draftAugust 24, 2020 14:19
@QuLogicQuLogic modified the milestones:v3.4.0,v3.5.0Jan 21, 2021
@tacaswelltacaswell modified the milestones:v3.5.0,3.6.0Jul 8, 2021
@timhoffmtimhoffm modified the milestones:v3.6.0,unassignedApr 30, 2022
@story645story645 modified the milestones:unassigned,needs sortingOct 6, 2022
@tacaswell
Copy link
MemberAuthor

rebased to keep the dream alive.

dstansby reacted with laugh emoji

@github-actions
Copy link

Since this Pull Request has not been updated in 60 days, it has been marked "inactive." This does not mean that it will be closed, though it may be moved to a "Draft" state. This helps maintainers prioritize their reviewing efforts. You can pick the PR back up anytime - please ping us if you need a review or guidance to move the PR forward! If you do not plan on continuing the work, please let us know so that we can either find someone to take the PR over, or close it.

@github-actionsgithub-actionsbot added the status: inactiveMarked by the “Stale” Github Action labelApr 16, 2023
@timhoffm
Copy link
Member

timhoffm commentedApr 16, 2023
edited
Loading

As a side-note: The place where theax keyword is most present is the pandas plot API. Unfortunately, they have a different semantic (“if not given, create a new axes” vs. pyplot: “if not given, use the current axes - only if there is no current axes, create a new one).
Not necessarily a blocker, but we have to be aware that this will be a source of confusion.


I've marked this askeep andneeds comment/discussion because it really something to investigate, but the correct approach is not yet clear.

@timhoffmtimhoffm added status: needs comment/discussionneeds consensus on next step keepItems to be ignored by the “Stale” Github Action and removed status: inactiveMarked by the “Stale” Github Action labelsApr 16, 2023
This allows passing `ax=some_ax` or `fig=some_fig` into all of thepyplot plotting functions.
@tacaswell
Copy link
MemberAuthor

I could not quickly figure out how to convince the generated annotations to not use the fully qualified class names.

Bit confused why it was not hitting these before.
@tacaswell
Copy link
MemberAuthor

mypy is still also a bit unhappy (it does not like forwarding returns through unconditionally...I guess the fix would be to make the generating code smart enough to drop the return if the wrapped function claims to only ever returnNone.

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

@NelleVNelleVNelleV left review comments

@anntzeranntzerAwaiting requested review from anntzer

@dopplershiftdopplershiftAwaiting requested review from dopplershift

Assignees
No one assigned
Labels
keepItems to be ignored by the “Stale” Github Actionstatus: needs comment/discussionneeds consensus on next stepstatus: needs rebase
Projects
None yet
Milestone
future releases
Development

Successfully merging this pull request may close these issues.

11 participants
@tacaswell@anntzer@WeatherGod@dopplershift@efiring@timhoffm@jklymak@NelleV@QuLogic@story645@dstansby

[8]ページ先頭

©2009-2025 Movatter.jp