Sage provides extensive 2D plotting functionality. The underlying rendering is done using the matplotlib Python library.
The following graphics primitives are supported:
The following plotting functions are supported:
The following miscellaneous Graphics functions are included:
Type ? after each primitive in Sage for help and examples.
EXAMPLES: We construct a plot involving several graphics objects:
sage: G = plot(cos, -5, 5, thickness=5, rgbcolor=(0.5,1,0.5))
sage: P = polygon([[1,2], [5,6], [5,0]], rgbcolor=(1,0,0))
sage: P # show it
We draw a circle and a curve:
sage: circle((1,1), 1) + plot(x^2, (0,5))
Notice that the above circle is not round, because the aspect ratio of the coordinate system is not 1:1. The aspect_ratio option to show allows us to fix this:
sage: show(circle((1,1), 1) + plot(x^2, (0,5)), aspect_ratio=1)
With an aspect ratio of 2 the circle is squashed half way down (it looks twice as wide as it does tall):
sage: show(circle((1,1), 1) + plot(x^2, (0,5)), aspect_ratio=2)
Use figsize to set the actual aspect ratio of the rendered image (i.e., of the frame). For example, this image is twice as many pixels wide as it is tall:
sage: show(circle((1,1), 1) + plot(x^2, (0,5)), figsize=[8,4])
Next we construct the reflection of the above polygon about the
-axis by iterating over the list of first-coordinates of
the first graphic element of
(which is the actual
Polygon; note that
is a Graphics object, which consists
of a single polygon):
sage: Q = polygon([(-x,y) for x,y in P[0]], rgbcolor=(0,0,1))
sage: Q # show it
We combine together different graphics objects using “+”:
sage: H = G + P + Q
sage: print H
Graphics object consisting of 3 graphics primitives
sage: type(H)
<class 'sage.plot.plot.Graphics'>
sage: H[1]
Polygon defined by 3 points
sage: list(H[1])
[(1.0, 2.0), (5.0, 6.0), (5.0, 0.0)]
sage: H # show it
We can put text in a graph:
sage: L = [[cos(pi*i/100)^3,sin(pi*i/100)] for i in range(200)]
sage: p = line(L, rgbcolor=(1/4,1/8,3/4))
sage: t = text('A Bulb', (1.5, 0.25))
sage: x = text('x axis', (1.5,-0.2))
sage: y = text('y axis', (0.4,0.9))
sage: g = p+t+x+y
sage: g.show(xmin=-1.5, xmax=2, ymin=-1, ymax=1)
We plot the Riemann zeta function along the critical line and see the first few zeros:
sage: i = CDF.0 # define i this way for maximum speed.
sage: p1 = plot(lambda t: arg(zeta(0.5+t*i)), 1,27,rgbcolor=(0.8,0,0))
sage: p2 = plot(lambda t: abs(zeta(0.5+t*i)), 1,27,rgbcolor=hue(0.7))
sage: print p1 + p2
Graphics object consisting of 2 graphics primitives
sage: p1 + p2 # display it
Many concentric circles shrinking toward the origin:
sage: show(sum(circle((i,0), i, hue=sin(i/10)) for i in [10,9.9,..,0]), aspect_ratio=1)
Here is a pretty graph:
sage: g = Graphics()
sage: for i in range(60):
... p = polygon([(i*cos(i),i*sin(i)), (0,i), (i,0)],\
... rgbcolor=hue(i/40+0.4), alpha=0.2)
... g = g + p
...
sage: g.show(dpi=200, axes=False)
Another graph:
sage: x = var('x')
sage: P = plot(sin(x)/x, -4,4, rgbcolor=(0,0,1)) + \
... plot(x*cos(x), -4,4, rgbcolor=(1,0,0)) + \
... plot(tan(x),-4,4,rgbcolor=(0,1,0))
...
sage: P.show(ymin=-pi,ymax=pi)
PYX EXAMPLES: These are some examples of plots similar to some of the plots in the PyX (http://pyx.sourceforge.net) documentation:
Symbolline:
sage: y(x) = x*sin(x^2)
sage: v = [(x, y(x)) for x in [-3,-2.95,..,3]]
sage: show(points(v, rgbcolor=(0.2,0.6, 0.1), pointsize=30) + plot(spline(v), -3.1, 3))
Cycliclink:
sage: x = var('x')
sage: g1 = plot(cos(20*x)*exp(-2*x), 0, 1)
sage: g2 = plot(2*exp(-30*x) - exp(-3*x), 0, 1)
sage: show(graphics_array([g1, g2], 2, 1), xmin=0)
Pi Axis: In the PyX manual, the point of this example is to show labeling the X-axis using rational multiples of Pi. Sage currently has no support for controlling how the ticks on the x and y axes are labeled, so this is really a bad example:
sage: g1 = plot(sin(x), 0, 2*pi)
sage: g2 = plot(cos(x), 0, 2*pi, linestyle = "--")
sage: g1 + g2 # show their sum
An illustration of integration:
sage: f(x) = (x-3)*(x-5)*(x-7)+40
sage: P = line([(2,0),(2,f(2))], rgbcolor=(0,0,0))
sage: P += line([(8,0),(8,f(8))], rgbcolor=(0,0,0))
sage: P += polygon([(2,0),(2,f(2))] + [(x, f(x)) for x in [2,2.1,..,8]] + [(8,0),(2,0)], rgbcolor=(0.8,0.8,0.8))
sage: P += text("$\\int_{a}^b f(x) dx$", (5, 20), fontsize=16, rgbcolor=(0,0,0))
sage: P += plot(f, 1, 8.5, thickness=3)
sage: P # show the result
NUMERICAL PLOTTING:
Sage also provides 2D plotting with an interface that is a likely very familiar to people doing numerical computation. For example,
sage: from pylab import *
sage: t = arange(0.0, 2.0, 0.01)
sage: s = sin(2*pi*t)
sage: P = plot(t, s, linewidth=1.0)
sage: xl = xlabel('time (s)')
sage: yl = ylabel('voltage (mV)')
sage: t = title('About as simple as it gets, folks')
sage: grid(True)
sage: savefig('sage.png')
Since the above overwrites many Sage plotting functions, we reset the state of Sage, so that the examples below work!
sage: reset()
See http://matplotlib.sourceforge.net for complete documentation about how to use Matplotlib.
TESTS: We test dumping and loading a plot.
sage: p = plot(sin(x), (x, 0,2*pi))
sage: Q = loads(dumps(p))
AUTHORS:
The Graphics object is an empty list of graphics objects It is useful to use this object when initializing a for loop where different graphics object will be added to the empty object.
EXAMPLES:
sage: G = Graphics(); print G
Graphics object consisting of 0 graphics primitives
sage: c = circle((1,1), 1)
sage: G+=c; print G
Graphics object consisting of 1 graphics primitive
Here we make a graphic of embedded isosceles triangles, coloring each one with a different color as we go:
sage: h=10; c=0.4; p=0.1;
sage: G = Graphics()
sage: for x in srange(1,h+1):
... l = [[0,x*sqrt(3)],[-x/2,-x*sqrt(3)/2],[x/2,-x*sqrt(3)/2],[0,x*sqrt(3)]]
... G+=line(l,rgbcolor=hue(c + p*(x/h)))
sage: G.show(figsize=[5,5])
If you have any Graphics object G1, you can always add any other amount of Graphics objects G2,G3,... to form a new Graphics object: G4 = G1 + G2 + G3.
The xmin, xmax, ymin, and ymax properties of the graphics objects are expanded to include all objects in both scenes. If the aspect ratio property of either or both objects are set, then the larger aspect ratio is chosen.
EXAMPLES:
sage: g1 = plot(abs(sqrt(x^3-1)), (x,1,5), frame=True)
sage: g2 = plot(-abs(sqrt(x^3-1)), (x,1,5), rgbcolor=(1,0,0))
sage: g1 + g2 # displays the plot
TESTS:
sage: (g1 + g2)._extra_kwds # extra keywords to show are propagated
{'frame': True}
If G is of type Graphics, then del(G[i]) removes the ith distinct graphic primitive making up that object.
EXAMPLES:
sage: G = circle((1,1),1) + circle((1,2),1) + circle((1,2),5); print G
Graphics object consisting of 3 graphics primitives
sage: len(G)
3
sage: del(G[2])
sage: print G
Graphics object consisting of 2 graphics primitives
sage: len(G)
2
Returns the ith graphics primitive object:
EXAMPLE:
sage: G = circle((1,1),2) + circle((2,2),5); print G
Graphics object consisting of 2 graphics primitives
sage: G[1]
Circle defined by (2.0,2.0) with r=5.0
Create a new empty Graphics objects with all the defaults.
EXAMPLES:
sage: G = Graphics()
If G is of type Graphics, then len(G) gives the number of distinct graphics primitives making up that object.
EXAMPLES:
sage: G = circle((1,1),1) + circle((1,2),1) + circle((1,2),5); print G
Graphics object consisting of 3 graphics primitives
sage: len(G)
3
Compute and return other + this graphics object.
This only works when other is a Python int equal to 0. In all other cases a TypeError is raised. The main reason for this function is to make summing a list of graphics objects easier.
EXAMPLES:
sage: S = circle((0,0), 2)
sage: print int(0) + S
Graphics object consisting of 1 graphics primitive
sage: print S + int(0)
Graphics object consisting of 1 graphics primitive
The following would fail were it not for this function:
sage: v = [circle((0,0), 2), circle((2,3), 1)]
sage: print sum(v)
Graphics object consisting of 2 graphics primitives
You can replace a GraphicPrimitive (point, line, circle, etc...) in a Graphics object G with any other GraphicPrimitive
EXAMPLES:
sage: G = circle((1,1),1) + circle((1,2),1) + circle((1,2),5); print G
Graphics object consisting of 3 graphics primitives
sage: p = polygon([[1,3],[2,-2],[1,1],[1,3]]); print p
Graphics object consisting of 1 graphics primitive
sage: G[1] = p[0]
sage: G # show the plot
Return string representation of this plot.
EXAMPLES:
sage: S = circle((0,0), 2); S.__str__()
'Graphics object consisting of 1 graphics primitive'
sage: print S
Graphics object consisting of 1 graphics primitive
Warning
__str__ is not called when printing lists of graphics objects, which can be confusing, since they will all pop up. One workaround is to call show_default:
For example, below when we do print v two plots are displayed:
sage: v = [circle((0,0), 2), circle((2,3), 1)]
sage: print v
[, ]
However, if we call show_default then we see the text representations of the graphics:
sage: show_default(False)
sage: print v
[Graphics object consisting of 1 graphics primitive, Graphics object consisting of 1 graphics primitive]
sage: v
[Graphics object consisting of 1 graphics primitive,
Graphics object consisting of 1 graphics primitive]
sage: show_default(True)
Extract keywords relevant to show() from the provided dictionary.
EXAMPLES:
sage: kwds = {'f': lambda x: x, 'xmin': 0, 'figsize': [1,1], 'plot_points': (40, 40)}
sage: G_kwds = Graphics._extract_kwds_for_show(kwds, ignore='xmin')
sage: kwds # Note how this action modifies the passed dictionary
{'xmin': 0, 'plot_points': (40, 40), 'f': <function <lambda> at ...>}
sage: G_kwds
{'figsize': [1, 1]}
This method is intended to be used with _set_extra_kwds(). Here is an idiom to ensure the correct keywords will get passed on to show():
sage: options = {} # Usually this will come from an argument
sage: g = Graphics()
sage: g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
Returns the underlying dictionary used to store the user’s custom ranges for the axes on this object.
EXAMPLES:
sage: L = line([(1,2), (3,-4), (2, 5), (1,2)])
sage: L._get_axes_range_dict()
{}
sage: L.set_axes_range(xmin=-1)
sage: L._get_axes_range_dict()
{'xmin': -1.0}
Show this graphics objects.
If the show_default function has been called with True (the default), then you’ll see this graphics object displayed. Otherwise you’ll see a text representation of it.
EXAMPLES: We create a plot and call _repr_ on it, which causes it to be displayed as a plot:
sage: P = plot(cos, (-1,1))
sage: P._repr_()
''
Just doing this also displays the plot:
sage: P
Note that printing P with the print statement does not display the plot:
sage: print P
Graphics object consisting of 1 graphics primitive
Now we turn off showing plots by default:
sage: show_default(False)
Now we just get a string. To show P you would have to do show(P).
sage: P._repr_()
'Graphics object consisting of 1 graphics primitive'
sage: P
Graphics object consisting of 1 graphics primitive
Finally, we turn show_default back on:
sage: show_default(True)
Set a dictionary of keywords that will get passed on to show().
TESTS:
sage: g = Graphics()
sage: g._extra_kwds
{}
sage: g._set_extra_kwds({'figsize': [10,10]})
sage: g._extra_kwds
{'figsize': [10, 10]}
sage: g.show() # Now the (blank) plot will be extra large
Get the current aspect ratio.
OUTPUT: either None if the aspect ratio hasn’t been set or a positive float
EXAMPLES:
sage: P = circle((1,1), 1)
sage: P.aspect_ratio() is None
True
sage: P.set_aspect_ratio(2)
sage: P.aspect_ratio()
2.0
Set whether or not the and
axes are shown
by default.
INPUT:
If called with no input, return the current axes setting.
EXAMPLES:
sage: L = line([(1,2), (3,-4), (2, 5), (1,2)])
By default the axes are displayed.
sage: L.axes()
True
But we turn them off, and verify that they are off
sage: L.axes(False)
sage: L.axes()
False
Displaying L now shows a triangle but no axes.
sage: L
Set the axes color.
If called with no input, return the current axes_color setting.
INPUT:
EXAMPLES: We create a line, which has like everything a default axes color of black.
sage: L = line([(1,2), (3,-4), (2, 5), (1,2)])
sage: L.axes_color()
(0, 0, 0)
We change the axes color to red and verify the change.
sage: L.axes_color((1,0,0))
sage: L.axes_color()
(1.0, 0.0, 0.0)
When we display the plot, we’ll see a blue triangle and bright red axes.
sage: L
Set the color of the axes labels.
The axes labels are placed at the edge of the x and y axes, and are not on by default (use the axes_labels command to set them; see the example below). This function just changes their color.
INPUT:
If called with no input, return the current axes_label_color setting.
EXAMPLES: We create a plot, which by default has axes label color black.
sage: p = plot(sin, (-1,1))
sage: p.axes_label_color()
(0, 0, 0)
We change the labels to be red, and confirm this:
sage: p.axes_label_color((1,0,0))
sage: p.axes_label_color()
(1.0, 0.0, 0.0)
We set labels, since otherwise we won’t see anything.
sage: p.axes_labels(['$x$ axis', '$y$ axis'])
In the plot below, notice that the labels are red:
sage: p
Set the axes labels.
INPUT:
OUTPUT: a 2-tuple of strings
If l is None, returns the current axes_labels, which is itself by default None. The default labels are both empty.
EXAMPLES: We create a plot and put x and y axes labels on it.
sage: p = plot(sin(x), (x, 0, 10))
sage: p.axes_labels(['x','y'])
sage: p.axes_labels()
('x', 'y')
Now when you plot p, you see x and y axes labels:
sage: p
Set the ranges of the and
axes.
INPUT:
EXAMPLES:
sage: L = line([(1,2), (3,-4), (2, 5), (1,2)])
sage: L.set_axes_range(-1, 20, 0, 2)
sage: d = L.get_axes_range()
sage: d['xmin'], d['xmax'], d['ymin'], d['ymax']
(-1.0, 20.0, 0.0, 2.0)
Set the axes width. Use this to draw a plot with really fat or really thin axes.
INPUT:
If called with no input, return the current axes_width setting.
EXAMPLE: We create a plot, see the default axes width (with funny Python float rounding), then reset the width to 10 (very fat).
sage: p = plot(cos, (-3,3))
sage: p.axes_width()
0.80000000000000004
sage: p.axes_width(10)
sage: p.axes_width()
10.0
Finally we plot the result, which is a graph with very fat axes.
sage: p
Set the font size of axes labels and tick marks.
INPUT:
If called with no input, return the current fontsize.
EXAMPLES:
sage: L = line([(1,2), (3,-4), (2, 5), (1,2)])
sage: L.fontsize()
10
sage: L.fontsize(20)
sage: L.fontsize()
20
All the numbers on the axes will be very large in this plot:
sage: L
Returns a dictionary of the range of the axes for this graphics object. This is fall back to the ranges in get_minmax_data() for any value which the user has not explicitly set.
Warning
Changing the dictionary returned by this function does not change the axes range for this object. To do that, use the set_axes_range() method.
EXAMPLES:
sage: L = line([(1,2), (3,-4), (2, 5), (1,2)])
sage: list(sorted(L.get_axes_range().items()))
[('xmax', 3.0), ('xmin', 1.0), ('ymax', 5.0), ('ymin', -4.0)]
sage: L.set_axes_range(xmin=-1)
sage: list(sorted(L.get_axes_range().items()))
[('xmax', 3.0), ('xmin', -1.0), ('ymax', 5.0), ('ymin', -4.0)]
Return a dictionary whose keys give the xmin, xmax, ymin, and ymax data for this graphic.
Warning
The returned dictionary is mutable, but changing it does not change the xmin/xmax/ymin/ymax data. The minmax data is a function of the primitives which make up this Graphics object. To change the range of the axes, call methods xmin(), xmax(), ymin(), ymax(), or set_axes_range().
EXAMPLES:
sage: g = line([(-1,1), (3,2)])
sage: list(sorted(g.get_minmax_data().items()))
[('xmax', 3.0), ('xmin', -1.0), ('ymax', 2.0), ('ymin', 1.0)]
Note that changing ymax doesn’t change the output of get_minmax_data:
sage: g.ymax(10)
sage: list(sorted(g.get_minmax_data().items()))
[('xmax', 3.0), ('xmin', -1.0), ('ymax', 2.0), ('ymin', 1.0)]
Draw a 2d plot this graphics object, which just returns this object since this is already a 2d graphics object.
EXAMPLES:
sage: S = circle((0,0), 2)
sage: S.plot() is S
True
Returns an embedding of this 2D plot into the xy-plane of 3D space, as a 3D plot object. An optional parameter z can be given to specify the z-coordinate.
EXAMPLES:
sage: sum([plot(z*sin(x), 0, 10).plot3d(z) for z in range(6)]) #long
Save the graphics to an image file of type: PNG, PS, EPS, SVG, SOBJ, depending on the file extension you give the filename. Extension types can be: .png, .ps, .eps, .svg, and .sobj (for a Sage object you can load later).
EXAMPLES:
sage: c = circle((1,1),1,rgbcolor=(1,0,0))
sage: c.show(xmin=-1,xmax=3,ymin=-1,ymax=3)
To correct the aspect ratio of certain graphics, it is necessary to show with a ‘figsize‘ of square dimensions.
sage: c.show(figsize=[5,5],xmin=-1,xmax=3,ymin=-1,ymax=3)
sage: point((-1,1),pointsize=30, rgbcolor=(1,0,0))
Set the aspect ratio.
INPUT:
EXAMPLES: We create a plot of a circle, and it doesn’t look quite round:
sage: P = circle((1,1), 1); P
So we set the aspect ratio and now it is round:
sage: P.set_aspect_ratio(1)
sage: P
Note that the aspect ratio is inherited upon addition (which takes the max of aspect ratios of objects whose aspect ratio has been set):
sage: P + circle((0,0), 0.5) # still square
In the following example, both plots produce a circle that looks twice as wide as tall:
sage: Q = circle((0,0), 0.5); Q.set_aspect_ratio(2)
sage: P + Q
sage: Q + P
Set the ranges of the and
axes.
INPUT:
EXAMPLES:
sage: L = line([(1,2), (3,-4), (2, 5), (1,2)])
sage: L.set_axes_range(-1, 20, 0, 2)
sage: d = L.get_axes_range()
sage: d['xmin'], d['xmax'], d['ymin'], d['ymax']
(-1.0, 20.0, 0.0, 2.0)
Show this graphics image with the default image viewer.
OPTIONAL INPUT:
filename - (default: None) string
dpi - dots per inch
figsize - [width, height]
aspect_ratio - the perceived width divided by the perceived height. If the aspect ratio is set to 1, circles will look round. If it is set to 2 they will look twice as wide as they are tall. This is the aspect_ratio of the image, not of the frame that contains it. If you want to set the aspect ratio of the frame, use figsize.
axes - (default: True)
axes_labels - (default: None) list (or tuple) of two strings; the first is used as the label for the horizontal axis, and the second for the vertical axis.
fontsize - (default: current setting – 10) positive integer; used for axes labels; if you make this very large, you may have to increase figsize to see all labels.
frame - (default: False) draw a frame around the image
gridlines - (default: None) can be any of the following:
gridlinesstyle, hgridlinesstyle, vgridlinesstyle - (default: None) a dictionary of MATPLOTLIB options for the rendering of the grid lines, the horizontal grid lines or the vertical grid lines, respectively.
to the produced file is returned.
EXAMPLES:
sage: c = circle((1,1), 1, rgbcolor=(1,0,0))
sage: c.show(xmin=-1, xmax=3, ymin=-1, ymax=3)
To correct the aspect ratio of certain graphics, it is necessary to show with a ‘figsize‘ of square dimensions.
sage: c.show(figsize=[5,5], xmin=-1, xmax=3, ymin=-1, ymax=3)
You can turn off the drawing of the axes:
sage: show(plot(sin,-4,4), axes=False)
You can also label the axes:
sage: show(plot(sin,-4,4), axes_labels=('x','y'))
You can turn on the drawing of a frame around the plots:
sage: show(plot(sin,-4,4), frame=True)
Add grid lines at the major ticks of the axes.
sage: c = circle((0,0), 1)
sage: c.show(gridlines=True)
sage: c.show(gridlines="automatic")
sage: c.show(gridlines="major")
Add grid lines at the major and minor ticks of the axes.
sage: u,v = var('u v')
sage: f = exp(-(u^2+v^2))
sage: p = plot_vector_field(f.gradient(), (u,-2,2), (v,-2,2))
sage: p.show(gridlines="minor")
Add only horizontal or vertical grid lines.
sage: p = plot(sin,-10,20)
sage: p.show(gridlines=[None, "automatic"])
sage: p.show(gridlines=["minor", False])
Add grid lines at specific positions (using lists/tuples).
sage: x, y = var('x, y')
sage: p = implicit_plot((y^2-x^2)*(x-1)*(2*x-3)-4*(x^2+y^2-2*x)^2, ... (x,-2,2), (y,-2,2), plot_points=1000)
sage: p.show(gridlines=[[1,0],[-1,0,1]])
Add grid lines at specific positions (using iterators).
sage: def maple_leaf(t):
... return (100/(100+(t-pi/2)^8))*(2-sin(7*t)-cos(30*t)/2)
sage: p = polar_plot(maple_leaf, -pi/4, 3*pi/2, rgbcolor="red",plot_points=1000) #long
sage: p.show(gridlines=( [-3,-2.75,..,3], xrange(-1,5,2) )) #long
Add grid lines at specific positions (using functions).
sage: y = x^5 + 4*x^4 - 10*x^3 - 40*x^2 + 9*x + 36
sage: p = plot(y, -4.1, 1.1)
sage: xlines = lambda a,b: [z for z,m in y.roots()]
sage: p.show(gridlines=[xlines, [0]], frame=True, axes=False)
Change the style of all the grid lines.
sage: b = bar_chart([-3,5,-6,11], rgbcolor=(1,0,0))
sage: b.show(gridlines=([-1,-0.5,..,4],True), ... gridlinesstyle=dict(color="blue", linestyle=":"))
Change the style of the horizontal or vertical grid lines separately.
sage: p = polar_plot(2 + 2*cos(x), 0, 2*pi, rgbcolor=hue(0.3))
sage: p.show(gridlines=True, ... hgridlinesstyle=dict(color="orange", linewidth=1.0), ... vgridlinesstyle=dict(color="blue", linestyle=":"))
Change the style of each grid line individually.
sage: x, y = var('x, y')
sage: p = implicit_plot((y^2-x^2)*(x-1)*(2*x-3)-4*(x^2+y^2-2*x)^2, ... (x,-2,2), (y,-2,2), plot_points=1000)
sage: p.show(gridlines=(
... [
... (1,{"color":"red","linestyle":":"}),
... (0,{"color":"blue","linestyle":"--"})
... ],
... [
... (-1,{"rgbcolor":"red","linestyle":":"}),
... (0,{"color":"blue","linestyle":"--"}),
... (1,{"rgbcolor":"red","linestyle":":"}),
... ]
... ),
... gridlinesstyle=dict(marker='x',rgbcolor="black"))
Grid lines can be added to contour plots.
sage: f = sin(x^2 + y^2)*cos(x)*sin(y)
sage: c = contour_plot(f, (x, -4, 4), (y, -4, 4), plot_points=100)
sage: c.show(gridlines=True, gridlinesstyle={'linestyle':':','linewidth':1, 'rgbcolor':'red'})
Grid lines can be added to matrix plots.
sage: M = MatrixSpace(QQ,10).random_element()
sage: matrix_plot(M).show(gridlines=True)
Set the color of the axes tick labels.
INPUT:
If called with no input, return the current tick_label_color setting.
EXAMPLES:
sage: p = plot(cos, (-3,3))
sage: p.tick_label_color()
(0, 0, 0)
sage: p.tick_label_color((1,0,0))
sage: p.tick_label_color()
(1.0, 0.0, 0.0)
sage: p
EXAMPLES:
sage: g = line([(-1,1), (3,2)])
sage: g.xmax()
3.0
sage: g.xmax(10)
sage: g.xmax()
10.0
EXAMPLES:
sage: g = line([(-1,1), (3,2)])
sage: g.xmin()
-1.0
sage: g.xmin(-3)
sage: g.xmin()
-3.0
EXAMPLES:
sage: g = line([(-1,1), (3,2)])
sage: g.ymax()
2.0
sage: g.ymax(10)
sage: g.ymax()
10.0
EXAMPLES:
sage: g = line([(-1,1), (3,2)])
sage: g.ymin()
1.0
sage: g.ymin(-3)
sage: g.ymin()
-3.0
GraphicsArray takes a ( x
) list of lists of
graphics objects and plots them all on one canvas.
Show this graphics array using the default viewer.
OPTIONAL INPUT:
EXAMPLES: This draws a graphics array with four trig plots and no axes in any of the plots.
sage: G = graphics_array([[plot(sin), plot(cos)], [plot(tan), plot(sec)]])
sage: G.show(axes=False)
The adaptive refinement algorithm for plotting a function f. See the docstring for plot for a description of the algorithm.
INPUT:
OUTPUT:
TESTS:
sage: from sage.plot.plot import adaptive_refinement
sage: adaptive_refinement(sin, (0,0), (pi,0), adaptive_tolerance=0.01, adaptive_recursion=0)
[]
sage: adaptive_refinement(sin, (0,0), (pi,0), adaptive_tolerance=0.01)
[(0.125000000000000*pi, 0.38268343236508978), (0.187500000000000*pi, 0.55557023301960218), (0.250000000000000*pi, 0.70710678118654746), (0.312500000000000*pi, 0.83146961230254524), (0.375000000000000*pi, 0.92387953251128674), (0.437500000000000*pi, 0.98078528040323043), (0.500000000000000*pi, 1.0), (0.562500000000000*pi, 0.98078528040323043), (0.625000000000000*pi, 0.92387953251128674), (0.687500000000000*pi, 0.83146961230254546), (0.750000000000000*pi, 0.70710678118654757), (0.812500000000000*pi, 0.55557023301960218), (0.875000000000000*pi, 0.38268343236508989)]
This shows that lowering adaptive_tolerance and raising adaptive_recursion both increase the number of subdivision points, though which one creates more points is heavily dependent upon the function being plotted.
sage: x = var('x')
sage: f(x) = sin(1/x)
sage: n1 = len(adaptive_refinement(f, (0,0), (pi,0), adaptive_tolerance=0.01)); n1
15
sage: n2 = len(adaptive_refinement(f, (0,0), (pi,0), adaptive_recursion=10, adaptive_tolerance=0.01)); n2
79
sage: n3 = len(adaptive_refinement(f, (0,0), (pi,0), adaptive_tolerance=0.001)); n3
26
Adjust the figsize in case the user also specifies an aspect ratio.
INPUTS: figsize - a sequence of two positive real numbers aspect_ratio - a positive real number xmin, xmax, ymin, ymax - real numbers
EXAMPLES: This function is used mainly internally by plotting code so we explicitly import it:
sage: from sage.plot.plot import adjust_figsize_for_aspect_ratio
This returns (5,5), since the requested aspect ratio is 1 and the x and y ranges are the same, so that’s the right size rendered image to produce a 1:1 ratio internally. 5 is used instead of 3 since the image size is always adjusted to the larger of the figsize dimensions.
sage: adjust_figsize_for_aspect_ratio([3,5], 1, 0, 2, 0, 2)
(5, 5)
Here we give a scalar figsize, which is automatically converted to the figsize (figsize, figsize/golden_ratio).
sage: adjust_figsize_for_aspect_ratio(3, 1, 0, 2, 0, 2)
(3, 3)
Here we omit the aspect ratio so the figsize is just returned.
sage: adjust_figsize_for_aspect_ratio([5,6], None, 0, 2, 0, 2)
[5, 6]
Here we have an aspect ratio of 2, and since the x and y ranges are the same the returned figsize is twice as wide as tall:
sage: adjust_figsize_for_aspect_ratio([3,5], 2, 0, 2, 0, 2)
(5, 5/2)
Here the x range is rather large, so to get an aspect ratio where circles look twice as wide as they are tall, we have to shrink the y size of the image.
sage: adjust_figsize_for_aspect_ratio([3,5], 2, 0, 10, 0, 2)
(5, 1/2)
Calculate plot points for a function f in the interval xrange. The adaptive refinement algorithm is also automatically invoked with a relative adaptive tolerance of adaptive_tolerance; see below.
INPUT:
OUTPUT:
TESTS:
sage: from sage.plot.plot import generate_plot_points
sage: generate_plot_points(sin, (0, pi), plot_points=2, adaptive_recursion=0)
[(0.0, 0.0), (3.1415926535897931, 1.2246...e-16)]
sage: generate_plot_points(sin(x).function(x), (-pi, pi), randomize=False)
[(-3.1415926535897931, -1.2246...e-16), (-2.748893571891069,
-0.3826834323650898...), (-2.3561944901923448, -0.707106781186547...),
(-2.1598449493429825, -0.831469612302545...), (-1.9634954084936207,
-0.92387953251128674), (-1.7671458676442586, -0.98078528040323043),
(-1.5707963267948966, -1.0), (-1.3744467859455345,
-0.98078528040323043), (-1.1780972450961724, -0.92387953251128674),
(-0.98174770424681035, -0.831469612302545...), (-0.78539816339744828,
-0.707106781186547...), (-0.39269908169872414, -0.38268343236508978),
(0.0, 0.0), (0.39269908169872414, 0.38268343236508978),
(0.78539816339744828, 0.707106781186547...), (0.98174770424681035,
0.831469612302545...), (1.1780972450961724, 0.92387953251128674),
(1.3744467859455345, 0.98078528040323043), (1.5707963267948966, 1.0),
(1.7671458676442586, 0.98078528040323043), (1.9634954084936207,
0.92387953251128674), (2.1598449493429825, 0.831469612302545...),
(2.3561944901923448, 0.707106781186547...), (2.748893571891069,
0.3826834323650898...), (3.1415926535897931, 1.2246...e-16)]
This shows that lowering adaptive_tolerance and raising adaptive_recursion both increase the number of subdivision points. (Note that which creates more points is heavily dependent on the particular function plotted.)
sage: x = var('x')
sage: f(x) = sin(1/x)
sage: [len(generate_plot_points(f, (-pi, pi), plot_points=16, adaptive_tolerance=i, randomize=False)) for i in [0.01, 0.001, 0.0001]]
[97, 161, 275]
sage: [len(generate_plot_points(f, (-pi, pi), plot_points=16, adaptive_recursion=i, randomize=False)) for i in [5, 10, 15]]
[97, 499, 2681]
graphics_array take a list of lists (or tuples) of graphics objects and plots them all on one canvas (single plot).
INPUT:
EXAMPLE: Make some plots of functions:
sage: f(x) = sin(x)
sage: g(x) = sin(2*x)
sage: h(x) = sin(4*x)
sage: p1 = plot(f,-2*pi,2*pi,rgbcolor=hue(0.5))
sage: p2 = plot(g,-2*pi,2*pi,rgbcolor=hue(0.9))
sage: p3 = parametric_plot((f,g),0,2*pi,rgbcolor=hue(0.6))
sage: p4 = parametric_plot((f,h),0,2*pi,rgbcolor=hue(1.0))
Now make a graphics array out of the plots; then you can type either: ga.show() or ga.save().
sage: graphics_array(((p1,p2),(p3,p4)))
Here we give only one row:
sage: p1 = plot(sin,-4,4)
sage: p2 = plot(cos,-4,4)
sage: g = graphics_array([p1, p2]); print g
Graphics Array of size 1 x 2
sage: g.show()
Return True if is a Graphics object.
EXAMPLES:
sage: from sage.plot.plot import is_Graphics
sage: is_Graphics(1)
False
sage: is_Graphics(disk((0.0, 0.0), 1, (0, pi/2)))
True
list_plot takes a single list of data, in which case it forms
a list of tuples where
goes from 0 to
and
is the
data value, and puts points
at those tuple values.
list_plot also takes a list of tuples where
is the
data representing the
-value, and
is the
-value. If plotjoined=True , then a line spanning
all the data is drawn instead.
EXAMPLES:
sage: list_plot([i^2 for i in range(5)])
Here are a bunch of random red points:
sage: r = [(random(),random()) for _ in range(20)]
sage: list_plot(r,rgbcolor=(1,0,0))
This gives all the random points joined in a purple line:
sage: list_plot(r, plotjoined=True, rgbcolor=(1,0,1))
If you have separate lists of values and
values which you
want to plot against each other, use the zip command to make a
single list whose entries are pairs of
values, and feed
the result into list_plot:
sage: x_coords = [cos(t)^3 for t in srange(0, 2*pi, 0.02)]
sage: y_coords = [sin(t)^3 for t in srange(0, 2*pi, 0.02)]
sage: list_plot(zip(x_coords, y_coords))
If instead you try to pass the two lists as separate arguments, you will get an error message:
sage: list_plot(x_coords, y_coords)
...
TypeError: The second argument 'plotjoined' should be boolean (True or False). If you meant to plot two lists 'x' and 'y' against each other, use 'list_plot(zip(x,y))'.
TESTS: We check to see that the x/y min/max data are set correctly.
sage: d = list_plot([(100,100), (120, 120)]).get_minmax_data()
sage: d['xmin']
100.0
sage: d['ymin']
100.0
Returns the minimums and maximums of xdata and ydata.
If dict is False, then minmax_data returns the tuple (xmin, xmax, ymin, ymax); otherwise, it returns a dictionary whose keys are ‘xmin’, ‘xmax’, ‘ymin’, and ‘ymax’ and whose values are the corresponding values.
EXAMPLES:
sage: from sage.plot.plot import minmax_data
sage: minmax_data([], [])
(-1, 1, -1, 1)
sage: minmax_data([-1, 2], [4, -3])
(-1, 2, -3, 4)
sage: d = minmax_data([-1, 2], [4, -3], dict=True)
sage: list(sorted(d.items()))
[('xmax', 2), ('xmin', -1), ('ymax', 4), ('ymin', -3)]
parametric_plot takes two or three functions as a
list or a tuple and makes a plot with the first function giving the
coordinates, the second function giving the
coordinates, and the third function (if present) giving the
coordinates.
In the 2d case, parametric_plot is equivalent to the plot command with the option parametric=True. In the 3d case, parametric_plot is equivalent to parametric_plot3d. See each of these functions for more help and examples.
INPUT:
EXAMPLES: We draw some 2d parametric plots:
sage: t = var('t')
sage: parametric_plot( (sin(t), sin(2*t)), (t, 0, 2*pi), rgbcolor=hue(0.6) )
sage: parametric_plot((1, t), (t, 0, 4))
Note that in parametric_plot, there is only fill or no fill.
sage: parametric_plot((t, t^2), (t, -4, 4), fill = True)
A filled Hypotrochoid:
sage: parametric_plot([cos(x) + 2 * cos(x/4), sin(x) - 2 * sin(x/4)], 0, 8*pi, fill = True)
sage: parametric_plot( (5*cos(x), 5*sin(x), x), (x,-12, 12), plot_points=150, color="red")
sage: y=var('y')
sage: parametric_plot( (5*cos(x), x*y, cos(x*y)), (x, -4,4), (y,-4,4))
TESTS:
sage: parametric_plot((x, t^2), (x, -4, 4))
...
ValueError: the number of functions and the number of free variables is not a possible combination for 2d or 3d parametric plots
sage: parametric_plot((1, x+t), (x, -4, 4))
...
ValueError: the number of functions and the number of free variables is not a possible combination for 2d or 3d parametric plots
sage: parametric_plot((-t, x+t), (x, -4, 4))
...
ValueError: the number of functions and the number of free variables is not a possible combination for 2d or 3d parametric plots
sage: parametric_plot((1, x+t, y), (x, -4, 4), (t, -4, 4))
...
ValueError: the number of functions and the number of free variables is not a possible combination for 2d or 3d parametric plots
Use plot by writing
plot(X, ...)
where is a Sage object (or list of Sage objects) that
either is callable and returns numbers that can be coerced to
floats, or has a plot method that returns a
GraphicPrimitive object.
There are many other specialized 2D plot commands available in Sage, such as plot_slope_field, as well as various graphics primitives like Arrow; type sage.plot.plot? for a current list.
Type plot.options for a dictionary of the default options for plots. You can change this to change the defaults for all future plots. Use plot.reset() to reset to the default options.
PLOT OPTIONS:
APPEARANCE OPTIONS:
The following options affect the appearance of
the line through the points on the graph of (these are
the same as for the line function):
INPUT:
Any MATPLOTLIB line option may also be passed in. E.g.,
FILLING OPTIONS: INPUT:
Note that this function does NOT simply sample equally spaced
points between xmin and xmax. Instead it computes equally spaced
points and add small perturbations to them. This reduces the
possibility of, e.g., sampling sin only at multiples of
, which would yield a very misleading graph.
EXAMPLES: We plot the sin function:
sage: P = plot(sin, (0,10)); print P
Graphics object consisting of 1 graphics primitive
sage: len(P) # number of graphics primitives
1
sage: len(P[0]) # how many points were computed (random)
225
sage: P # render
sage: P = plot(sin, (0,10), plot_points=10); print P
Graphics object consisting of 1 graphics primitive
sage: len(P[0]) # random output
32
sage: P # render
We plot with randomize=False, which makes the initial sample points evenly spaced (hence always the same). Adaptive plotting might insert other points, however, unless adaptive_recursion=0.
sage: p=plot(1, (x,0,3), plot_points=4, randomize=False, adaptive_recursion=0)
sage: list(p[0])
[(0.0, 1.0), (1.0, 1.0), (2.0, 1.0), (3.0, 1.0)]
Some colored functions:
sage: plot(sin, 0, 10, rgbcolor='#ff00ff')
sage: plot(sin, 0, 10, rgbcolor='purple')
We plot several functions together by passing a list of functions as input:
sage: plot([sin(n*x) for n in [1..4]], (0, pi))
The function wiggles wildly near
.
Sage adapts to this and plots extra points near the origin.
sage: plot(sin(1/x), (x, -1, 1))
Note that the independent variable may be omitted if there is no ambiguity:
sage: plot(sin(1/x), (-1, 1))
The algorithm used to insert extra points is actually pretty simple. On the picture drawn by the lines below:
sage: p = plot(x^2, (-0.5, 1.4)) + line([(0,0), (1,1)], rgbcolor='green')
sage: p += line([(0.5, 0.5), (0.5, 0.5^2)], rgbcolor='purple')
sage: p += point(((0, 0), (0.5, 0.5), (0.5, 0.5^2), (1, 1)), rgbcolor='red', pointsize=20)
sage: p += text('A', (-0.05, 0.1), rgbcolor='red')
sage: p += text('B', (1.01, 1.1), rgbcolor='red')
sage: p += text('C', (0.48, 0.57), rgbcolor='red')
sage: p += text('D', (0.53, 0.18), rgbcolor='red')
sage: p.show(axes=False, xmin=-0.5, xmax=1.4, ymin=0, ymax=2)
You have the function (in blue) and its approximation (in green) passing through the points A and B. The algorithm finds the midpoint C of AB and computes the distance between C and D. If that distance exceeds the adaptive_tolerance threshold (relative to the size of the initial plot subintervals), the point D is added to the curve. If D is added to the curve, then the algorithm is applied recursively to the points A and D, and D and B. It is repeated adaptive_recursion times (5, by default).
The actual sample points are slightly randomized, so the above plots may look slightly different each time you draw them.
We draw the graph of an elliptic curve as the union of graphs of 2 functions.
sage: def h1(x): return abs(sqrt(x^3 - 1))
sage: def h2(x): return -abs(sqrt(x^3 - 1))
sage: P = plot([h1, h2], 1,4)
sage: P # show the result
We can also directly plot the elliptic curve:
sage: E = EllipticCurve([0,-1])
sage: plot(E, (1, 4), rgbcolor=hue(0.6))
We can change the line style to one of '--' (two hyphens, yielding dashed), '-.' (dash dot), '-' (solid), 'steps', ':' (dotted):
sage: plot(sin(x), 0, 10, linestyle='-.')
Sage currently ignores points that cannot be evaluated
sage: set_verbose(-1)
sage: plot(-x*log(x), (x,0,1)) # this works fine since the failed endpoint is just skipped.
sage: set_verbose(0)
This prints out a warning and plots where it can (we turn off the warning by setting the verbose mode temporarily to -1.)
sage: set_verbose(-1)
sage: plot(x^(1/3), (x,-1,1))
sage: set_verbose(0)
To plot the negative real cube root, use something like the following:
sage: plot(lambda x : RR(x).nth_root(3), (x,-1, 1))
We can detect the poles of a function:
sage: plot(gamma, (-3, 4), detect_poles = True).show(ymin = -5, ymax = 5)
We draw the Gamma-Function with its poles highlighted:
sage: plot(gamma, (-3, 4), detect_poles = 'show').show(ymin = -5, ymax = 5)
The basic options for filling a plot:
sage: p1 = plot(sin(x), -pi, pi, fill = 'axis')
sage: p2 = plot(sin(x), -pi, pi, fill = 'min')
sage: p3 = plot(sin(x), -pi, pi, fill = 'max')
sage: p4 = plot(sin(x), -pi, pi, fill = 0.5)
sage: graphics_array([[p1, p2], [p3, p4]]).show(frame=True, axes=False)
sage: plot([sin(x), cos(2*x)*sin(4*x)], -pi, pi, fill = {0: 1}, fillcolor = 'red', fillalpha = 1)
A example about the growth of prime numbers:
sage: plot(1.13*log(x), 1, 100, fill = lambda x: nth_prime(x)/floor(x), fillcolor = 'red')
Fill the area between a function and its asymptote:
sage: f = (2*x^3+2*x-1)/((x-2)*(x+1))
sage: plot([f, 2*x+2], -7,7, fill = {0: [1]}, fillcolor='#ccc').show(ymin=-20, ymax=20)
Fill the area between a list of functions and the x-axis:
sage: def b(n): return lambda x: bessel_J(n, x)
sage: plot([b(n) for n in [1..5]], 0, 20, fill = 'axis')
Note that to fill between the ith and jth functions, you must use dictionary key-value pairs i:[j]; key-value pairs like i:j will fill between the ith function and the line y=j:
sage: def b(n): return lambda x: bessel_J(n, x) + 0.5*(n-1)
sage: plot([b(c) for c in [1..5]], 0, 40, fill = dict([(i, [i+1]) for i in [0..3]]))
sage: plot([b(c) for c in [1..5]], 0, 40, fill = dict([(i, i+1) for i in [0..3]]))
Extra options will get passed on to show(), as long as they are valid:
sage: plot(sin(x^2), (x, -3, 3), figsize=[8,2])
sage: plot(sin(x^2), (x, -3, 3)).show(figsize=[8,2]) # These are equivalent
TESTS:
We do not randomize the endpoints:
sage: p = plot(x, (x,-1,1))
sage: p[0].xdata[0] == -1
True
sage: p[0].xdata[-1] == 1
True
We check to make sure that the x/y min/max data get set correctly when there are multiple functions.
sage: d = plot([sin(x), cos(x)], 100, 120).get_minmax_data()
sage: d['xmin']
100.0
sage: d['xmax']
120.0
We check various combinations of tuples and functions, ending with tests that lambda functions work properly with explicit variable declaration, without a tuple.
sage: p = plot(lambda x: x,(x,-1,1))
sage: p = plot(lambda x: x,-1,1)
sage: p = plot(x,x,-1,1)
sage: p = plot(x,-1,1)
sage: p = plot(x^2,x,-1,1)
sage: p = plot(x^2,xmin=-1,xmax=2)
sage: p = plot(lambda x: x,x,-1,1)
sage: p = plot(lambda x: x^2,x,-1,1)
sage: p = plot(lambda x: 1/x,x,-1,1)
sage: f(x) = sin(x+3)-.1*x^3
sage: p = plot(lambda x: f(x),x,-1,1)
We check to handle cases where the function gets evaluated at a point which causes an ‘inf’ or ‘-inf’ result to be produced.
sage: p = plot(1/x, 0, 1)
sage: p = plot(-1/x, 0, 1)
Bad options now give better errors:
sage: P = plot(sin(1/x), (x,-1,3), foo=10)
...
RuntimeError: Error in line(): option 'foo' not valid.
polar_plot takes a single function or a list or tuple of functions and plots them with polar coordinates in the given domain.
This function is equivalent to the plot command with the option polar=True. For more help on options, see the documentation for plot.
INPUT:
EXAMPLES:
Here is a blue 8-leaved petal:
sage: polar_plot(sin(5*x)^2, (x, 0, 2*pi), color='blue')
A red figure-8:
sage: polar_plot(abs(sqrt(1 - sin(x)^2)), (x, 0, 2*pi), color='red')
A green limacon of Pascal:
sage: polar_plot(2 + 2*cos(x), (x, 0, 2*pi), rgbcolor=hue(0.3))
Several polar plots:
sage: polar_plot([2*sin(x), 2*cos(x)], (x, 0, 2*pi))
A filled spiral:
sage: polar_plot(sqrt, 0, 2 * pi, fill = True)
Fill the area between two functions:
sage: polar_plot(cos(4*x) + 1.5, 0, 2*pi, fill=0.5 * cos(4*x) + 2.5, fillcolor='orange').show(aspect_ratio=1)
Fill the area between several spirals:
sage: polar_plot([(1.2+k*0.2)*log(x) for k in range(6)], 1, 3 * pi, fill = {0: [1], 2: [3], 4: [5]})
INPUT:
OUTPUT:
EXAMPLES:
sage: x,y = var('x,y')
sage: sage.plot.plot.setup_for_eval_on_grid([x^2 + y^2], (x,0,5), (y,0,pi), 11)
([<sage.ext... object at ...>],
0.5,
0.31415926535897931,
(0.0, 5.0),
(0.0, 3.1415926535897931))
We always plot at least two points; one at the beginning and one at the end of the ranges.
sage: sage.plot.plot.setup_for_eval_on_grid([x^2+y^2], (x,0,1), (y,-1,1), 1)
([<sage.ext... object at ...>],
1.0,
2.0,
(0.0, 1.0),
(-1.0, 1.0))
Set the default for showing plots using any plot commands. If called with no arguments, returns the current default.
If this is True (the default) then any plot object when displayed will be displayed as an actual plot instead of text, i.e., the show command is not needed.
EXAMPLES: The default starts out as True:
sage: show_default()
True
We set it to False.
sage: show_default(False)
We see that it is False.
sage: show_default()
False
Now plot commands will not display their plots by default.
Turn back on default display.
sage: show_default(True)
Given a list or tuple or iterable v, coerce each element of v to a float and make a list out of the result.
EXAMPLES:
sage: from sage.plot.plot import to_float_list
sage: to_float_list([1,1/2,3])
[1.0, 0.5, 3.0]
INPUT:
OUTPUT:
EXAMPLES:
sage: from sage.plot.plot import var_and_list_of_values
sage: var_and_list_of_values((var('theta'), 2, 5), 5)
(theta, [2.0, 2.75, 3.5, 4.25, 5.0])
sage: var_and_list_of_values((2, 5), 5)
(None, [2.0, 2.75, 3.5, 4.25, 5.0])
sage: var_and_list_of_values((var('theta'), 2, 5), 2)
(theta, [2.0, 5.0])
sage: var_and_list_of_values((2, 5), 2)
(None, [2.0, 5.0])
Returns two lists (xdata, ydata), each coerced to a list of floats, which correspond to the x-coordinates and the y-coordinates of the points.
The points parameter can be a list of 2-tuples or some object that yields a list of one or two numbers.
This function can potentially be very slow for large point sets.