Skip to content

which={"major", "minor", "both"} vs minor={True, False} #11773

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
anntzer opened this issue Jul 25, 2018 · 11 comments
Closed

which={"major", "minor", "both"} vs minor={True, False} #11773

anntzer opened this issue Jul 25, 2018 · 11 comments

Comments

@anntzer
Copy link
Contributor

anntzer commented Jul 25, 2018

Just mentioning it here, not that it's particularly urgent: for specification of major vs minor ticks, there is currently a mix between methods that take a which ("major"/"minor"/"both" (if applicable)) kwarg and those that take a minor (bool) kwarg. And then there are those that try to please everyone, like get_ticklabels:

        minor : bool
           If True return the minor ticklabels,
           else return the major ticklabels

        which : None, ('minor', 'major', 'both')
           Overrides `minor`.

           Selects which ticklabels to return

... ugh.

I'd suggest homogenizing to use which (as that can also handle "both"), even in the cases where "both" is not valid (in which case we just accept "major"/"minor").

Or we can wait for the ticking refactor proposed in #5665...

@tacaswell tacaswell added this to the v3.1 milestone Jul 25, 2018
@jklymak
Copy link
Member

jklymak commented Jul 25, 2018

I find “which” obscure. What about a “major” and a “minor” bool kwarg?

@timhoffm
Copy link
Member

timhoffm commented Jul 25, 2018

I wouldn't want to make separate "major" and "minor" args. It feels more natural to specify which ticks you want in a single arguement. No strong arguments bu with two separate args:

  • You_d have to care for the unreasonable minor=False, major=False case.
  • What to do in cases where "both" is not allowed? Do we still have both arguments? If yes, that's quite verbose and you have to make sure, that only one at a time is True. If not, and say minor : bool toggles the behavior, that would be an asymmetry to the case where "both" was allowed and we would have introduced "major" and "minor" there.

The naming "which" is not really good as a standalone name. However, in the context of a function signature get_ticklabels(which='minor') it's still quite readable. I don't really have a much better name. "type" and "kind" would be equally general, "labeltype" would be marginally better at the cost of being longer and a change in the API. Overall, I'd stick to "which".

@jklymak
Copy link
Member

jklymak commented Jul 25, 2018

Not sure that minor=False, major=False is unreasonable.

I'm not following your second point. If both is not allowed, either don't have both kwargs, ignore the one thats not applicable, or error if both are set True, as I guess we do if both is set.

@anntzer
Copy link
Contributor Author

anntzer commented Feb 12, 2019

I think I'm warming up to (major: bool, minor: bool). The problem of which is that sometimes it's not clear whether you're referring to major vs minor or to x vs y, e.g. in ax.grid(which="both"). OK, that's not really true because the axis is always specified with the axis keyword, but still...

OTOH the axis keyword does take values "x", "y", and "both"; we don't have e.g. grid(x=True, y=False)...

@github-actions
Copy link

This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

@github-actions github-actions bot added the status: inactive Marked by the “Stale” Github Action label May 11, 2023
@anntzer
Copy link
Contributor Author

anntzer commented May 11, 2023

It would be good to at least list the APIs where this happens before deciding what to do with it.

@oscargus
Copy link
Member

Quick grepping:

which

matplotlib/axis.py:    def set_tick_params(self, which='major', reset=False, **kwargs):
matplotlib/axis.py:    def get_tick_params(self, which='major'):
matplotlib/axis.py:    def get_ticklabels(self, minor=False, which=None):

minor

matplotlib/axes/_secondary_axes.py:    def set_ticks(self, ticks, labels=None, *, minor=False, **kwargs):
matplotlib/axis.py:    def get_ticklabels(self, minor=False, which=None):
matplotlib/axis.py:    def get_ticklines(self, minor=False):
matplotlib/axis.py:    def get_ticklocs(self, *, minor=False):
matplotlib/axis.py:    def get_ticks_direction(self, minor=False):
matplotlib/axis.py:    def set_ticklabels(self, labels, *, minor=False, fontdict=None, **kwargs):
matplotlib/axis.py:    def _set_tick_locations(self, ticks, *, minor=False):
matplotlib/axis.py:    def set_ticks(self, ticks, labels=None, *, minor=False, **kwargs):
matplotlib/colorbar.py:    def set_ticks(self, ticks, *, labels=None, minor=False, **kwargs):
matplotlib/colorbar.py:    def get_ticks(self, minor=False):
matplotlib/colorbar.py:    def set_ticklabels(self, ticklabels, *, minor=False, **kwargs):
mpl_toolkits/axisartist/grid_helper_curvelinear.py:    def get_tick_iterator(self, nth_coord, axis_side, minor=False):

