Open kcrisman opened 2 years ago
Description changed:
---
+++
@@ -9,5 +9,12 @@
gh-niranjankm has identified the problem as the use of `SelectiveFormatter`, in particular `skip_values=[0]`
Related:
-* 30983
-* #7964
+
+- #31447: list_plot labels don't indicate exponential notation by default
+- #30983: Fix tick label rendering in 2D plots, eg 4.0e6 displays as 4.0
+- #7964: axis labels in weird scientific notation
+- [Ask Sage question 63469: Plot drops exponent when scientific notation appears on the y-axis](https://ask.sagemath.org/question/63469)
+- [Ask Sage question 54462: Some 2-d plot questions](https://ask.sagemath.org/question/54462)
+- [Ask Sage question 54361: Plot ratio of Bessel functions](https://ask.sagemath.org/question/54361)
+- [2022-07 sage-devel discussion: Display of scale multiplier in scientific notation (the e notation for powers of ten) is missing for plots starting with 0](https://groups.google.com/g/sage-devel/c/s39WysaG0fI)
+
The fix is as follows:
STEP 1: Add following function to sage.plot.plot.py
def CustomScalarFormatter(replace_values=([],[])):
"""
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.
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)
I have verified the examples in docstring but check once the formatting.
STEP 2: Replace following lines in sage.plot.graphics.py
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]))
by
from sage.plot.plot import CustomScalarFormatter
subplot.yaxis.set_major_formatter(CustomScalarFormatter(replace_values=([0],[''])))
subplot.xaxis.set_major_formatter(CustomScalarFormatter(replace_values=([0],[''])))
STEP 3: (Optional) To have nice display of scientific label as x107 instead of 1e7 (say for example) by default add following line in sage.plot.graphics.py
rcParams['axes.formatter.use_mathtext'] = True
just after
from matplotlib import rcParams
in function
def matplotlib(self, filename=None,
Very sorry, now I am far from setting up and working with sage git due to my upcoming exams and also since i am new to git and i have to explore and learn some more about git. Please somebody take up this task of getting these into sage.
FWIW, a new report for this bug: https://groups.google.com/g/sage-support/c/zH_4KsKCscQ
I think this should be a blocker. After all the impact is that the y-axis labels are incorrect. I just got a report of this on our support system from a confused user.
C(p) = 90000*p/(100-p)
show('For p=0.85, cost = ', C(85))
show('For p=0.90, cost = ', C(90))
plot(C(p), (p,0,100), ymin=0, ymax=1000000)
The y range of this plot looks like it is between 0 and 1. However it is actually between 0 and 1 million:
If you include frame=True it is a little clearer maybe what is going wrong:
Perhaps this is a sufficiently serious bug to be considered a "blocker", since it is a mathematically incorrect output, which is highly likely to be seen by our largest group of users (beginners), and seriously confuse them?
I thought it's a problem of plotting near a singular point, but no, with (p,0,95)
it looks just as bad.
To compare, sympy+mathplotlib (from Anaconda, or from PyPI)
from sympy import symbols
from sympy.plotting import plot
p=symbols('p')
x=symbols('x')
C=90000*p/(100-p)
p=plot(C, (p,0,99), ymin=0, ymax=1000000) # with 99 or 100 the graph is too steep, below it's 95
That's on cocalc - not sure why I couldn't do a screenshot with Firefox, or save an image, so this is a photo of the screen.
I can confirm that https://github.com/sagemath/sage/issues/34233#issuecomment-1418180812 provides a fix. I'll make a PR.
See this sage-devel discussion for the problem. Compare
gh-niranjankm has identified the problem as the use of
SelectiveFormatter
, in particularskip_values=[0]
Related:
31447: list_plot labels don't indicate exponential notation by default
30983: Fix tick label rendering in 2D plots, eg 4.0e6 displays as 4.0
7964: axis labels in weird scientific notation
CC: @niranjankm
Component: graphics
Issue created by migration from https://trac.sagemath.org/ticket/34233