# Plotting Data with Sage

May 2011

## Sage Beginner's Guide

 Unlock the full potential of Sage for simplifying and automating mathematical computing

(For more resources related to this topic, see here.)

# Confusion alert: Sage plots and matplotlib

The 2D plotting capabilities of Sage are built upon a Python plotting package called matplotlib. The most widely used features of matplotlib are accessible through Sage functions. You can also import the matplotlib package into Sage, and use all of its features directly. This is very powerful, but it's also confusing, because there's more than one way to do the same thing. To further add to the confusion, matplotlib has two interfaces: the command-oriented Pyplot interface and an object-oriented interface. The examples in this chapter will attempt to clarify which interface is being used.

# Plotting in two dimensions

Two-dimensional plots are probably the most important tool for visually presenting information in math, science, and engineering. Sage has a wide variety of tools for making many types of 2D plots.

# Plotting symbolic expressions with Sage

We will start by exploring the plotting functions that are built in to Sage. They are generally less flexible than using matplotlib directly, but also tend to be easier to use.

# Time for action – plotting symbolic expressions

Let's plot some simple functions. Enter the following code:

p1 = plot(sin, (-2*pi, 2*pi), thickness=2.0, rgbcolor=(0.5, 1, 0),   legend_label='sin(x)')p2 = plot(cos, (-2*pi, 2*pi), thickness=3.0, color='purple',   alpha=0.5, legend_label='cos(x)')plt = p1 + p2plt.axes_labels(['x', 'f(x)'])show(plt)

If you run the code from the interactive shell, the plot will open in a separate window. If you run it from the notebook interface, the plot will appear below the input cell. In either case, the result should look like this:

## What just happened?

This example demonstrated the most basic type of plotting in Sage. The plot function requires the following arguments:

graphics_object = plot(callable symbolic expression, (independent_var,ind_var_min, ind_var_max))

The first argument is a callable symbolic expression, and the second argument is a tuple consisting of the independent variable, the lower limit of the domain, and the upper limit. If there is no ambiguity, you do not need to specify the independent variable. Sage automatically selects the right number of points to make a nice curve in the specified domain. The plot function returns a graphics object. To combine two graphics objects in the same image, use the + operator: plt = p1 + p2. Graphics objects have additional methods for modifying the final image. In this case, we used the axes_labels method to label the x and y axes. Finally, the show function was used to finish the calculation and display the image.

The plot function accepts optional arguments that can be used to customize the appearance and format of the plot. To see a list of all the options and their default values, type:

sage: plot.options{'fillalpha': 0.5, 'detect_poles': False, 'plot_points': 200,'thickness': 1, 'alpha': 1, 'adaptive_tolerance': 0.01, 'fillcolor':'automatic', 'adaptive_recursion': 5, 'exclude': None, 'legend_label':None, 'rgbcolor': (0, 0, 1), 'fill': False}

Here is a summary of the options for customizing the appearance of a plot:

 Keyword Description alpha Transparency of the line (0=opaque, 1=transparent) fill True to fill area below the line fillalpha Transparency of the filled-in area (0=opaque, 1=transparent) fillcolor Color of the filled-in area rgbcolor Color of the line

Sage uses an algorithm to determine the best number of points to use for the plot, and how to distribute them on the x axis. The algorithm uses recursion to add more points to resolve regions where the function changes rapidly. Here are the options that control how the plot is generated:

 Keyword Description adaptive_recursion Max depth of recursion when resolving areas of the plot where the function changes rapidly adaptive_tolerance Tolerance for stopping recursion detect_poles Detect points where function value approaches infinity (see next example) exclude A list or tuple of points to exclude from the plot plot_points Number of points to use in the plot

Specifying colors in Sage
There are several ways to specify a color in Sage. For basic colors, you can use a string containing the name of the color, such as red or blue. You can also use a tuple of three floating-point values between 0 and 1.0. The first value is the amount of red, the second is the amount of green, and the third is the amount of blue. For example, the tuple (0.5, 0.0, 0.5) represents a medium purple color.

Some functions "blow up" to plus or minus infinity at a certain point. A simplistic plotting algorithm will have trouble plotting these points, but Sage adapts.

# Time for action – plotting a function with a pole

Let's try to plot a simple function that takes on infinite values within the domain of the plot:

pole_plot = plot(1 / (x - 1), (0.8, 1.2), detect_poles='show',    marker='.')print("min y = {0} max y = {1}".format(pole_plot.ymax(),    pole_plot.ymin()))pole_plot.ymax(100.0)pole_plot.ymin(-100.0)# Use TeX to make nicer labelspole_plot.axes_labels([r'$x$', r'$1/(x-1)$'])pole_plot.show()

The output from this code is as follows:

## What just happened?

We did a few things differently compared to the previous example. We defined a callable symbolic expression right in the plot function. We also used the option detect_poles='show' to plot a dashed vertical line at the x value where the function returns infinite values. The option marker='.' tells Sage to use a small dot to mark the individual (x,y) values on the graph. In this case, the dots are so close together that they look like a fat line. We also used the methods ymin and ymax to get and set the minimum and maximum values of the vertical axis. When called without arguments, these methods return the current values. When given an argument, they set the minimum and maximum values of the vertical axis.

Finally, we labeled the axes with nicely typeset mathematical expressions. As in the previous example, we used the method axes_labels to set the labels on the x and y axes. However, we did two special things with the label strings:

r'$\frac{1}{(x-1)}$'

The letter r is placed in front of the string, which tells Python that this is a raw string. When processing a raw string, Python does not interpret backslash characters as commands (such as interpreting \n as a newline). Note that the first and last characters of the string are dollar signs, which tells Sage that the strings contain mark-up that needs to be processed before being displayed. The mark-up language is a subset of TeX, which is widely used for typesetting complicated mathematical expressions. Sage performs this processing with a built-in interpreter, so you don't need to have TeX installed to take advantage of typeset labels. It's a good idea to use raw strings to hold TeX markup because TeX uses a lot of backslashes. To learn about the typesetting language, see the matplotlib documentation at:

http://matplotlib.sourceforge.net/users/mathtext.html

# Time for action – plotting a parametric function

Some functions are defined in terms of a parameter. Sage can easily plot parametric functions:

var('t')pp = parametric_plot((cos(t), sin(t)), (t, 0, 2*pi),     fill=True, fillcolor='blue')pp.show(aspect_ratio=1, figsize=(3, 3), frame=True)

The output from this code is as follows:

## What just happened?

We used two parametric functions to plot a circle. This is a convenient place to demonstrate the fill option, which fills in the space between the function and the horizontal axis. The fillcolor option tells Sage which color to use for the fill, and the color can be specified in the usual ways. We also demonstrated some useful options for the show method (these options also work with the show function). The option aspect_ratio=1 forces the x and y axes to use the same scale. In other words, one unit on the x axis takes up the same number of pixels on the screen as one unit on the y axis. Try changing the aspect ratio to 0.5 and 2.0, and see how the circle looks. The option figsize=(x_size,y_size) specifies the aspect ratio and relative size of the figure. The units for the figure size are relative, and don't correspond to an absolute unit like inches or centimetres. The option frame=True places a frame with tick marks around the outside of the plot.

# Time for action – making a polar plot

Some functions are more easily described in terms of angle and radius. The angle is the independent variable, and the radius at that angle is the dependent variable. Polar plots are widely used in electrical engineering to describe the radiation pattern of an antenna. Some antennas are designed to transmit (or receive) electromagnetic radiation in a very narrow beam. The beam shape is known as the radiation pattern. One way to achieve a narrow beam is to use an array of simple dipole antennas, and carefully control the phase of the signal fed to each antenna. In the following example, we will consider seven short dipole antennas set in a straight line:

# A linear broadside array of short vertical dipoles# located along the z axis with 1/2 wavelength spacingvar('r, theta')N = 7normalized_element_pattern = sin(theta)array_factor = 1 / N * sin(N * pi / 2 * cos(theta)) \/ sin(pi / 2 * cos(theta))array_plot = polar_plot(abs(array_factor), (theta, 0, pi),     color='red', legend_label='Array')radiation_plot = polar_plot(abs(normalized_element_pattern     * array_factor), (theta, 0, pi), color='blue',     legend_label='Radiation')combined_plot = array_plot + radiation_plotcombined_plot.xmin(-0.25)combined_plot.xmax(0.25)combined_plot.set_legend_options(loc=(0.5, 0.3))show(combined_plot, figsize=(2, 5), aspect_ratio=1)

Execute the code. You should get a plot like this:

## What just happened?

We plotted a polar function, and used several of the plotting features that we've already discussed. There are two subtle points worth mentioning. The function array_factor is a function of two variables, N and theta. In this example, N is more like a parameter, while theta is the independent variable we want to use for plotting. We use the syntax (theta, 0, pi) in the plot function to indicate that theta is the independent variable. The second new aspect of this example is that we used the methods xmin and xmax to set the limits of the x axis for the graphics object called combined_plot. We also used the set_legend_options of the graphics object to adjust the position of the legend to avoid covering up important details of the plot.

# Time for action – plotting a vector field

Vector fields are used to represent force fields such as electromagnetic fields, and are used to visualize the solutions of differential equations. Sage has a special plotting function to visualize vector fields.

var('x, y')a = plot_vector_field((x, y), (x, -3, 3), (y, -3, 3), color='blue')b = plot_vector_field((y, -x), (x, -3, 3), (y, -3, 3), color='red')show(a + b, aspect_ratio=1, figsize=(4, 4))

You should get the following image:

## What just happened?

The plot_vector_field function uses the following syntax:

plot_vector_field((x_function,y_function), (x,x_min,x_max), (y,y_min,y_max))

The keyword argument color specifies the color of the vectors.

# Plotting data in Sage

So far, we've been making graphs of functions. We specify the function and the domain, and Sage automatically chooses the points to make a nice-looking curve. Sometimes, we need to plot discrete data points that represent experimental measurements or simulation results. The following functions are used for plotting defined sets of points.

# Time for action – making a scatter plot

Scatter plots are used in science and engineering to look for correlation between two variables. A cloud of points that is roughly circular indicates that the two variables are independent, while a more elliptical arrangement indicates that there may be a relationship between them. In the following example, the x and y coordinates are contrived to make a nice plot. In real life, the x and y coordinates would typically be read in from data files. Enter the following code:

def noisy_line(m, b, x):    return m * x + b + 0.5 * (random() - 0.5)slope = 1.0intercept = -0.5x_coords = [random() for t in range(50)]y_coords = [noisy_line(slope, intercept, x) for x in x_coords]sp = scatter_plot(zip(x_coords, y_coords))sp += line([(0.0, intercept), (1.0, slope+intercept)], color='red')sp.show()

The result should look similar to this plot. Note that your results won't match exactly, since the point positions are determined randomly.

## What just happened?

We created a list of randomized x coordinates using the built-in random function. This function returns a random number in the range 0 <= x < 1. We defined a function called noisy_line that we then used to create a list of randomized y coordinates with a linear relationship to the x coordinates. We now have a list of x coordinates and a list of y coordinates, but the scatter_plot function needs a list of (x,y) tuples. The zip function takes the two lists and combines them into a single list of tuples. The scatter_plot function returns a graphics object called sp. To add a line object to the plot, we use the following syntax:

sp += line([(x1, y1), (x2,y2)], color='red')

The += operator is a way to increment a variable; x+=1 is a shortcut for x = x + 1. Because the + operator also combines graphics objects, this syntax can be used to add a graphics object to an existing graphics object.

# Time for action – plotting a list

Sometimes, you need to plot a list of discrete data points. The following example might be found in an introductory digital signal processing (DSP) course. We will use lists to represent digital signals. We sample the analogue function cosine(t) at two different sampling rates, and plot the resulting digital signals.

# Use list_plot to visualize digital signals# Undersampling and oversampling a cosine signalsample_times_1 = srange(0, 6*pi, 4*pi/5)sample_times_2 = srange(0, 6*pi, pi/3)data1 = [cos(t) for t in sample_times_1]data2 = [cos(t) for t in sample_times_2]plot1 = list_plot(zip(sample_times_1, data1), color='blue')plot1.axes_range(0, 18, -1, 1)plot1 += text("Undersampled", (9, 1.1), color='blue', fontsize=12)plot2 = list_plot(zip(sample_times_2, data2), color='red')plot2.axes_range(0, 18, -1, 1)plot2 += text("Oversampled", (9, 1.1), color='red', fontsize=12)g = graphics_array([plot1, plot2], 2, 1) # 2 rows, 1 columng.show(gridlines=["minor", False])

The result is as follows:

## What just happened?

The function list_plot works a lot like scatter_plot from the previous example, so I won't explain it again. We used the method axes_range(x_min, x_max, y_min, y_max) to set the limits of the x and y axes all at once. Once again, we used the += operator to add a graphics object to an existing object. This time, we added a text annotation instead of a line. The basic syntax for adding text at a given (x,y) position is text('a string', (x,y)). To see the options that text accepts, type the following:

sage: text.options{'vertical_alignment': 'center', 'fontsize': 10, 'rgbcolor': (0, 0,1),'horizontal_alignment': 'center', 'axis_coords': False}

To display the two plots, we introduced a new function called graphics_array, which uses the basic syntax:

graphics_array([plot_1, plot_2, ..., plot_n], num_rows, num_columns)

This function returns another graphics object, and we used the show method to display the plots. We used the keyword argument gridlines=["minor", False] to tell Sage to display vertical lines at each of the minor ticks on the x axis. The first item in the list specifies vertical grid lines, and the second specifies horizontal grid lines. The following options can be used for either element:

 "major" Grid lines at major ticks "minor" Grid lines at major and minor ticks False No grid lines

Try playing with these options in the previous example.

(For more resources related to this topic, see here.)

# Using graphics primitives

We've already seen that Sage has graphics primitives such as lines and text annotations. Sage has other types of graphics primitives that can be used for plotting.

# Time for action – plotting with graphics primitives

A class of mathematical models called random sequential adsorption (RSA) models deals with the patterns that result when two-dimensional shapes are randomly deposited onto a plane. The following method can be used to visualize these kinds of models:

# Since the circles are random, your plot will not# look exactly like the example!circle_list = []for i in range(15):     x = -5 + 10 * random()     y = -5 + 10 * random()    circle_list.append(circle((x, y), 1, facecolor='red',           edgecolor=(0, 0, 1), thickness=2, fill=True))gr = sum(circle_list)gr.axes(False)gr.show(aspect_ratio=1, frame=True, gridlines=True, figsize=(4, 4))

You should get a plot that resembles the one below. Because the positions of the circles are randomly generated, your plot will not look exactly like this one.

## What just happened?

We created a list of graphics objects with a for loop and the circle function. The basic syntax for the circle function is as follows:

graphics_object = circle((center_x, center_y), radius)

In order to plot all the circles at once, we used the sum function to add up the list. We then prevented the axes from being drawn by calling the method gr.axes(False). Finally, when calling the show method we used the keyword argument frame=True to draw a frame, with ticks and labels, around the outside of the plotting area. The argument gridlines=True is a shortcut to activate both horizontal and vertical grid lines. Sage has many other types of primitives, including elliptical arcs, arrows, disks, ellipses, points, and polygons.

# Using matplotlib

We can access matplotlib directly to do things that we can't do with Sage plotting functions. matplotlib has such a large number of options and features. We will only touch on a few basic features. If you want to know more, the matplotlib website has excellent documentation:

http://matplotlib.sourceforge.net/contents.html

# Time for action – plotting functions with matplotlib

To illustrate the similarities and differences between plotting with matplotlib and plotting with Sage, we will repeat the first example of this article using the Pyplot interface to matplotlib. Enter and evaluate the following code:

