Skip to content
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

Missing scientific labels #34233

Open
kcrisman opened this issue Jul 28, 2022 · 8 comments · May be fixed by #37502
Open

Missing scientific labels #34233

kcrisman opened this issue Jul 28, 2022 · 8 comments · May be fixed by #37502

Comments

@kcrisman
Copy link
Member

See this sage-devel discussion for the problem. Compare

sage:  plot(x^2,(x,0,5000))  # missing display of 1e7 above y-axis
sage:  plot(x^2,(x,50,5000))  # missing display of 1e7 above y-axis
sage:  plot(x^2,(x,100,5000))  # display of 1e7 above y-axis is visible

gh-niranjankm has identified the problem as the use of SelectiveFormatter, in particular skip_values=[0]

Related:

CC: @niranjankm

Component: graphics

Issue created by migration from https://trac.sagemath.org/ticket/34233

@kcrisman kcrisman added this to the sage-9.7 milestone Jul 28, 2022
@slel

This comment has been minimized.

@niranjankm
Copy link
Mannequin

niranjankm mannequin commented Aug 7, 2022

comment:2

See:
https://stackoverflow.com/a/73371333/18152652

@niranjankm
Copy link
Mannequin

niranjankm mannequin commented Aug 7, 2022

comment:3

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.

@mkoeppe mkoeppe modified the milestones: sage-9.7, sage-9.8 Sep 19, 2022
@egourgoulhon
Copy link
Member

comment:5

FWIW, a new report for this bug:
https://groups.google.com/g/sage-support/c/zH_4KsKCscQ

@mkoeppe mkoeppe removed this from the sage-9.8 milestone Jan 29, 2023
@williamstein
Copy link
Contributor

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:

image

If you include frame=True it is a little clearer maybe what is going wrong:

image

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?

@dimpase
Copy link
Member

dimpase commented Feb 28, 2024

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

p

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.

@dimpase
Copy link
Member

dimpase commented Feb 28, 2024

I can confirm that #34233 (comment) provides a fix.
I'll make a PR.

dimpase added a commit to dimpase/sage that referenced this issue Feb 28, 2024
Fix is provided in a comment by @niranjankm (Niranjana K.M.)
@dimpase dimpase linked a pull request Feb 28, 2024 that will close this issue
5 tasks
dimpase pushed a commit to dimpase/sage that referenced this issue Feb 29, 2024
Fix is provided in a comment by @niranjankm (Niranjana K.M.)
dimpase added a commit to dimpase/sage that referenced this issue Feb 29, 2024
also, adjust one other example to show customized large-scale y-axis
@kcrisman
Copy link
Member Author

kcrisman commented Mar 1, 2024

#37502 does fix this as such, though see the related problems it causes in its current version (likely quite fixable).

dimpase pushed a commit to dimpase/sage that referenced this issue Mar 3, 2024
Fix is provided in a comment by @niranjankm (Niranjana K.M.)
dimpase added a commit to dimpase/sage that referenced this issue Mar 3, 2024
also, adjust one other example to show customized large-scale y-axis
dimpase pushed a commit to dimpase/sage that referenced this issue Mar 5, 2024
Fix is provided in a comment by @niranjankm (Niranjana K.M.)
dimpase added a commit to dimpase/sage that referenced this issue Mar 5, 2024
also, adjust one other example to show customized large-scale y-axis
dimpase pushed a commit to dimpase/sage that referenced this issue Mar 10, 2024
Fix is provided in a comment by @niranjankm (Niranjana K.M.)
dimpase added a commit to dimpase/sage that referenced this issue Mar 10, 2024
also, adjust one other example to show customized large-scale y-axis
dimpase pushed a commit to dimpase/sage that referenced this issue Mar 29, 2024
Fix is provided in a comment by @niranjankm (Niranjana K.M.)
dimpase added a commit to dimpase/sage that referenced this issue Mar 29, 2024
also, adjust one other example to show customized large-scale y-axis
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants