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

Skip to content

ENH: Only create ticks if required #27027

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

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/matplotlib/axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import matplotlib.ticker as mticker
import matplotlib.transforms as mtransforms
import matplotlib.units as munits
from matplotlib.ticker import NullLocator

_log = logging.getLogger(__name__)

Expand Down Expand Up @@ -568,11 +569,15 @@ def __get__(self, instance, owner):
# list, then create the tick and append it.
if self._major:
instance.majorTicks = []
if isinstance(instance.major.locator, NullLocator):
return instance.majorTicks
tick = instance._get_tick(major=True)
instance.majorTicks.append(tick)
return instance.majorTicks
else:
instance.minorTicks = []
if isinstance(instance.minor.locator, NullLocator):
return instance.minorTicks
tick = instance._get_tick(major=False)
instance.minorTicks.append(tick)
return instance.minorTicks
Expand Down Expand Up @@ -2208,6 +2213,8 @@ def _get_ticks_position(self):
- "default" if only tick1line, tick2line and label1 are visible;
- "unknown" otherwise.
"""
if not len(self.majorTicks) or not len(self.minorTicks):
return "unknown"
major = self.majorTicks[0]
minor = self.minorTicks[0]
if all(tick.tick1line.get_visible()
Expand Down
5 changes: 4 additions & 1 deletion lib/matplotlib/projections/polar.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import matplotlib.ticker as mticker
import matplotlib.transforms as mtransforms
from matplotlib.spines import Spine
from matplotlib.ticker import AutoLocator


class PolarTransform(mtransforms.Transform):
Expand Down Expand Up @@ -428,8 +429,10 @@ def _set_scale(self, value, **kwargs):
"The xscale cannot be set on a polar plot")
super()._set_scale(value, **kwargs)
# LinearScale.set_default_locators_and_formatters just set the major
# locator to be an AutoLocator, so we customize it here to have ticks
# locator to be an AutoLocator(maybe), so we customize it here to have ticks
# at sensible degree multiples.
if not isinstance(self.get_major_locator(), AutoLocator):
self.set_major_locator(AutoLocator())
self.get_major_locator().set_params(steps=[1, 1.5, 3, 4.5, 9, 10])
self._wrap_locator_formatter()

Expand Down
6 changes: 5 additions & 1 deletion lib/matplotlib/scale.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,11 @@ def __init__(self, axis):

def set_default_locators_and_formatters(self, axis):
# docstring inherited
axis.set_major_locator(AutoLocator())
if (axis.axis_name == 'x' and (mpl.rcParams['xtick.top'] or mpl.rcParams['xtick.bottom']) or
axis.axis_name == 'y' and (mpl.rcParams['ytick.left'] or mpl.rcParams['ytick.right'])):
axis.set_major_locator(AutoLocator())
else:
axis.set_major_locator(NullLocator())
Copy link
Member

Choose a reason for hiding this comment

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

I think this is breaking on polar where I think these axes are named something else (r and theta?)

But I'm curious how this is helping you? Are your axes not named x and y?

Copy link
Contributor Author

@larsoner larsoner Oct 7, 2023

Choose a reason for hiding this comment

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

But I'm curious how this is helping you? Are your axes not named x and y?

This logic is copied directly from below (109-113 on main), only adapting major in place of minor. Below for the minor ticks if the axis is x (or y), and the user has x.minor.visible set to False, it uses NullLocator for minorTicks. So this was the equivalent logic (I think) for major where if the axis is x (or y), and the user has xtick.visible set to False, it uses NullLocator for majorTicks.

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 think this is breaking on polar where I think these axes are named something else (r and theta?)

I think I see something else. Assuming Polar uses a Linear scaling (I assume it does), Polar could be making an assumption that the locator is AutoLocator or whatever the default used to be before my change. Then you NullLocator.set_params(...) which is not allowed (safely at least). At least that's what I'm thinking from this traceback:

/home/runner/work/matplotlib/matplotlib/lib/matplotlib/projections/polar.py:421: in clear
    super().clear()
/home/runner/work/matplotlib/matplotlib/lib/matplotlib/axis.py:897: in clear
    self._set_scale('linear')
/home/runner/work/matplotlib/matplotlib/lib/matplotlib/projections/polar.py:433: in _set_scale
    self.get_major_locator().set_params(steps=[1, 1.5, 3, 4.5, 9, 10])
/home/runner/work/matplotlib/matplotlib/lib/matplotlib/ticker.py:1605: in set_params
    _api.warn_external(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

message = "'set_params()' not defined for locator of type <class 'matplotlib.ticker.NullLocator'>"

One easy fix/workaround is to just make clear or maybe better Polar._set_scale set the formatter to AutoFormatter since it almost immediately thereafter assumes it can set_params on it.

Copy link
Member

Choose a reason for hiding this comment

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

OK, I see - this is just not setting the locators/formatters if the ticks are turned off. That seems a reasonable short path, if a rare use case.

axis.set_major_formatter(ScalarFormatter())
axis.set_minor_formatter(NullFormatter())
# update the minor locator for x and y axis based on rcParams
Expand Down