import numpyimport matplotlib.pyplot as pltx = numpy.arange(-2 * numpy.pi, 2 * numpy.pi, 0.1)func1 = numpy.sin(x)func2 = numpy.cos(x)plt.figure(figsize=(5.5, 3.7)) # size in inchesplt.plot(x, func1, linewidth=2.0, color=(0.5, 1,0),label='$f(x)=sin(x)$')plt.plot(x, func2, linewidth=3.0, color='purple', alpha=0.5,label='$f(x)=cos(x)$')plt.xlabel('$x$')plt.ylabel('$f(x)$')plt.title('Plotting with matplotlib')plt.legend(loc='lower left')plt.savefig('demo1.png')plt.close()

The result should be as follows:

## What just happened?

We gained access to matplotlib functions and types with the following line:

import matplotlib.pyplot as plt

We can now access these functions as plt.function_name. We also import numpy so that we can use its numerical arrays.

There is an important difference between the Sage plot function and the matplotlib plot function. matplotlib always plots lists or arrays of discrete points, rather than callable symbolic expressions. This block of code creates an array of x values:

x = numpy.arange(-2*numpy.pi, 2*numpy.pi, 0.1)func1 = numpy.sin(x)func2 = numpy.cos(x)

func1 and func2 are arrays of y values. Notice that we specify the NumPy version of sin and cos, since the Sage functions don't know what to do with NumPy arrays. The syntax for plotting with matplotlib is as follows:

plt.figure()plt.plot(x_values, y_values)

The first line creates an empty figure. The optional argument figsize=(x_size, y_size) sets the figure size in inches. The second line plots the data points that are specified in the arrays or lists. By default, the points are connected with straight line segments. If you specify points that are too far apart, you will see the line segments instead of a smooth curve. The options for the plt.plot function are very similar to the options for the Sage plot function. The following code labels the x and y axes, and places a title above the figure:

plt.xlabel('$x$')plt.ylabel('$f(x)$')plt.title('Plotting with matplotlib')plt.legend(loc='lower right')

The legend method places a legend on the figure. You can use TeX to format any text on the plot by wrapping the text in dollar signs. The following code actually displays the plot:

plt.savefig('demo1.png')plt.close()

If you are running this example from the notebook interface, the graphic will automatically appear in the notebook. If you're running it in the interactive shell, you won't see any output. The savefig function will save an image file in your home directory. To specify a different path for saving files, pass a full or relative path in addition to the file name. For example:

sage: plt.savefig('Sage for Beginners/Chapter 6/Images/polar_plot.png')

matplotlib can save figures in a variety of image formats, such as png, pdf, ps (PostScript), eps (encapsulated PostScript), and svg (scalable vector graphics). It will automatically determine the correct format from the extension of the file name. You can also use the format keyword to specify the image format. PNG is a raster format, which is compatible with Microsoft Office and OpenOffice. For publications, it is best to use a vector format like PostScript, EPS, or PDF. The SVG format is used for displaying vector graphics on the Web.

# Using matplotlib to "tweak" a Sage plot

Every Sage plot is actually an encapsulated matplotlib figure. We can get the underlying figure and modify it.

# Time for action – getting the matplotlib figure object

Let's say you've made a plot with Sage, but you want to fix one or two formatting details, and Sage doesn't give you enough control. In this example, we'll use the object-oriented interface of matplotlib:

# Create a Sage plot, as shown in the first examplep1 = plot(sin, (-2*pi, 2*pi), thickness=2.0, rgbcolor=(0.5,1,0))p2 = plot(cos, (-2*pi, 2*pi), thickness=3.0, color='purple',alpha=0.5)plt = p1 + p2# Get the Matplotlib objectfig = plt.matplotlib()from matplotlib.backends.backend_agg import FigureCanvasAggfig.set_canvas(FigureCanvasAgg(fig)) # this line is criticalax = fig.gca() # get current axes# Add a legend and plot titleax.legend(['sin(x)', 'cos(x)'])ax.set_title('Modified with matplotlib')# Add a y axis label in a custom locationymin, ymax = ax.get_ylim()ax.set_ylim(ymin, ymax*1.2)ax.set_ylabel('$f(x)$', y=ymax*0.9)# Fancy annotation of a point of interestx_value = numerical_approx(-3*pi/4)y_value = numerical_approx(cos(-3*pi/4))ax.annotate('Point', xy=(x_value, y_value),     xytext=(-6, -0.5), color='red',     arrowprops=dict(arrowstyle="->", connectionstyle="angle3"))# Show the matplotlib figurefig.savefig('Sage_to_matplotlib.png')

