# 3D Plotting Software for Python::Part 1::PyX

There are lots of good open-source tools that you can use to make high-resolution, publication-quality 2D plots.  Personally, I like to use Python, numpy, and matplotlib.  Unfortunately, it is much harder to find a good tools to make 3D plots.  Older versions of matplotlib had rudimentary 3D support, but this was removed in version 0.98.  In this post, I will review a Python 3D plotting library called PyX.

## Preparing the data

Figuring out how to store the data to be plotted was actually the hardest part of learning to use PyX.  The data format for 3D plots is not well documented.  PyX requires a list of (x,y,z) lists like this:

[
[x0  y0  z[0,0]]
[x0  y1  z[0,1]]
[x0  y2  z[0,2]]
...
[x1  y0  z[1,0]]
[x1  y1  z[1,1]]
[x1  y2  z[1,2]]
...
]

Unfortunately, PyX is designed to work with lists rather than Numpy arrays, which can be a real disadvantage for large datasets.  Here is a code snippet that shows how I transformed some Numpy data into a list of lists that can be plotted in PyX.  The 1D Numpy arrays z_values and theta_average contain x and y values, and the z values are stored in the 2D Numpy array called B_h_theta.

# Reshape data for plotting with pyx
values = []
for i in range(B_h_theta.shape[0]):
for j in range(B_h_theta.shape[1]):
values.append([z_values[i], theta_average[j], B_h_theta[i][j]])

## Plotting

First create a graph.data.points object.  The one required argument is a list of values to plot, in the form described above.  There are other types of graph.data objects for reading data from text files, plotting functions, etc.  Then, create a graph.graphxyz object which defines the visual appearance of the graph.  Call the plot() method of graph.graphxyz and pass in the data object as an argument.  Call the dodata() to finish the plot, and then call writeEPSfile() or writePDFfile() to write the plot to a file on disk.  There is no way (that I found) to just show the plot in a graphical window.

from pyx import *
v = graph.data.points(values, title="B(h,theta)", addlinenumbers=0, x=0, y=1, z=2)
g = graph.graphxyz(size=4, projector=graph.graphxyz.central(10, 150, 30),
x=graph.axis.linear(title="z"), y=graph.axis.linear(title=r'\$theta\$'),
z=graph.axis.linear(title="B(h,theta)"), x2=None, y2=None, z2=None)
g.plot(v, [graph.style.grid()])
g.dodata()
g.writeEPSfile("phi_plot")

## Results

• Clean, object-oriented interface
• Produces nice surface and wireframe plots in .pdf and .eps formats
• Appears to be flexible and full-featured