From 179ae6da8b6ae262e061f43788e73ae6092180a2 Mon Sep 17 00:00:00 2001 From: Niranjana K M Date: Wed, 28 Feb 2024 20:18:07 +0000 Subject: [PATCH] This fixes #34233 Fix is provided in a comment by @niranjankm (Niranjana K.M.) --- src/sage/plot/graphics.py | 9 +++--- src/sage/plot/plot.py | 59 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index 8a61068887f..e159381ee83 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -2758,6 +2758,7 @@ def matplotlib(self, filename=None, from matplotlib import rcParams rcParams['mathtext.fontset'] = 'cm' rcParams['mathtext.rm'] = 'serif' + rcParams['axes.formatter.use_mathtext'] = True import matplotlib.pyplot as plt if stylesheet in plt.style.available: @@ -3035,11 +3036,9 @@ def matplotlib(self, filename=None, # Make the zero tick labels disappear if the axes cross # inside the picture, but only if log scale is not used if (xmiddle and ymiddle and xscale == 'linear' == yscale): - from sage.plot.plot import SelectiveFormatter - subplot.yaxis.set_major_formatter(SelectiveFormatter( - subplot.yaxis.get_major_formatter(), skip_values=[0])) - subplot.xaxis.set_major_formatter(SelectiveFormatter( - subplot.xaxis.get_major_formatter(), skip_values=[0])) + from sage.plot.plot import CustomScalarFormatter + subplot.yaxis.set_major_formatter(CustomScalarFormatter(replace_values=([0],['']))) + subplot.xaxis.set_major_formatter(CustomScalarFormatter(replace_values=([0],['']))) else: for spine in subplot.spines.values(): diff --git a/src/sage/plot/plot.py b/src/sage/plot/plot.py index 20a71ef8bd1..fc7ab254c51 100644 --- a/src/sage/plot/plot.py +++ b/src/sage/plot/plot.py @@ -4138,3 +4138,62 @@ def generate_plot_points(f, xrange, plot_points=5, adaptive_tolerance=0.01, if excluded: return data, excluded_points return data + +def CustomScalarFormatter(replace_values=([],[])): + r""" + This matplotlib formatter selectively replaces the given tick labels. + Takes a tuple or list of two lists as argument. First list labels will be replaced by second list labels. + Note that the first label entries are cumpulsorily int or float values. No strings. + No such restrictions for the second list. Because they will be anyway converted to strings in the end. + + Authored by Niranjana K. M. + + EXAMPLES: + + :: + + sage: from sage.plot.plot import CustomScalarFormatter + sage: import matplotlib.pyplot as plt + sage: import numpy as np + sage: z = np.linspace(0, 5000, 100) + sage: fig, ax = plt.subplots() + sage: xmajorformatter = CustomScalarFormatter(replace_values=([2000,0],['$x_0$',''])) + sage: ymajorformatter = CustomScalarFormatter(replace_values=([1E7,0],['$y_0$',''])) + sage: ax.xaxis.set_major_formatter(xmajorformatter) + sage: ax.yaxis.set_major_formatter(ymajorformatter) + sage: ax.plot(z,z**2) + sage: plt.show() + + :: + + sage: from sage.plot.plot import CustomScalarFormatter + sage: from matplotlib import font_manager + sage: plot(x^2, (x,100,5000), tick_formatter = [ CustomScalarFormatter(replace_values=[[2000,0],['$x_0$','']]), CustomScalarFormatter(replace_values=[[1E7,0],['$y_0$','']]) ]) + + """ + + from matplotlib.ticker import ScalarFormatter + + class _CustomScalarFormatter(ScalarFormatter): + def __init__(self, useOffset=None, useMathText=None, useLocale=None, replace_values=([],[])): + super().__init__(useOffset=None, useMathText=None, useLocale=None) + self.replace_values = replace_values + + def __call__(self, x, pos=None): + """ + Return the format for tick value *x* at position *pos*. + """ + if len(self.locs) == 0: + return '' + #elif x == 0: + # return '' + elif x in self.replace_values[0]: + idx = self.replace_values[0].index(x) + return str(self.replace_values[1][idx]) + else: + xp = (x - self.offset) / (10. ** self.orderOfMagnitude) + if abs(xp) < 1e-8: + xp = 0 + return self._format_maybe_minus_and_locale(self.format, xp) + + return _CustomScalarFormatter(replace_values=replace_values)