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
Advantages
- Clean, object-oriented interface
- Produces nice surface and wireframe plots in .pdf and .eps formats
- Appears to be flexible and full-featured
Disadvantages
- Does not seem to be actively developed or maintained (although it is very useful in its present state)
- Does not integrate easily with Numpy–all data needs to be stored in text files or Python lists
- No GUI output–writes images straight to .pdf or .eps files
- TeX labels have poor resolution (at least on my system)
i am in the middle of picking something up for the 3D vector map. thanks for the review. please keep on.
You can look at a much better solution IMHO: Asymptote.
I may confess that it’s not in Python but an amazing solution for 3D with animation and 3D pdf generation have a look at Asymptote:
http://asymptote.sourceforge.net/gallery/
Thanks, Anton! I’m glad to hear that you liked it.
Francois–I was actually planning to do a “part 2” of this review covering Asymptote when this site went down due to a server crash. I have hacked together a process to run Asymptote from Python so that I don’t have to manually go through the process of generating a data file and then running Asymptote. I will write a new post on this as soon as I get some time.