major

(Had to skip the "def "-part to get some hits.)

matplotlib/axis.py:        major=True,
matplotlib/axis.py:                tick = instance._get_tick(major=True)
matplotlib/axis.py:                tick = instance._get_tick(major=False)
matplotlib/axis.py:    majorTicks = _LazyTickList(major=True)
matplotlib/axis.py:    minorTicks = _LazyTickList(major=False)
matplotlib/axis.py:        return self._tick_class(self.axes, 0, major=major, **tick_kw)
matplotlib/axis.py:            tick = self._get_tick(major=True)
matplotlib/axis.py:            tick = self._get_tick(major=False)
matplotlib/tests/test_skew.py:        return SkewXTick(self.axes, None, major=major)

Not perfect, but gives some indication at least... (There are several other APIs where which is used though, such as axis-selection.)

@timhoffm
Copy link
Member

The first major=True is actually from Tick.__init__(). So we have all three cases in public API 🤦.

@timhoffm
Copy link
Member

timhoffm commented May 11, 2023

tl;dr Changing any of this is not worth the hassle. We should live with the current slight imperfections.

Terminology: I use tri-state for the logical major/minor/both case and two-state for the logical major/minor case. Think of this as independent on the way we describe it via keyword arguments.

1) We'll have a mixture of two-state and tri-state functions

For example in set_tick_params(color="red", ...) it is reasonable to address all ticks. But for set_ticklabels() targeting "both" would not make sense.

2) Tri-state parameter variants

  1. which="major"/"minor"/"both" is a reasonable API.

  2. major=True/False, minor=True/False is awkward. major=False, minor=False is a useless edge case of that API, but can be handled well enough through a no-op or raising.

    The real issue here are the defaults. If we wanted to switch def set_tick_params(which='major', ...), the default no-argument behavior must stay for compatibility, so that we have def set_tick_params(major=True, minor=False). If the user now writes set_tick_params(minor=True) this is surprisingly equivalent to "both". To get minor only, one would have to write set_tick_params(major=False, minor=True). IMHO this disqualifies separate major/minor parameters for the tri-state.

3) Two-state parameter variants

  1. which="major"/"minor" would be possible. On the one hand, using strings for two values where a bool would suffice feels a bit verbose, on the other hand, its definition is very clear and explicit.
  2. only a default minor=False parameter is quite reasonable in many cases. Major ticks are more prominent (sometimes we don't even have minor ticks) and deserve to be the default if you have to choose between "major" and "minor". The API to addressing the minor keys get_ticklocs(minor=True) is also clear.
  3. only a default major=True is somewhat worse than be because the usage is a negation get_ticklocs(major=False) - you only say what you don't want, not what you want.

Summary

We have a mixture of two-state and tri-state functions. Tri-state functions must have the which= API. Two-state functions could have either. We need to weigh consistency (+0.5) vs. the cost of API change for the two-state functions (-0.8) vs. the advantage/disadvantage of the changed API for the two-state functions (+/-0). Numbers are my estimates. I therefore suggest to leave everything as is.

The only function we could discuss about is the ugly parameter redundancy in def get_ticklabels(self, minor=False, which=None). If one really wanted one could deprecate this. However all alternatives also have a drawback:

  • remove which: This would remove the "both" functionality, because as stated above, which is the only reasonalbe API for tri-state
  • remove minor: Logically, it is not needed. However, that breaks with the current approximate systematic API that all get/set functions except for tick_params use the minor API.

@github-actions github-actions bot removed the status: inactive Marked by the “Stale” Github Action label May 12, 2023
Copy link

This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

@github-actions github-actions bot added the status: inactive Marked by the “Stale” Github Action label Aug 14, 2024
@timhoffm
Copy link
Member

While the mixture is not great, I believe there is no reasonable way to improve. We need to live with the current state. See #11773 (comment) for details.

@timhoffm timhoffm closed this as not planned Won't fix, can't repro, duplicate, stale Aug 14, 2024
@timhoffm timhoffm removed the status: inactive Marked by the “Stale” Github Action label Aug 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants