Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Make kwargs names in scale.py not include the axis direction. #14916

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

Merged
merged 3 commits into from
Feb 9, 2020

Conversation

anntzer
Copy link
Contributor

@anntzer anntzer commented Jul 29, 2019

  • Make names of kwargs to Scale subclasses independent of whether the
    underlying axis is x or y (so that after the deprecation period, one
    can just have a normal signature --
    def __init__(self, *, base=10, ...).

    We could possibly also change semilogx and semilogy to use the
    unsuffixed names (with deprecation), leaving only loglog with the
    suffixed names, or even also make loglog use unsuffixed names, in
    which case it would become impossible to set separate x and y bases
    directly in loglog -- one should then do gca().set_xscale("log", base=...) which doesn't seem too onerous. (loglog is the only case
    where the suffixed names has some utility.)
    EDIT: see Make kwargs names in scale.py not include the axis direction. #14916 (comment).

    In general, note that having kwargs that depend on the axis direction
    doesn't really scale -- for example, if we were to finally add
    log-scale support to mplot3d, should scale.py know about it and add
    basez? Should we have baser for log-scale polar plots? (at least
    in the radial direction, they make sense)

  • Move argument validation up the the Transform subclasses.

  • Make SymmetricalLogScale.{base,linthresh,linscale} properties
    mapping to the underlying transform so that they can't go out of sync.

As discussed with @tacaswell during the dev call.

PR Summary

PR Checklist

  • Has Pytest style unit tests
  • Code is Flake 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)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@anntzer anntzer force-pushed the morescalevalidation branch from 1e946e0 to acd0e2f Compare July 29, 2019 22:10
Copy link
Member

@timhoffm timhoffm left a comment

Choose a reason for hiding this comment

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

I've always found the abbreviations quite confusing. Since we're renaming the parameters anyway, we could move to more telling names:

subs -> subticks
nonpos -> nonpositive
linthresh -> linthreshold

But to be fair, that'd be a bit more work; at least for subs and linthresh. They are used as public attributes in some places, which should then be deprecated/changed as well. nonpos is only a private attribute.

@rename_parameter("3.2", f"linthresh{axis.axis_name}", "linthresh")
@rename_parameter("3.2", f"subs{axis.axis_name}", "subs")
@rename_parameter("3.2", f"linscale{axis.axis_name}", "linscale")
def __init__(*, base=10, linthresh=2, subs=None, linscale=1, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

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

any particular reason to call this __init__? I would just use init because it's just a regular local method. The dunder may be a bit misleading.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is so that when the wrong arg names are passed, Python generates the error message with the right name (__init__() got an unexpected argument...).

Copy link
Member

Choose a reason for hiding this comment

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

Maybe a comment in the code for why you did this? I guess its just a place holder until a future version?

@anntzer
Copy link
Contributor Author

anntzer commented Aug 10, 2019

I agree that if we are changing the names it may be better to directly pick better names rather than have two changes in a row... but subs and linthresh are also used as parameter/attribute names in ticker.py, which would also need to be changed for consistency, but that seems to not cross the threshold of "is it really worth the disruption".

@timhoffm
Copy link
Member

We should at least change nonpos -> nonpositive. That one is particularly confusing because "pos" is often used as an abbreviation of "position". And there is no parameter/attribute involved that would need changing as well.

For reference:

Usages of subs:

  • As parameter in __init__ and set_params of LogLocator and SymmetricalLogLocator
  • As method in LogLocator (should rather be set_subs() anyway)
  • As attribute in LogScale (and its derivatives)

Usage of linthresh:

  • As parameter in LogFormatter, SymmetricalLogFormatter, SymmetricalLogTransform, InvertredSymmetricalLogTransform, SymLogNorm
  • As attribute in SymmetricalLogTransform, InvertredSymmetricalLogTransform, SymmetricalLogScale

I agree that linthresh is not worth the disruption. I support changing subs but won't insist on it.

@anntzer
Copy link
Contributor Author

anntzer commented Aug 11, 2019

nonpos also maps to minpos, which appears in various places.

@timhoffm
Copy link
Member

timhoffm commented Aug 11, 2019

nonpos also maps to minpos, which appears in various places.

😭

In the trade-off I wouldn't let that prevent the nonpos change. They are only loosely related, and IMHO a clearer name is more important than the similarity here.

@tacaswell tacaswell added this to the v3.3.0 milestone Aug 12, 2019
@anntzer anntzer force-pushed the morescalevalidation branch from acd0e2f to 6551cb1 Compare November 29, 2019 19:54
@anntzer
Copy link
Contributor Author

anntzer commented Nov 29, 2019

I'm fine with renaming nonpos to nonpositive if there's a consensus in that direction (i.e. if another dev agrees).
Another advantage of making scales more independent of the axis is that this could later help in constructing some norms (which are independent of axis) as wrappers around scales -- thus allowing norms to take advantage of e.g. the scale -> locator/formatter mapping that already exists, instead of having to hard-code it into colorbar.py.

@anntzer anntzer force-pushed the morescalevalidation branch from 6551cb1 to 965f599 Compare November 30, 2019 22:01
@anntzer anntzer force-pushed the morescalevalidation branch 2 times, most recently from 92041d0 to 3e4af57 Compare December 9, 2019 06:39
Copy link
Member

@jklymak jklymak left a comment

Choose a reason for hiding this comment

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

This looks great to me, just a few minor questions. I think this is worth the API change - I don't see any reason a scale should care if its an x or y axis....

@@ -1791,16 +1791,13 @@ def loglog(self, *args, **kwargs):
**kwargs
All parameters supported by `.plot`.
"""
dx = {k: kwargs.pop(k) for k in ['basex', 'subsx', 'nonposx']
dx = {k[:-1]: kwargs.pop(k) for k in ['basex', 'subsx', 'nonposx']
Copy link
Member

Choose a reason for hiding this comment

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

Sorry, why are you excluding the last element here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because the kwarg name for semilogx/y is still "basex"; this PR doesn't change that. Specifically, while I could change the kwarg name in semilogx to "base" (with the same deprecation), this doesn't work for loglog(), which needs a separate basex/basey (although it would also be reasonable to deprecate supporting directly setting two different bases for x and y in loglog() and require the user to call set_x/yscale("log", base=...) for that specific case. I think we just need to decide on the best API change here.

Copy link
Member

Choose a reason for hiding this comment

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

OK. Duh, I see now, but this might be a rare case where not using comprehension might be a lot clearer:

for k in ['basex', 'subex', 'nonposx']:
  dx{k[:-1]} = kwargs.pop(k)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree that the side-effect of popping kwargs in the comprehension may not be nicest, and can change that, but before doing so, do you have comments on the API changes suggested above?

Copy link
Member

Choose a reason for hiding this comment

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

I agree that most folks won't use different basex, basey. OTOH there is call to use different subs and nonpos isn't there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

People can still use set_xscale("log", subs=...) in that case. Note that in the (common?) case of using the same subs on x and y, the proposed new API is actually nicer (loglog(..., subs=...) instead of repeating yourself with subs(..., subsx=..., subsy=...)).
I have kind of changed my mind compared to when I first wrote the PR; I now think that having the same kwargs in loglog/semilogx/y as in set_scale("log", ...) would actually be quite nice (whereas I was previously more ok with keeping basex/basey on loglog/semilog).

Copy link
Member

Choose a reason for hiding this comment

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

I'd be onboard with this, but we should prob be prepared to not do this if the deprecation warning freaks too many people out.

Other comments? @timhoffm @ImportanceOfBeingErnest @efiring?

Copy link
Member

Choose a reason for hiding this comment

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

basex, basey are poor names anyway; I would be happy to see them go. This sort of regularization of the API will inevitably cause some pain, but I think we should do it.

@@ -280,8 +280,11 @@ class LogTransform(Transform):

def __init__(self, base, nonpos='clip'):
Transform.__init__(self)
if base <= 0 or base == 1:
raise ValueError('The log base cannot be <= 0 or == 1')
Copy link
Member

Choose a reason for hiding this comment

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

What happened before? Did we just get a ValueError later?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The error checking was in LogScale (which calls into LogTransform), but that meant that you could construct invalid LogTransforms which only errored out at use time. With the change you can't construct invalid LogTransforms or LogScales anymore.

if linthresh <= 0.0:
raise ValueError("'linthresh' must be positive")
if linscale <= 0.0:
raise ValueError("'linscale' must be positive")
Copy link
Member

Choose a reason for hiding this comment

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

Same question here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

as above

@rename_parameter("3.2", f"linthresh{axis.axis_name}", "linthresh")
@rename_parameter("3.2", f"subs{axis.axis_name}", "subs")
@rename_parameter("3.2", f"linscale{axis.axis_name}", "linscale")
def __init__(*, base=10, linthresh=2, subs=None, linscale=1, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

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

Maybe a comment in the code for why you did this? I guess its just a place holder until a future version?

@anntzer anntzer force-pushed the morescalevalidation branch from 3e4af57 to bbb5d4f Compare February 3, 2020 14:41
@anntzer
Copy link
Contributor Author

anntzer commented Feb 3, 2020

re your last point: added a comment to clarify.

@anntzer anntzer force-pushed the morescalevalidation branch from bbb5d4f to eb37584 Compare February 3, 2020 16:05
@tacaswell
Copy link
Member

👍 in principle, but have not reviewed in detail.

@anntzer
Copy link
Contributor Author

anntzer commented Feb 4, 2020

OK, added a second commit which also changes the kwarg names on the Axes methods.
#14916 (review) (rename "nonpos" to "nonpositive"?) still needs to be decided upon.

@anntzer anntzer force-pushed the morescalevalidation branch from eb37584 to dee07b2 Compare February 4, 2020 07:35
@codecov
Copy link

codecov bot commented Feb 4, 2020

Codecov Report

Merging #14916 into master will decrease coverage by 0.38%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #14916      +/-   ##
==========================================
- Coverage   80.85%   80.46%   -0.39%     
==========================================
  Files         307      307              
  Lines       75746    74412    -1334     
  Branches     9691     9695       +4     
==========================================
- Hits        61244    59876    -1368     
- Misses      11962    11988      +26     
- Partials     2540     2548       +8     
Impacted Files Coverage Δ
lib/matplotlib/backends/backend_macosx.py 4.54% <0.00%> (-36.12%) ⬇️
lib/matplotlib/testing/jpl_units/StrConverter.py 15.55% <0.00%> (-5.28%) ⬇️
lib/matplotlib/testing/jpl_units/EpochConverter.py 69.69% <0.00%> (-4.67%) ⬇️
lib/matplotlib/docstring.py 65.00% <0.00%> (-3.19%) ⬇️
lib/matplotlib/backends/qt_compat.py 48.42% <0.00%> (-3.16%) ⬇️
...b/matplotlib/testing/jpl_units/UnitDblConverter.py 65.85% <0.00%> (-2.33%) ⬇️
lib/matplotlib/backend_managers.py 20.95% <0.00%> (-2.30%) ⬇️
lib/matplotlib/backends/backend_qt5.py 55.94% <0.00%> (-1.44%) ⬇️
lib/matplotlib/font_manager.py 74.10% <0.00%> (-1.17%) ⬇️
lib/matplotlib/pyplot.py 71.72% <0.00%> (-1.14%) ⬇️
... and 152 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7b6eb77...dee07b2. Read the comment docs.

@anntzer anntzer mentioned this pull request Feb 6, 2020
- Make names of kwargs to Scale subclasses independent of whether the
  underlying axis is x or y (so that after the deprecation period, one
  can just have a normal signature --
  `def __init__(self, *, base=10, ...)`.

  We could possibly also change semilogx and semilogy to use the
  unsuffixed names (with deprecation), leaving only loglog with the
  suffixed names, or even also make loglog use unsuffixed names, in
  which case it would become impossible to set separate x and y bases
  directly in loglog -- one should then do `gca().set_xscale("log",
  base=...)` which doesn't seem too onerous.  (loglog is the only case
  where the suffixed names has *some* utility.)

  In general, note that having kwargs that depend on the axis direction
  doesn't really scale -- for example, if we were to finally add
  log-scale support to mplot3d, should scale.py know about it and add
  `basez`?  Should we have `baser` for log-scale polar plots? (at least
  in the radial direction, they make sense)

- Move argument validation up the the Transform subclasses.

- Make SymmetricalLogScale.{base,linthresh,linscale} properties
  mapping to the underlying transform so that they can't go out of sync.
@anntzer
Copy link
Contributor Author

anntzer commented Feb 8, 2020

rebased

@anntzer
Copy link
Contributor Author

anntzer commented Feb 8, 2020

before this gets merged please comment on @timhoffm's suggestion to switch nonpos to nonpositive as well.

@efiring
Copy link
Member

efiring commented Feb 9, 2020

It's a modest difference, but I agree that "nonpositive='clip'" reads better than "nonpos='clip'". I'm guessing the kwarg (the plain version, not "nonposx" etc.) is not widely used, so the additional irritation will be moderate.

@efiring
Copy link
Member

efiring commented Feb 9, 2020

@anntzer While you are in the neighborhood, see also #16451.

@anntzer
Copy link
Contributor Author

anntzer commented Feb 9, 2020

@efiring see #16452.
I'll make the change to nonpositive here.

@jklymak
Copy link
Member

jklymak commented Feb 9, 2020

I'm still happy with this. @efiring if you are OK can you merge?

@efiring efiring merged commit 93de426 into matplotlib:master Feb 9, 2020
@anntzer anntzer deleted the morescalevalidation branch February 9, 2020 22:53
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

Successfully merging this pull request may close these issues.

5 participants