Opened 13 months ago
Last modified 4 weeks ago
#31169 new defect
Metaticket: improve quality of one-variable function plots
Reported by: | gh-DaveWitteMorris | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | sage-9.6 |
Component: | graphics | Keywords: | plotting |
Cc: | Merged in: | ||
Authors: | Reviewers: | ||
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description (last modified by )
This metaticket addresses defects in Sage's algorithm for plotting one-variable functions.
- #31089:
detect_poles
puts a gap in function plots (even if there are no poles). - #29954: plots sometimes have a gap in intervals where the function is nearly linear.
- #6895: plots should not have a vertical line segment
at places where the function has a vertical asymptote
or jump discontinuity (see also ticket:29954#comment:12
and ticket:29954#comment:13). The behaviour
of
detect_poles=True
is a small step in this direction. - "
adaptive_refinement
fails quite a lot ... because it takes the absolute error instead of a relative one" (from ticket:29954#comment:13). On intervals where the graph has large slope, even a relative error is not correct -- an angle (or the horizontal relative distance) should be used instead. - plots do not accurately locate the endpoints of an interval
where the function is not defined (see ticket:13246#comment:44
and
plot(sqrt(cos(27*x)), 0, 1)
): adaptive plotting should not be terminated when an exclusion point of the function is detected. - plots do not accurately locate the tip of a cusp
(such as
plot(abs(x - sqrt(2))^(1/3), 1, 2)
, which should touch the x-axis) - #8341:
detect_poles="show"
does not detect a vertical asymptote unless the function changes sign.
Related tickets that could also be discussed:
- #31870: Fix using matplotlib stylesheets in plots
- #13368: plot(x, xmin=1, xmax=-1) comes up empty
- #12676: plot exclude sometimes just connects instead of excluding
- #6893: plotting code improvements
- Clarify the documentation in
sage/plot/plot.py
:- The description of
sage.plot.line.line
in the class docstring says "a line determined by a sequence of points (this need not be straight!)". This should be changed to something like "a piecewise-linear curve determined by a sequence of points". - A
point
is an ordered pair(x,y)
, but, confusingly, this word is sometimes also used to refer to a real number that represents a possible value ofx
. (Regrettably, this is institutionalized in the naming of the argumentinitial_points
of the functiongenerate_plot_points
.)
- The description of
Change History (8)
comment:1 Changed 13 months ago by
- Summary changed from Metaticket: improve accuracy of one-variable function plots to Metaticket: improve quality of one-variable function plots
comment:2 Changed 13 months ago by
What I don't like about the current behaviour, is that things are connected even if adaptive refinment fails.
Examples plot(sin(1/x))
, plot(floor(x))
and similar.
This would also automatically take care of poles, if done right (of course the absolute, relative error etc are even more an issue then). at
Additionally one should also take care of functions, that need many refinments in only few locations, e.g. plot(real_nth_root(x, 3))
. You don't see the error currently, because we just connect everything, but 0
actually needs about 50 refinements, which isn't a big deal because it is only one value.
Currently, the keyword adaptive_recursion
does not really take care of this, because it does not distinguish between functions where refinement needs to be done an exponential number of times and those where this needs not to be done. Of course you can always leave this up to the user as well to discover that
plot(real_nth_root(x, 3), adaptive_recursion=50)
does indeed do many recursions but only at one location so it is not a runtime problem.
comment:3 Changed 12 months ago by
I think the default behaviour should probably be to connect the graph even if adaptive refinement fails (because it is usually the right thing to do for continuous functions), but I also strongly believe that there should be an option to disable this, and it is certainly reasonable to consider changing the default (or, at least, make detect_poles=True
the default). (I think Maple has keywords discont
and fdiscont
to disable the default behaviour.) Let's move the discussion of this issue to #6895.
I think that being smart about adaptively increasing the number of refinements is a difficult problem, but certainly worth thinking about. Let's open a new ticket when we start discussing it in detail. However, I don't think that plot(real_nth_root(x, 3))
should require a lot of refinements, because the graph is nearly linear near 0
. (The horizontal distance from the graph to the linear approximation is very small, even if the vertical distance is relatively large.)
comment:4 Changed 12 months ago by
- Description modified (diff)
comment:5 Changed 8 months ago by
- Milestone changed from sage-9.3 to sage-9.4
Moving to 9.4, as 9.3 has been released.
comment:6 Changed 8 months ago by
- Description modified (diff)
Adding #31870 (Fix using matplotlib stylesheets in plots).
comment:7 Changed 6 months ago by
- Milestone changed from sage-9.4 to sage-9.5
comment:8 Changed 4 weeks ago by
- Milestone changed from sage-9.5 to sage-9.6
Perhaps we can avoid reinventing the wheel, and also compare with the quality of plots provided by completing platforms. Here are some references that may be relevant: