I have this file : https://pastebin.com/WK6K97jv (columns are respectively x,y,z=f(x,y)).
I would like to plot using matplotlib (pyplot) unfortunately I never have to deal with 3d plot and I've tried to do this :
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
fig = plt.figure()
ax = fig.gca(projection='3d')
X=np.genfromtxt('./jpdf1/jpdf1.000533048.dat',usecols=(0,))
Y=np.genfromtxt('./jpdf1/jpdf1.000533048.dat',usecols=(1,))
X, Y = np.meshgrid(X, Y)
Z=np.genfromtxt('./jpdf1/jpdf1.000533048.dat',usecols=(2,))
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
but interpreter back me this :
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/homebrew/lib/python3.9/site-packages/matplotlib/_api/deprecation.py", line 431, in wrapper
return func(*inner_args, **inner_kwargs)
File "/opt/homebrew/lib/python3.9/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 1658, in plot_surface
raise ValueError("Argument Z must be 2-dimensional.")
ValueError: Argument Z must be 2-dimensional.
check the Z.shape whether equal to X.shape or Y.shape.
Z.shape == X.shape
then give your a example.
# import package
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
fig = plt.figure()
ax = fig.gca(projection='3d')
# generate x and y data
X = np.arange(20) # shape: 20
Y = np.arange(30) # shape:30
X, Y = np.meshgrid(X, Y) # convert x y data shape to new shape
print(X.shape) # (20,30)
print(Y.shape) # (20, 30)
Z= np.cos(X**2 + Y**2) # shape =(20,30)
printt(Z.shape) # (20, 30)
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
dears. I am a totally beginner to the python community and I would like to draw the below picture in python as a 3D.
I have made a try, but I could not reach any successful results.
This is my data
This is below my try:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
# data
x = [86, 91, 97]
y = [82, 88, 94]
z = [80, 85, 89]
ax1.plot(x,y,z)
plt.show()
Shape of your data is not correct. You provide 3 flat lists, what you should provide are x, y, z coordinates for each bar.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cm as cm
import numpy as np
# create data
data_2d = [[729, 575, 528],
[805, 768, 667],
[841, 773, 724],
[899, 857, 787]]
# Convert it into an numpy array.
data_array = np.array(data_2d)
# Create a figure for plotting the data as a 3D histogram.
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Create an X-Y mesh of the same dimension as the 2D data. The floor of the plot.
x_data, y_data = np.meshgrid( np.arange(data_array.shape[1]),
np.arange(data_array.shape[0]) )
# Flatten out the arrays so that they may be passed to "ax.bar3d".
# ax.bar3d expects three one-dimensional arrays:
# x_data, y_data, z_data. The following call boils down to picking
# one entry from each array and plotting a bar to from
# (x_data[i], y_data[i], 0) to (x_data[i], y_data[i], z_data[i]).
x_data = x_data.flatten()
y_data = y_data.flatten()
z_data = data_array.flatten()
dz = z_data
offset = dz + np.abs(dz.min())
fracs = offset.astype(float)/offset.max()
norm = colors.Normalize(fracs.min(), fracs.max())
color_values = cm.jet(norm(fracs.tolist()))
ax.bar3d( x_data, y_data, np.zeros(len(z_data)), 0.6, 0.6, z_data, color=color_values)
# Labels
ax.set_xlabel("Grid Size")
ax.set_ylabel("Bézier")
ax.set_zlabel("Success Rate")
# Ticks
ax.set_zticks(range(0,1200,200))
# Shape of the 3D cube
ax.set_box_aspect(aspect=(8,8,10))
output:
I have a 3D numpy array that has the dimensions 1400x1400x29. However, the data is 4D because for every x, y, z there is a different value (4th dimension). I believe that it can be done something like the below.
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
//some calculation that creates a 3D array called "cube"
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for x in range(1400):
for y in range(1400):
for z in range(29):
ax.scatter(x, y, z, c=cube[x,y,z])
plt.show()
However, the above script gives me an error saying
"TypeError: object of type 'numpy.float64' has no len()"
EDIT 1
Complete error message
File "cube.py", line 57, in <module>
ax.scatter(x, y, z, c=cube[z , x , y], cmap=plt.hot())
File "/pawsey/cle60up05/python/2.7.14/matplotlib/2.1.0/lib/python2.7/site-packages/matplotlib-2.1.0-py2.7-linux-x86_64.egg/mpl_toolkits/mplot3d/axes3d.py", line 2353, in scatter
xs, ys, s=s, c=c, *args, **kwargs)
File "/pawsey/cle60up05/python/2.7.14/matplotlib/2.1.0/lib/python2.7/site-packages/matplotlib-2.1.0-py2.7-linux-x86_64.egg/matplotlib/__init__.py", line 1710, in inner
return func(ax, *args, **kwargs)
File "/pawsey/cle60up05/python/2.7.14/matplotlib/2.1.0/lib/python2.7/site-packages/matplotlib-2.1.0-py2.7-linux-x86_64.egg/matplotlib/axes/_axes.py", line 4050, in scatter
colors = mcolors.to_rgba_array(c)
File "/pawsey/cle60up05/python/2.7.14/matplotlib/2.1.0/lib/python2.7/site-packages/matplotlib-2.1.0-py2.7-linux-x86_64.egg/matplotlib/colors.py", line 231, in to_rgba_array
result = np.empty((len(c), 4), float)
TypeError: object of type 'numpy.float64' has no len()
Thanks
So understanding cube is a numpy.ndarray of shape (1400, 1400, 29), the proper way to plot a 3D scatter would be:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
//some calculation that creates a 3D array called "cube"
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
X, Y, Z = np.mgrid[:1400, :1400, :29]
ax.scatter(X, Y, Z, c=cube.ravel())
plt.show()
You have to call ax.scatter with arrays, not scalars. Also, it takes a 1D array as c input, so I called ravel(). np.mgrid is just a fast way to create uniform grids of N-dimensions. It is equivalent to a np.meshgrid of np.arange. I suggest you read the documentation of each of those if you want to know more.
I was trying to plot a 3D diagram with manual input data (x,y,z) using ax.plot_surface. Even though I used a similar code I found online, I still got some errors.
"Warning (from warnings module):
File "D:\Program Files (x86)\Python\Python36\lib\site-packages\numpy\core\_methods.py", line 29
return umr_minimum(a, axis, None, out, keepdims)
RuntimeWarning: invalid value encountered in reduce
Warning (from warnings module):
File "D:\Program Files (x86)\Python\Python36\lib\site-packages\numpy\core\_methods.py", line 26
return umr_maximum(a, axis, None, out, keepdims)
RuntimeWarning: invalid value encountered in reduce
Warning (from warnings module):
File "D:\Program Files (x86)\Python\Python36\lib\site-packages\matplotlib\colors.py", line 489
np.copyto(xa, -1, where=xa < 0.0)
RuntimeWarning: invalid value encountered in less"
Even with this errors, the diagram could be plotted. But it's all black. And somehow, the colorbar does not match the z values.
Can anyone help me with this problem? I appreciate your help.
This is the code I used (the exact code is shown below):
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt
from matplotlib.mlab import griddata
import numpy as np
import scipy.interpolate
from matplotlib.ticker import LinearLocator, FormatStrFormatter
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = [1043.797,621.694,203.275,-213.783,-627.143,-1045.474,-1045.474,-628.403,-213.783,0.42,203.278,621.697,1043.801,1042.545,621.701,203.282,0.426,-213.778,-628.397,-1045.467,-0.834,1043.804,621.701,203.292,0.434,-213.77,-628.393,-1045.462,-1045.464,-628.395,-213.772,-0.829,203.29,621.707,1043.812,1043.807,621.706,203.287,-213.775,-628.398,-1045.466]
y = [-1210.936,-1211.146,-1210.931,-1210.819,-1210.916,-1210.916,-727.082,-726.768,-726.776,-726.883,-726.887,-727.101,-726.68,-242.741,-243.059,-242.846,-242.841,-242.732,-242.723,-243.037,19.801,241.133,241.025,241.248,241.148,241.154,241.167,241.07,725.216,725.208,724.565,725.401,724.976,724.97,724.975,1209.226,1209.324,1209.328,1209.338,1209.559,1209.254]
z = [3753.086,4054.802,4101.778,4064.706,3844.414,3614.887,4156.525,4184.521,4284.536,4269.797,4273.816,4298.024,4264.16,4224.935,4188.664,4200.863,4210.243,4164.851,4143.223,4148.073,3980.13,4094.025,4203.862,4260.099,4238.935,4233.248,4186.161,4072.293,4021.05,4311.022,4351.636,4359.61,4385.24,4382.892,4169.055,3927.979,4226.974,4237.096,4180.779,4082.677,3739.785]
x=np.asarray(x)
y=np.asarray(y)
N = 100
xi = np.linspace(x.min(), x.max(), N)
yi = np.linspace(y.min(), y.max(), N)
zi = scipy.interpolate.griddata((x, y), z, (xi[None,:], yi[:,None]),
method='cubic')
xi, yi = np.meshgrid(xi,yi)
surf = ax.plot_surface(xi, yi, zi, cmap=plt.cm.hot)
plt.show()
Due to the interpolation on the grid, the outmost points of the resulting array are nan (i.e. first and last column & first and last row). While nan values can be ignored for plotting, they are unfortunately not for producing the colorization. In order to be able to use a colormap, an array without nan values should be provided (this is strictly only true for 3D plots).
While there are in general several options like replacing values and masking, here the easiest is to leave out the rows and columns from plotting. I.e. instead of ax.plot_surface(xi, yi, zi, cmap="hot") you can use
ax.plot_surface(xi[1:-1,1:-1], yi[1:-1,1:-1], zi[1:-1,1:-1], cmap="hot")
Complete example:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
import scipy.interpolate
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = [1043.797,621.694,203.275,-213.783,-627.143,-1045.474,-1045.474,-628.403,-213.783,0.42,203.278,621.697,1043.801,1042.545,621.701,203.282,0.426,-213.778,-628.397,-1045.467,-0.834,1043.804,621.701,203.292,0.434,-213.77,-628.393,-1045.462,-1045.464,-628.395,-213.772,-0.829,203.29,621.707,1043.812,1043.807,621.706,203.287,-213.775,-628.398,-1045.466]
y = [-1210.936,-1211.146,-1210.931,-1210.819,-1210.916,-1210.916,-727.082,-726.768,-726.776,-726.883,-726.887,-727.101,-726.68,-242.741,-243.059,-242.846,-242.841,-242.732,-242.723,-243.037,19.801,241.133,241.025,241.248,241.148,241.154,241.167,241.07,725.216,725.208,724.565,725.401,724.976,724.97,724.975,1209.226,1209.324,1209.328,1209.338,1209.559,1209.254]
z = [3753.086,4054.802,4101.778,4064.706,3844.414,3614.887,4156.525,4184.521,4284.536,4269.797,4273.816,4298.024,4264.16,4224.935,4188.664,4200.863,4210.243,4164.851,4143.223,4148.073,3980.13,4094.025,4203.862,4260.099,4238.935,4233.248,4186.161,4072.293,4021.05,4311.022,4351.636,4359.61,4385.24,4382.892,4169.055,3927.979,4226.974,4237.096,4180.779,4082.677,3739.785]
x=np.asarray(x)
y=np.asarray(y)
N = 100
xi = np.linspace(x.min(), x.max(), N)
yi = np.linspace(y.min(), y.max(), N)
zi = scipy.interpolate.griddata((x, y), z, (xi[None,:], yi[:,None]),
method='cubic')
xi, yi = np.meshgrid(xi,yi)
surf = ax.plot_surface(xi[1:-1,1:-1], yi[1:-1,1:-1], zi[1:-1,1:-1], cmap=plt.cm.hot)
plt.show()
I try to visualize 3D surface using Matplolib.
I got a RESULTS.csv file with results:
T1,T2,Energy
0,0.0,0.0,0.0
1,0.0,-1.0,0.02326751
2,0.0,1.0,0.0232677
3,0.0,-2.0,0.09329646
4,0.0,2.0,0.0932964
5,0.0,-3.0,0.20991799
6,0.0,3.0,0.2099179
7,0.0,-4.0,0.37299244
8,0.0,4.0,0.37299269
9,0.0,-5.0,0.58232459
10,0.0,5.0,0.58232482
11,0.0,-6.0,0.83765862
12,0.0,6.0,0.83765867
13,-1.0,0.0,0.02297095
14,1.0,0.0,0.02297112
15,-1.0,-1.0,0.09457491
16,-1.0,1.0,-0.00195612
17,1.0,-1.0,-0.00195583
18,1.0,1.0,0.09457513
19,-1.0,-2.0,0.21270257
20,-1.0,2.0,0.01988884
21,1.0,-2.0,0.01988887
22,1.0,2.0,0.21270261
23,-1.0,-3.0,0.37714697
24,-1.0,3.0,0.08936601
25,1.0,-3.0,0.08936597
26,1.0,3.0,0.37714726
27,-1.0,-4.0,0.58764634
28,-1.0,4.0,0.20399978
29,1.0,-4.0,0.20399997
30,1.0,4.0,0.58764618
Subsequently, I wrote a script:
#!/usr/bin/env python
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
FRAME = pd.read_csv('RESULTS.csv')
fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-4, 4, 1.0)
xlen = len(X)
Y = np.arange(-4, 4, 1.0)
ylen = len(Y)
X, Y = np.meshgrid(X, Y)
Z = np.array(FRAME['Energy'])
colortuple = ('y', 'b')
colors = np.empty(X.shape, dtype=str)
for y in range(ylen):
for x in range(xlen):
colors[x, y] = colortuple[(x + y) % len(colortuple)]
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=colors,
linewidth=0, antialiased=False)
ax.set_zlim3d(-1, 1)
ax.w_zaxis.set_major_locator(LinearLocator(6))
plt.show()
Unfortunately it doesn't work in an expecting way and am getting the following error in return:
File "./test.py", line 27, in <module>
linewidth=0, antialiased=False)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 1586, in plot_surface
X, Y, Z = np.broadcast_arrays(X, Y, Z)
File "/usr/local/lib/python2.7/site-packages/numpy/lib/stride_tricks.py", line 191, in broadcast_arrays
shape = _broadcast_shape(*args)
File "/usr/local/lib/python2.7/site-packages/numpy/lib/stride_tricks.py", line 126, in _broadcast_shape
b = np.broadcast(*args[:32])
ValueError: shape mismatch: objects cannot be broadcast to a single shape
Any tips how to fix this error?
Why do you need this buggy "pandas"-module at all?
Everytime I see someone perform "pandas" operations together with numpy and matplotlib there appear absurd errors..
If you read your .csv-file conventionally with xlrd and add each cell value to a numpy array, and all 3 arrays "X", "Y" and "Z" have same length, there is no problem plotting it...
See matplotlib example
http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
print len(X)
print len(Y)
print len(Z) #all 3 arrays must have same length!
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()