5

I'm plotting a 3D scatter plot reading my values from a file. Each line of this file has 3 coordinates and a standard deviation. Let's keep the errors aside for the moment.

import os
import numpy as np
import matplotlib.pyplot as plt

input_file = os.path.normpath('C:/Users/sturaroa/Documents/my_file.tsv')

# read data from file
my_data = np.genfromtxt(input_file, delimiter='\t', skiprows=0)
X = my_data[:, 0]  # 1st column
Y = my_data[:, 1]  # 2nd column
Z = my_data[:, 2]  # 3rd column
errors = my_data[:, 3]  # 4th column (errors)

# draw 3D scatter graph
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.scatter(X, Y, Z)

I get this 3d_scatter_plot

There is a nice example in the gallery that draws a surface and the projection of contours (image below). I need to have a similar representation while elaborating my data as little as possible (to prevent distortions).

contourf3d_demo2

I'm aware of this question explaining how to get a 3D surface out of irregular 3D data. However, it "smooths" the curve, and interpolates to a regular set of points. I've read the doc about griddata, it says it returns a

2d float array - Array of values interpolated at (xi, yi) points.

Not what I want. I was told by some people that I absolutely need to interpolate to find a surface. Ant it may be true. I was also told by some other people that interpolation is bad, because it forces a shape. And this is probably also true (for large values of "interpolation").

How can get a decent 3D graph with minimal interpolation? Is there something like just linking the closest 3D points together?

By the way, my data is fairly regular, like they are organized as a set of 2D planes, or "slices", but I'd like to know if this is possible without making that assumption.

Here's an example file, it's the same used for the scatter plot. It's simple and regular, I would suggest testing on a more general one, if possible.

2    1    2.0    0.0
2    2    82.666664    35.30187
2    3    100.0    0.0
2    4    98.0    4.472136
2    7    100.0    0.0
2    12    100.0    0.0
2    15    100.0    0.0
2    17    100.0    0.0
2    21    100.0    0.0
2    24    100.0    0.0
3    1    2.0    0.0
3    2    4.0    0.0
3    3    6.0    0.0
3    4    8.181818    0.60302263
3    7    15.090909    1.8683975
3    12    53.454544    33.6344
3    15    97.09091    3.9358494
3    17    97.09091    3.9358494
3    21    97.09091    3.3898242
3    24    97.09091    3.5058389
4    1    2.0    0.0
4    2    4.0    0.0
4    3    6.0    0.0
4    4    8.0    0.0
4    7    14.0    0.0
4    12    24.0    0.0
4    15    30.333334    0.74535596
4    17    37.666668    2.1343749
4    21    48.0    5.1639776
4    24    92.0    11.075499

Longer example input. The first 2 columns are supposed to be int and the last 2 ones are float.

Here's an improved loading, just in case

# tell numpy the first 2 columns are int and the last 2 are floats
my_data = np.genfromtxt(infile, dtype=[('a', '<i8'), ('b', '<i8'), ('x', '<f8'), ('d', '<f8')])

# access columns by name
print(my_data["b"]) # column 1
Community
  • 1
  • 1
Agostino
  • 2,723
  • 9
  • 48
  • 65
  • I think what you want is to put surfaces as triangles between adjacent triples of points. Does that make sense? I am pretty sure you will be able to find a function that does it. – Konstantin Schubert Mar 27 '15 at 18:30
  • Triangles would be fine, quadrilaterals too. I'm not so proficient in matplotlib, some code would help. – Agostino Mar 27 '15 at 18:33
  • In general you cannot draw a plane through 4 points in 3D. This means that quadrilaterals are not possible without being bent. (the plot in my answer below has not quadrilaterals as they are bent across one diagonal.) – Konstantin Schubert Mar 27 '15 at 18:52
  • If triangles are more suited, that's fine. The interesting part is how to find those triangles with minimum bias. – Agostino Mar 27 '15 at 19:00

2 Answers2

1

You want to draw a surface that goes exactly though all your data points and that does so "directly" without smoothing out.

I recently created this plot with matplotlib: enter image description here

I wouldn't want to claim that it has minimal "smoothness", but at least it passes exactly through all data points.

I used the plot_surface function from matplotlib. You might also want to use plot_wireframe

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(xGrid, yGrid, zGrid, rstride=1, cstride=1,cmap="autumn")

I think part of the trick is to set rstride=1 and cstride=1. You probably want to verify this. Someone with a deeper insight might be able to explain this better, in the documentation it just says that the stride is the sampling length.

Konstantin Schubert
  • 3,242
  • 1
  • 31
  • 46
  • It paints an empty plot in my case. I don't have grids, I have a set of 3D points. I can post an example file, if needed. – Agostino Mar 27 '15 at 18:54
  • Any news? The code you provided uses grids. Please, expain how you created those grids and if they truly have a minimal interpolation. – Agostino Mar 31 '15 at 02:15
  • The x Grid is a 2D array with the x-values for all points of the x-y plane. The y-Grid has the y-values for all points in the x-y plane. The z - Grid has the z-values for all points in the x-y plane. How to transform your data into this format is a simple question, maybe a bit googling and trial and error. I could do it for you, or you could do it yourself, sorry. Or ask another question. As for the answer if the interpolation is "minimal", I cannot answer this, partially because the question isn't well-defined and partially because I don't know. – Konstantin Schubert Mar 31 '15 at 13:00
  • I would appreciate if you showed how to turn my example input into those grids. It's a crucial point for me. I added a longer example input as well, if that can be of help. – Agostino Mar 31 '15 at 15:00
0

This is an old post, but I think this can be accomplished using matplotlib's triangulation support. See the mkTris() function in this question, though on a different topic. The final surface plot places triangle vertices at the original, irregularly-space samples. The rest of the plotted surface lies on a triangle face.

Jim
  • 474
  • 5
  • 17