The output should look like this:

## What just happened?

We modified a plot with matplotlib. First, we used Sage plotting commands to create a Sage graphics object. We then used the matplotlib method of the Sage graphics object to obtain the underlying matplotlib figure object. The rest of this example uses matplotlib functions, rather than Sage functions, to modify the figure. It is critical to use the following line of code:

fig.set_canvas(FigureCanvasAgg(fig))

The canvas is a "backend," which controls how matplotlib outputs the graphics it creates. Once we set the right canvas, we used the gca method of the figure object to get an object that represents the current axes. We then used methods of the axes object to modify the plot.

# Time for action – improving polar plots

In a previous example, we made polar pots with the Sage function polar_plot. However, polar plots in matplotlib look nicer because they are plotted on special axes. Let's use matplotlib to make these plots again. This example uses the Pyplot interface to matplotlib:

import numpyimport matplotlib.pyplot as plt# Repeat the antenna pattern example with the Pyplot interfaceN = float(7)theta = numpy.arange(0, numpy.pi, numpy.pi/100)def normalized_element_pattern(theta):     return abs(numpy.sin(theta))def array_factor(theta, N):     return abs(float(1 / N) * numpy.sin(float(N * pi / 2)         * numpy.cos(theta))         / numpy.sin(float(pi / 2) * numpy.cos(theta)))plt.figure(figsize=(6, 4))plt.subplot(121, polar=True)plt.polar(theta, normalized_element_pattern(theta))plt.title('Element factor')plt.subplot(122, polar=True)plt.polar(theta, array_factor(theta, N), color='red',        label="Array factor")plt.polar(theta, array_factor(theta, N) *        normalized_element_pattern(theta),        label="Pattern", color='blue')plt.legend(loc='lower right', bbox_to_anchor = (1, 0))plt.subplots_adjust(wspace=0.3)plt.savefig('Polar_plot.png')plt.close()

## What just happened?

We made polar plots on nicely formatted polar axes. We introduced a new Pyplot function called subplot, which creates multiple axes on a single figure, arranged as a grid. Subplot accepts three integer arguments that specify the arrangement of axes and chooses one of the axes as the current axes object. The first integer specifies the number of columns in the grid, the second integer specifies the number of rows in the grid, and the third integer selects the current axes object. The first subplot, which is number one, is located in the upper-left corner of the figure. Subplot numbers increase from left to right across a row, and from top to bottom. It is possible, although not recommended, to omit the commas between arguments and pass a single three-digit integer value to subplot. This rather unusual syntax was chosen for compatibility with the subplot function in MATLAB. We used the polar keyword to choose polar axes for each of the subplots.

We also introduced a function called subplots_adjust, which we used to increase the amount of horizontal space between the plots. This command can be used to adjust the amount of space around and between subplots, using the following keyword arguments:

 Keyword Default Meaning left 0.125 Space to the left of the subplots right 0.9 Space to the right of the subplots bottom 0.1 Space below the subplots top 0.9 Space above the subplots wspace 0.2 Space between columns of subplots hspace 0.2 Space between rows of subplots

# Plotting data with matplotlib

Because matplotlib plots arrays of points, it is well suited to working with data. You can make many kinds of charts and publication-quality graphics with matplotlib.

# Time for action – making a bar chart

Bar charts are often used to present experimental data in scientific papers. Let's make a chart with bars that represent the average value of some experimental data and add error bars to represent the standard deviation:

