Plotting utilities

class sage.plot.misc.FastCallablePlotWrapper(ff, imag_tol)[source]

Bases: FastCallableFloatWrapper

A fast-callable wrapper for plotting that returns nan instead of raising an error whenever the imaginary tolerance is exceeded.

A detailed rationale for this can be found in the superclass documentation.

EXAMPLES:

The float incarnation of “not a number” is returned instead of an error being thrown if the answer is complex:

sage: from sage.plot.misc import FastCallablePlotWrapper
sage: f = sqrt(x)
sage: ff = fast_callable(f, vars=[x], domain=CDF)
sage: fff = FastCallablePlotWrapper(ff, imag_tol=1e-8)
sage: fff(1)
1.0
sage: fff(-1)
nan
>>> from sage.all import *
>>> from sage.plot.misc import FastCallablePlotWrapper
>>> f = sqrt(x)
>>> ff = fast_callable(f, vars=[x], domain=CDF)
>>> fff = FastCallablePlotWrapper(ff, imag_tol=RealNumber('1e-8'))
>>> fff(Integer(1))
1.0
>>> fff(-Integer(1))
nan
sage.plot.misc.get_matplotlib_linestyle(linestyle, return_type)[source]

Function which translates between matplotlib linestyle in short notation (i.e. ‘-’, ‘–’, ‘:’, ‘-.’) and long notation (i.e. ‘solid’, ‘dashed’, ‘dotted’, ‘dashdot’ ).

If linestyle is none of these allowed options, the function raises a ValueError.

INPUT:

  • linestyle – the style of the line, which is one of
    • '-' or 'solid'

    • '--' or 'dashed'

    • '-.' or 'dash dot'

    • ':' or 'dotted'

    • "None" or " " or "" (nothing)

    The linestyle can also be prefixed with a drawing style (e.g., 'steps--')

    • 'default' (connect the points with straight lines)

    • 'steps' or 'steps-pre' (step function; horizontal line is to the left of point)

    • 'steps-mid' (step function; points are in the middle of horizontal lines)

    • 'steps-post' (step function; horizontal line is to the right of point)

    If linestyle is None (of type NoneType), then we return it back unmodified.

  • return_type – the type of linestyle that should be output. This argument takes only two values - 'long' or 'short'

EXAMPLES:

Here is an example how to call this function:

sage: from sage.plot.misc import get_matplotlib_linestyle
sage: get_matplotlib_linestyle(':', return_type='short')
':'

sage: get_matplotlib_linestyle(':', return_type='long')
'dotted'
>>> from sage.all import *
>>> from sage.plot.misc import get_matplotlib_linestyle
>>> get_matplotlib_linestyle(':', return_type='short')
':'

>>> get_matplotlib_linestyle(':', return_type='long')
'dotted'
sage.plot.misc.setup_for_eval_on_grid(funcs, ranges, plot_points=None, return_vars=False, imaginary_tolerance=1e-08)[source]

Calculate the necessary parameters to construct a list of points, and make the functions fast_callable.

INPUT:

  • funcs – a function, or a list, tuple, or vector of functions

  • ranges – list of ranges. A range can be a 2-tuple of numbers specifying the minimum and maximum, or a 3-tuple giving the variable explicitly.

  • plot_points – tuple of integers specifying the number of plot points for each range. If a single number is specified, it will be the value for all ranges. This defaults to 2.

  • return_vars – (default: False) if True, return the variables, in order

  • imaginary_tolerance – (default: 1e-8) if an imaginary number arises (due, for example, to numerical issues), this tolerance specifies how large it has to be in magnitude before we raise an error. In other words, imaginary parts smaller than this are ignored in your plot points.

OUTPUT:

  • fast_funcs – if only one function passed, then a fast callable function. If funcs is a list or tuple, then a tuple of fast callable functions is returned.

  • range_specs – list of range_specs: for each range, a tuple is returned of the form (range_min, range_max, range_step) such that srange(range_min, range_max, range_step, include_endpoint=True) gives the correct points for evaluation.

EXAMPLES:

sage: x,y,z=var('x,y,z')
sage: f(x,y)=x+y-z
sage: g(x,y)=x+y
sage: h(y)=-y
sage: sage.plot.misc.setup_for_eval_on_grid(f, [(0, 2),(1,3),(-4,1)], plot_points=5)
(<sage...>, [(0.0, 2.0, 0.5), (1.0, 3.0, 0.5), (-4.0, 1.0, 1.25)])
sage: sage.plot.misc.setup_for_eval_on_grid([g,h], [(0, 2),(-1,1)], plot_points=5)
((<sage...>, <sage...>), [(0.0, 2.0, 0.5), (-1.0, 1.0, 0.5)])
sage: sage.plot.misc.setup_for_eval_on_grid([sin,cos], [(-1,1)], plot_points=9)
((<sage...>, <sage...>), [(-1.0, 1.0, 0.25)])
sage: sage.plot.misc.setup_for_eval_on_grid([lambda x: x^2,cos], [(-1,1)], plot_points=9)
((<function <lambda> ...>, <sage...>), [(-1.0, 1.0, 0.25)])
sage: sage.plot.misc.setup_for_eval_on_grid([x+y], [(x,-1,1),(y,-2,2)])
((<sage...>,), [(-1.0, 1.0, 2.0), (-2.0, 2.0, 4.0)])
sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,-1,1),(y,-1,1)], plot_points=[4,9])
(<sage...>, [(-1.0, 1.0, 0.6666666666666666), (-1.0, 1.0, 0.25)])
sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,-1,1),(y,-1,1)], plot_points=[4,9,10])
Traceback (most recent call last):
...
ValueError: plot_points must be either an integer or a list of integers, one for each range
sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(1,-1),(y,-1,1)], plot_points=[4,9,10])
Traceback (most recent call last):
...
ValueError: Some variable ranges specify variables while others do not
>>> from sage.all import *
>>> x,y,z=var('x,y,z')
>>> __tmp__=var("x,y"); f = symbolic_expression(x+y-z).function(x,y)
>>> __tmp__=var("x,y"); g = symbolic_expression(x+y).function(x,y)
>>> __tmp__=var("y"); h = symbolic_expression(-y).function(y)
>>> sage.plot.misc.setup_for_eval_on_grid(f, [(Integer(0), Integer(2)),(Integer(1),Integer(3)),(-Integer(4),Integer(1))], plot_points=Integer(5))
(<sage...>, [(0.0, 2.0, 0.5), (1.0, 3.0, 0.5), (-4.0, 1.0, 1.25)])
>>> sage.plot.misc.setup_for_eval_on_grid([g,h], [(Integer(0), Integer(2)),(-Integer(1),Integer(1))], plot_points=Integer(5))
((<sage...>, <sage...>), [(0.0, 2.0, 0.5), (-1.0, 1.0, 0.5)])
>>> sage.plot.misc.setup_for_eval_on_grid([sin,cos], [(-Integer(1),Integer(1))], plot_points=Integer(9))
((<sage...>, <sage...>), [(-1.0, 1.0, 0.25)])
>>> sage.plot.misc.setup_for_eval_on_grid([lambda x: x**Integer(2),cos], [(-Integer(1),Integer(1))], plot_points=Integer(9))
((<function <lambda> ...>, <sage...>), [(-1.0, 1.0, 0.25)])
>>> sage.plot.misc.setup_for_eval_on_grid([x+y], [(x,-Integer(1),Integer(1)),(y,-Integer(2),Integer(2))])
((<sage...>,), [(-1.0, 1.0, 2.0), (-2.0, 2.0, 4.0)])
>>> sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,-Integer(1),Integer(1)),(y,-Integer(1),Integer(1))], plot_points=[Integer(4),Integer(9)])
(<sage...>, [(-1.0, 1.0, 0.6666666666666666), (-1.0, 1.0, 0.25)])
>>> sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,-Integer(1),Integer(1)),(y,-Integer(1),Integer(1))], plot_points=[Integer(4),Integer(9),Integer(10)])
Traceback (most recent call last):
...
ValueError: plot_points must be either an integer or a list of integers, one for each range
>>> sage.plot.misc.setup_for_eval_on_grid(x+y, [(Integer(1),-Integer(1)),(y,-Integer(1),Integer(1))], plot_points=[Integer(4),Integer(9),Integer(10)])
Traceback (most recent call last):
...
ValueError: Some variable ranges specify variables while others do not

Beware typos: a comma which should be a period, for instance:

sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x, 1, 2), (y, 0,1, 0.2)], plot_points=[4,9,10])
Traceback (most recent call last):
...
ValueError: At least one variable range has more than 3 entries: each should either have 2 or 3 entries, with one of the forms (xmin, xmax) or (x, xmin, xmax)

sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(y,1,-1),(x,-1,1)], plot_points=5)
(<sage...>, [(-1.0, 1.0, 0.5), (-1.0, 1.0, 0.5)])
sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,1,-1),(x,-1,1)], plot_points=5)
Traceback (most recent call last):
...
ValueError: range variables should be distinct, but there are duplicates
sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,1,1),(y,-1,1)])
Traceback (most recent call last):
...
ValueError: plot start point and end point must be different
sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,1,-1),(y,-1,1)], return_vars=True)
(<sage...>, [(-1.0, 1.0, 2.0), (-1.0, 1.0, 2.0)], [x, y])
sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(y,1,-1),(x,-1,1)], return_vars=True)
(<sage...>, [(-1.0, 1.0, 2.0), (-1.0, 1.0, 2.0)], [y, x])
>>> from sage.all import *
>>> sage.plot.misc.setup_for_eval_on_grid(x+y, [(x, Integer(1), Integer(2)), (y, Integer(0),Integer(1), RealNumber('0.2'))], plot_points=[Integer(4),Integer(9),Integer(10)])
Traceback (most recent call last):
...
ValueError: At least one variable range has more than 3 entries: each should either have 2 or 3 entries, with one of the forms (xmin, xmax) or (x, xmin, xmax)

>>> sage.plot.misc.setup_for_eval_on_grid(x+y, [(y,Integer(1),-Integer(1)),(x,-Integer(1),Integer(1))], plot_points=Integer(5))
(<sage...>, [(-1.0, 1.0, 0.5), (-1.0, 1.0, 0.5)])
>>> sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,Integer(1),-Integer(1)),(x,-Integer(1),Integer(1))], plot_points=Integer(5))
Traceback (most recent call last):
...
ValueError: range variables should be distinct, but there are duplicates
>>> sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,Integer(1),Integer(1)),(y,-Integer(1),Integer(1))])
Traceback (most recent call last):
...
ValueError: plot start point and end point must be different
>>> sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,Integer(1),-Integer(1)),(y,-Integer(1),Integer(1))], return_vars=True)
(<sage...>, [(-1.0, 1.0, 2.0), (-1.0, 1.0, 2.0)], [x, y])
>>> sage.plot.misc.setup_for_eval_on_grid(x+y, [(y,Integer(1),-Integer(1)),(x,-Integer(1),Integer(1))], return_vars=True)
(<sage...>, [(-1.0, 1.0, 2.0), (-1.0, 1.0, 2.0)], [y, x])
sage.plot.misc.unify_arguments(funcs)[source]

Return a tuple of variables of the functions, as well as the number of “free” variables (i.e., variables that defined in a callable function).

INPUT:

  • funcs – list of functions; these can be symbolic expressions, polynomials, etc.

OUTPUT: functions, expected arguments

  • A tuple of variables in the functions

  • A tuple of variables that were “free” in the functions

EXAMPLES:

sage: x,y,z=var('x,y,z')
sage: f(x,y)=x+y-z
sage: g(x,y)=x+y
sage: h(y)=-y
sage: sage.plot.misc.unify_arguments((f,g,h))
((x, y, z), (z,))
sage: sage.plot.misc.unify_arguments((g,h))
((x, y), ())
sage: sage.plot.misc.unify_arguments((f,z))
((x, y, z), (z,))
sage: sage.plot.misc.unify_arguments((h,z))
((y, z), (z,))
sage: sage.plot.misc.unify_arguments((x+y,x-y))
((x, y), (x, y))
>>> from sage.all import *
>>> x,y,z=var('x,y,z')
>>> __tmp__=var("x,y"); f = symbolic_expression(x+y-z).function(x,y)
>>> __tmp__=var("x,y"); g = symbolic_expression(x+y).function(x,y)
>>> __tmp__=var("y"); h = symbolic_expression(-y).function(y)
>>> sage.plot.misc.unify_arguments((f,g,h))
((x, y, z), (z,))
>>> sage.plot.misc.unify_arguments((g,h))
((x, y), ())
>>> sage.plot.misc.unify_arguments((f,z))
((x, y, z), (z,))
>>> sage.plot.misc.unify_arguments((h,z))
((y, z), (z,))
>>> sage.plot.misc.unify_arguments((x+y,x-y))
((x, y), (x, y))