diff --git a/doc/api/next_api_changes/deprecations/23014-OG.rst b/doc/api/next_api_changes/deprecations/23014-OG.rst new file mode 100644 index 000000000000..b7d995e22802 --- /dev/null +++ b/doc/api/next_api_changes/deprecations/23014-OG.rst @@ -0,0 +1,10 @@ +Methods to set parameters in ``LogLocator`` and ``LogFormatter*`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In `~.LogFormatter` and derived subclasses, the methods ``base`` and +``label_minor`` for setting the respective parameter are deprecated and +replaced by ``set_base`` and ``set_label_minor``, respectively. + +In `~.LogLocator`, the methods ``base`` and ``subs`` for setting the +respective parameter are deprecated. Instead, use +``set_params(base=..., subs=...)``. diff --git a/lib/matplotlib/tests/test_ticker.py b/lib/matplotlib/tests/test_ticker.py index d8c8c7d9e764..d2a50a1d735a 100644 --- a/lib/matplotlib/tests/test_ticker.py +++ b/lib/matplotlib/tests/test_ticker.py @@ -585,6 +585,8 @@ class TestScalarFormatter: use_offset_data = [True, False] + useMathText_data = [True, False] + # (sci_type, scilimits, lim, orderOfMag, fewticks) scilimits_data = [ (False, (0, 0), (10.0, 20.0), 0, False), @@ -643,6 +645,19 @@ def test_use_offset(self, use_offset): with mpl.rc_context({'axes.formatter.useoffset': use_offset}): tmp_form = mticker.ScalarFormatter() assert use_offset == tmp_form.get_useOffset() + assert tmp_form.offset == 0 + + @pytest.mark.parametrize('use_math_text', useMathText_data) + def test_useMathText(self, use_math_text): + with mpl.rc_context({'axes.formatter.use_mathtext': use_math_text}): + tmp_form = mticker.ScalarFormatter() + assert use_math_text == tmp_form.get_useMathText() + + def test_set_use_offset_float(self): + tmp_form = mticker.ScalarFormatter() + tmp_form.set_useOffset(0.5) + assert not tmp_form.get_useOffset() + assert tmp_form.offset == 0.5 def test_use_locale(self): conv = locale.localeconv() @@ -695,6 +710,8 @@ def test_cursor_dummy_axis(self, data, expected): sf.axis.set_view_interval(0, 10) fmt = sf.format_data_short assert fmt(data) == expected + assert sf.axis.get_tick_space() == 9 + assert sf.axis.get_minpos() == 0 def test_mathtext_ticks(self): mpl.rcParams.update({ @@ -708,6 +725,11 @@ def test_mathtext_ticks(self): ax.set_xticks([-1, 0, 1]) fig.canvas.draw() + def test_empty_locs(self): + sf = mticker.ScalarFormatter() + sf.set_locs([]) + assert sf(0.5) == '' + class FakeAxis: """Allow Formatter to be called without having a "full" plot set up.""" @@ -1485,7 +1507,7 @@ def test_remove_overlap(remove_overlapping_locs, expected_num): def test_bad_locator_subs(sub): ll = mticker.LogLocator() with pytest.raises(ValueError): - ll.subs(sub) + ll.set_params(subs=sub) @pytest.mark.parametrize('numticks', [1, 2, 3, 9]) @@ -1496,3 +1518,19 @@ def test_small_range_loglocator(numticks): for top in [5, 7, 9, 11, 15, 50, 100, 1000]: ticks = ll.tick_values(.5, top) assert (np.diff(np.log10(ll.tick_values(6, 150))) == 1).all() + + +def test_NullFormatter(): + formatter = mticker.NullFormatter() + assert formatter(1.0) == '' + assert formatter.format_data(1.0) == '' + assert formatter.format_data_short(1.0) == '' + + +@pytest.mark.parametrize('formatter', ( + mticker.FuncFormatter(lambda a: f'val: {a}'), + mticker.FixedFormatter(('foo', 'bar')))) +def test_set_offset_string(formatter): + assert formatter.get_offset() == '' + formatter.set_offset_string('mpl') + assert formatter.get_offset() == 'mpl' diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py index ac5865cc2576..da9582849f22 100644 --- a/lib/matplotlib/ticker.py +++ b/lib/matplotlib/ticker.py @@ -446,33 +446,12 @@ def __init__(self, useOffset=None, useMathText=None, useLocale=None): mpl.rcParams['axes.formatter.offset_threshold'] self.set_useOffset(useOffset) self._usetex = mpl.rcParams['text.usetex'] - if useMathText is None: - useMathText = mpl.rcParams['axes.formatter.use_mathtext'] - if useMathText is False: - try: - from matplotlib import font_manager - ufont = font_manager.findfont( - font_manager.FontProperties( - mpl.rcParams["font.family"] - ), - fallback_to_default=False, - ) - except ValueError: - ufont = None - - if ufont == str(cbook._get_data_path("fonts/ttf/cmr10.ttf")): - _api.warn_external( - "cmr10 font should ideally be used with " - "mathtext, set axes.formatter.use_mathtext to True" - ) self.set_useMathText(useMathText) self.orderOfMagnitude = 0 self.format = '' self._scientific = True self._powerlimits = mpl.rcParams['axes.formatter.limits'] - if useLocale is None: - useLocale = mpl.rcParams['axes.formatter.use_locale'] - self._useLocale = useLocale + self.set_useLocale(useLocale) def get_useOffset(self): """ @@ -579,6 +558,23 @@ def set_useMathText(self, val): """ if val is None: self._useMathText = mpl.rcParams['axes.formatter.use_mathtext'] + if self._useMathText is False: + try: + from matplotlib import font_manager + ufont = font_manager.findfont( + font_manager.FontProperties( + mpl.rcParams["font.family"] + ), + fallback_to_default=False, + ) + except ValueError: + ufont = None + + if ufont == str(cbook._get_data_path("fonts/ttf/cmr10.ttf")): + _api.warn_external( + "cmr10 font should ideally be used with " + "mathtext, set axes.formatter.use_mathtext to True" + ) else: self._useMathText = val @@ -890,8 +886,8 @@ def __init__(self, base=10.0, labelOnlyBase=False, minor_thresholds=None, linthresh=None): - self._base = float(base) - self.labelOnlyBase = labelOnlyBase + self.set_base(base) + self.set_label_minor(labelOnlyBase) if minor_thresholds is None: if mpl.rcParams['_internal.classic_mode']: minor_thresholds = (0, 0) @@ -901,6 +897,7 @@ def __init__(self, base=10.0, labelOnlyBase=False, self._sublabels = None self._linthresh = linthresh + @_api.deprecated("3.6", alternative='set_base()') def base(self, base): """ Change the *base* for labeling. @@ -908,12 +905,33 @@ def base(self, base): .. warning:: Should always match the base used for :class:`LogLocator` """ - self._base = base + self.set_base(base) + def set_base(self, base): + """ + Change the *base* for labeling. + + .. warning:: + Should always match the base used for :class:`LogLocator` + """ + self._base = float(base) + + @_api.deprecated("3.6", alternative='set_label_minor()') def label_minor(self, labelOnlyBase): """ Switch minor tick labeling on or off. + Parameters + ---------- + labelOnlyBase : bool + If True, label ticks only at integer powers of base. + """ + self.set_label_minor(labelOnlyBase) + + def set_label_minor(self, labelOnlyBase): + """ + Switch minor tick labeling on or off. + Parameters ---------- labelOnlyBase : bool @@ -2250,7 +2268,8 @@ def __init__(self, base=10.0, subs=(1.0,), numdecs=4, numticks=None): Parameters ---------- base : float, default: 10.0 - The base of the log used, so ticks are placed at ``base**n``. + The base of the log used, so major ticks are placed at + ``base**n``, n integer. subs : None or str or sequence of float, default: (1.0,) Gives the multiples of integer powers of the base at which to place ticks. The default places ticks only at @@ -2273,30 +2292,35 @@ def __init__(self, base=10.0, subs=(1.0,), numdecs=4, numticks=None): numticks = 15 else: numticks = 'auto' - self.base(base) - self.subs(subs) + self._base = float(base) + self._set_subs(subs) self.numdecs = numdecs self.numticks = numticks def set_params(self, base=None, subs=None, numdecs=None, numticks=None): """Set parameters within this locator.""" if base is not None: - self.base(base) + self._base = float(base) if subs is not None: - self.subs(subs) + self._set_subs(subs) if numdecs is not None: self.numdecs = numdecs if numticks is not None: self.numticks = numticks - # FIXME: these base and subs functions are contrary to our - # usual and desired API. - + @_api.deprecated("3.6", alternative='set_params(base=...)') def base(self, base): """Set the log base (major tick every ``base**i``, i integer).""" self._base = float(base) + @_api.deprecated("3.6", alternative='set_params(subs=...)') def subs(self, subs): + """ + Set the minor ticks for the log scaling every ``base**i*subs[j]``. + """ + self._set_subs(subs) + + def _set_subs(self, subs): """ Set the minor ticks for the log scaling every ``base**i*subs[j]``. """