import numpyimport matplotlib.pyplot as plt# Define experimental datacluster1_data = numpy.array([9.7, 3.2])cluster1_x = numpy.array([2,4])cluster1_error = numpy.array([1.3, 0.52])cluster2_data = numpy.array([6.8, 7.3])cluster2_x = numpy.array([8,10])cluster2_error = numpy.array([0.72, 0.97])# Join data arrays for plottingdata = numpy.concatenate([cluster1_data, cluster2_data])bar_centers = numpy.concatenate([cluster1_x, cluster2_x])errors = numpy.concatenate([cluster1_error, cluster2_error])# Plotfig = plt.figure(figsize=(5,4)) # size in inchesplt.bar(bar_centers, data, yerr=errors,    width=2.0, align='center', color='white', ecolor='black')plt.ylabel('outcome')plt.text(4, 4, '*', fontsize=14)# Label ticks on x axisaxes = fig.gca()axes.set_xticks(bar_centers)axes.set_xticklabels(['trial 1', 'trial 2', 'trial 3', 'trial 4'])plt.savefig('Bar_Chart.png')plt.close()

The output should look like this:

## What just happened?

We created a publication-quality bar chart using the bar function from matplotlib. This function has two mandatory arguments. The first argument sets the horizontal location of each bar, and the second sets the height of each bar. Here is a summary of the optional arguments we used to customize the appearance of the plot:

 Keyword Description yerr Sets the size of the error bars on top of each bar. width Width of each bar. align Determines how the first argument is interpreted. If set to 'center', the array sets the location of the centre of each bar; otherwise, it sets the location of the left edge. color The color of the fill inside the bars. ecolor The color of the edge (outline) of the bars.

There are other optional arguments, which are described in the matplotlib documentation.

We used the text function to add text to the plot—in this case, an asterisk to indicate that one of the bars is statistically distinct from the others. The text function requires the x and y coordinates of the text, and a string containing the text to be displayed. The fontsize keyword allowed us to change the size of the text. In order to customize the tick labels on the x axis, we used the gca method of the figure object to get its axes object. We then passed an array of bar centres to the set_xticks method so that ticks will only be displayed at the centre of each bar. We used the set_xticklabels method to label the ticks with strings instead of numbers.

# Time for action – making a pie chart

matplotlib can also make business graphics that are more commonly associated with spreadsheets. Let's try a pie chart:

import numpyimport matplotlib.pyplot as pltdata = [1.0, 10.0, 20.0, 30.0, 40.0]explode = numpy.zeros(len(data))explode[3] = 0.1plt.figure(figsize=(4, 4))plt.pie(data, explode=explode, labels=['a', 'b', 'c', 'd', 'e'])plt.title('Revenue sources')plt.savefig('Pie_chart.png')plt.close()

The plot should look like this:

## What just happened?

We made a pie chart. The pie function in matplotlib only requires one argument, which is a list of numbers that indicate the relative size of the slices. The explode option takes a list of numbers that show how far to offset each piece of the pie from the centre. In this case, we created an array of zeros and set the fourth element to 0.1, which offset the fourth slice of the pie. We used the keyword explode to pass this array to the pie function. We used the labels keyword to pass a list of strings to be used as labels for each slice.

# Time for action – plotting a histogram

matplotlib has a built-in function for making histograms, which are used to visualize the distribution of values in a set of data. In this example, we will generate an array of random numbers that are drawn from a Gaussian distribution:

import numpyimport matplotlib.pyplot as pltdata = numpy.random.normal(0, 1, size=1000)plt.figure(figsize=(4, 4))plt.hist(data, normed=True, facecolor=(0.9, 0.9, 0.9))plt.savefig('Histogram.png')plt.close()

The result should be similar to the following plot. Because we are generating random data, your plot will not look exactly like this one:

## What just happened?

We used the hist function to visualize the distribution of values in an array of pseudorandom numbers. hist requires one argument, which is an array containing the data. In practice, the data would typically consist of experimental measurements, sensor data, or the results of a Monte Carlo simulation. We used the optional argument normed=True to indicate that the histogram should be normalized, which means that its integral is one. The facecolor keyword was used to specify the fill color of the bars as a tuple of R, G, B values.

# Summary

We have seen that Sage has powerful graphics capabilities. Specifically, we learned about:

• Plotting functions of one variable, in rectangular and polar coordinates
• Setting options that control the appearance of plots
• Visualizing data with list_plot and scatter_plot
• Using graphics primitives to customize
• Using matplotlib to gain more control over the formatting of plots
• Making various types of charts for presenting data

Further resources on this subject:

You've been reading an excerpt of: