3

I am looking to plot a 3D surface. The data is generated in mathematica and exported in a file with three columns separated by spaces (I can switch it to comma or other delimiter). The problem I have is that so far I have been using gnuplot for all my 2D plots, but for this particular plot gnuplot is not really that easy to use and the results are not that great.

I have read about matplotlib but I find the documentation really difficult to get through. When I started with gnuplot, I found a really good template here which I can use to generate 2D plots and multiplots any way I like.

Is there something similar for matplotlib that I can use? Almost all examples for matplotlib involve functions that are plotted in various ways but there aren't any examples where data is imported and the plotted.

  • Seems like you might be able to "functionalize" the data in the file—by which I mean create a function that could be called or otherwise used by matplotlib that provides the file data to it a/the way it expects/requires.. – martineau Jun 4 '18 at 12:26
  • I don't really understand what you mean by functionalize. If you mean that I should generate the data (that now is comming from mathematica) inside matplotlib, while it is doable in principle, I do not have the experience with python to do it. I wrote a rather complicated program in mathematica which gives me the data. The problem is that Mathematica in all its might it is rather poor at exporting nice figures suitable for publication. – lucian Jun 4 '18 at 16:33
  • No, that's not what I meant by the (made-up) term "functionalize". What I was trying to describe was the creation of a function that could be used with matplotlib's existing function-plotting capabilities that would present/return the data (from your existing exported file) to it in the format or way it expects or requires. Python can easily read the file data and is also capable of providing that data to the caller (matplotlib) incrementally if necessary. I suggest you re-ask your question on stackoveflow. – martineau Jun 4 '18 at 16:50
  • Hope it helps. When you do, be sure to tag your question with both "python" and "matplotlib" tags. – martineau Jun 4 '18 at 17:14
3

I think you're asking several questions here, I will try and answer the most fundamental one: loading your CSV data into Python and then plotting a basic surface plot.

Note that in the general case you need an NxN matrix of Z values for a plot where X and Y are vectors of length N. This makes sense because every (x, y) point needs a Z value and there are N x N (x, y) points. I will show you two ways. Once you have those then at least you are in a good position to start customizing your plot using documentation and other examples found on the web.

This answer assumes you are using Python 3 and a recent version of Matplotlib and Numpy. (Numpy is a numerical Python package that is commonly included in Python distributions, e.g. Anaconda.) However, syntax should be not be very different in older versions.

First, make the necessary imports:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

For the case when you have 3 columns of 1d data --- x, y and z:

DataAll1D = np.loadtxt("datacsv_1d.csv", delimiter=",")

# create 2d x,y grid (both X and Y will be 2d)
X, Y = np.meshgrid(DataAll1D[:,0], DataAll1D[:,1])

# repeat Z to make it a 2d grid
Z = np.tile(DataAll1D[:,2], (len(DataAll1D[:,2]), 1))

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.plot_surface(X, Y, Z, cmap='ocean')

plt.show()

enter image description here

Note than in np.loadtxt you can set any delimiter, e.g. ' ' for a space.

For the case when you have 2 columns of 1d data --- x and y --- and a 2d matrix of z data:

DataX_Y_1D = np.loadtxt("datacsv_1d_xy.csv", delimiter=",")

# create 2d x,y grid (both X and Y will be 2d)
X, Y = np.meshgrid(DataX_Y_1D[:,0], DataX_Y_1D[:,1])

# get 2D z data
Z = np.loadtxt("datacsv_2d_Z.csv", delimiter=",")

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.plot_surface(X, Y, Z, cmap='ocean')

plt.show()

enter image description here

For more advanced customization, here's a link to another good tutorial on the subject:

https://jakevdp.github.io/PythonDataScienceHandbook/04.12-three-dimensional-plotting.html

Edit: For the case where you have all the necessary data points covered in 3 columns (X, Y, Z) then plot_trisurf is what you need. See my answer on Stack Overflow for a simple example: https://stackoverflow.com/questions/39240327/3d-surface-plot-using-matplotlib-in-python/52630484#52630484

| improve this answer | |
  • 1
    thank you very much! this is a very clear answer! I will try to build on it! – lucian Aug 2 '18 at 7:48
  • Sure --- Feel free to post a new question/comment if you need clarification. Surface plots are always a bit tricky. – Moustache Aug 2 '18 at 10:39
  • Note: I wrote another answer for the case when you have just have 3 columns of unstructured X, Y, Z data (when all necessary data points are covered in those 3 columns) on stack overflow: stackoverflow.com/questions/39240327/… – Moustache Oct 3 '18 at 15:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.