3D Python Plotting (x,y,z) with list of lists - python

I'm trying to to a 3D scatter plot (or any 3D plot that will work) in Python 3.7.6. I have x, y, and z data in the following formats:
x = [[1,2,3,46,2,...],[6,4,24,56,4,...],...[7,3,52,524,3...]]
y = [[3,4,5,63,...],[23,35,64,4,6,3...],...[34,345,45,4,3,4,...]]
z = [1,2,3,4,5,6,7,8,...]
The data corresponds to essentially a 3D volume where x[0] and y[0] are plotted at z[0], and so on. The data that I put there is example data, not actual numbers that I am using.
When I try to plot using
ax.scatter(x,y,z)
I get the error as seen in the attached figure .
My code is written as :
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.scatter(xphases,yphases,zphases)

Related

Projection of 2D histogram to one axis with matplotlib

I have the following code where I produced a 2d histogram with matplotlib of a function f of two variables, namely x and y. x goes from 0 to 7 and y from 0 to np.pi/2. Below you can find related code. I would like to project onto the x-axis so that I have the function f only as function of x: f(x). How can I do that? I would like to plot it as a 1d histogram and possibly save the values in a list.
from matplotlib import cm
plt.figure(figsize=(20,16))
h = plt.hist2d(x, y, bins=[110,110],cmin=0.000001,cmap='jet')
plt.colorbar(h[3])
plt.title("SW Distribution for Pion Zero",fontsize=22)
plt.xlabel("Momentum (GeV/c)",fontsize=22)
plt.ylabel("Angle (rad)",fontsize=22)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.show()

Python - matplotlib - how do I plot a plane from equation?

I have an equation z=0.12861723162963065X + 0.0014024845304814665Y + 1.0964608113924048
I need to plot a 3D plane for this equation in python using matplotlib. I have already tried following this post -- Given general 3D plane equation, how can I plot this in python matplotlib?
However I am unable to set the x,y and z limits for this plane.
Can someone provide me the correct way of converting this equation into 3D plane. Thanks
You have it easy since your equation gives the value of z for any values of x and y.
So choose any limits you like for x and y. You could even use the ones in the web page you linked to. Just calculate the z values according to your equation. Here is code modified slightly from the linked page:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
x = np.linspace(-1,1,10)
y = np.linspace(-1,1,10)
X,Y = np.meshgrid(x,y)
Z=0.12861723162963065*X + 0.0014024845304814665*Y + 1.0964608113924048
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z)
And here is the result:
That is not the greatest graph, but now you can modify some of the parameters to get just what you want.

Python - 3D Plotting, horizontal lines missing and incorrect gradients showing

I am new to 3D surface plots and I am trying to make a 3D plot of temperature as a function of distance and time using the following:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
t = np.arange(0,60,1)
z = np.arange(5,85,5)
fig=plt.figure(1)
ax = fig.gca(projection='3d')
X, Y = np.meshgrid(z, t)
surface=ax.plot_surface(X,Y,T1, linewidth=1,cmap=cm.coolwarm, antialiased=False)
fig.colorbar(surface, shrink=0.5, aspect=5)
ax.view_init(ax.elev, ax.azim+90)
ax.set_title("Temperature Distribution 1")
ax.set_xlabel('z (cm)')
ax.set_ylabel('Time (min)')
ax.set_zlabel('Temperature ($^\circ$C)')
ax.set_xticks(np.arange(0,80, 15))
plt.savefig("3D_1.png",format='png',dpi=1000,bbox_inches='tight')
plt.show()
T1 is 2D data. This produces the following:
There is only 1 horizontal line showing at around 60cm, however I would like a horiztonal line every 5cm (data was taken along every 5cm). It seems there is only 2 sections to the plot along the distance axis. The colour gradients are showing in large blocks instead of showing as a function of temperature all along the length.
e.g. for time between 50-60mins from distance 0~40cm, the temperature goes from ~180 to ~20 degrees, but the colour of that block is dark red all the way along it, instead it should start as dark red and reduce down to blue. How do I get the temperature to show the correct gradient along the whole length axis.
Also the temperature legend is in %, instead of the temperature values in degrees, how do I fix this?
Looking at the documentation of surface we find
The rstride and cstride kwargs set the stride used to sample the input data to generate the graph. If 1k by 1k arrays are passed in, the default values for the strides will result in a 100x100 grid being plotted. Defaults to 10.
Thus, using
surface=ax.plot_surface(X,Y,T1, rstride=8, cstride=8)
you get
While using
surface=ax.plot_surface(X,Y,T1, rstride=5, cstride=1)
you get
This is an example how to create reproducible data for this case:
t = np.arange(0,60,1)
z = z=np.arange(5,85,5)
f = lambda z, t, z0, t0, sz, st: 180.*np.exp(-(z-z0)**2/sz**2 -(t-t0)**2/st**2)
X, Y = np.meshgrid(z, t)
T1 =f(X,Y,-20.,56, 40.,30.)

Creating a 3D plot of several lines in one figure

I'm currently having a small problem with plotting several different lines in a 3d plot. I have a list of lists containing three numpy arrays corresponding to the xyz coordinates for the three points on each line, i.e.
lines=[[array([10,0,0]),array([10,0,101.5]),array([-5,0,250])],[array([9,0,0]), array([9,0,101.5]),array([-4,0,250])]]
would represent 2 lines with 3 sets of xyz coordinates in each (the first one here would be (10,0,0),(10,0,101.5) and (-5,0,250)).
In general I would have n lines in this list each with 3 sets of xyz coordinates each. I would like to plot these lines on a single 3d plot with matplotlib. All I've managed to do so far is to create n plots each containing a single line.
Thanks for the help!
EDIT:
I have a list 'lines' containing 'line' objects which are just lists themselves containing 3 numpy arrays for the 3 points on each line. I tried to use the following method:
for line in lines:
fig = plt.figure()
ax = fig.gca(projection='3d')
z = []
for i in [0,1,2]:
z.append(line[i][2])
x = []
for i in [0,1,2]:
x.append(line[i][0])
y = []
for i in [0,1,2]:
y.append(line[i][1])
ax.plot(x, y, z, label='path')
plt.show()
I think I understand why this gives me 2 plots of lines 1 and 2 but I can't figure out a way to put both lines on the same plot.
You almost got it. The solution to your problem is simple, just move required statments out of for loop:
import matplotlib.pyplot as plt
lines=[[array([10,0,0]),array([10,0,101.5]),array([-5,0,250])],[array([9,0,0]), array([9,0,101.5]),array([-4,0,250])]]
fig = plt.figure()
ax = fig.gca(projection='3d')
for line in lines:
z = []
for i in [0,1,2]:
z.append(line[i][2])
x = []
for i in [0,1,2]:
x.append(line[i][0])
y = []
for i in [0,1,2]:
y.append(line[i][1])
ax.plot(x, y, z, label='path')
plt.show()
I had a similar problem trying to plot a 3D path between locations, and this was about the closest / most helpful solution I found. So just if anybody else is trying to do this and might find this similar solution sheds a bit of light :
for location in list_of_locations:
x_list.append(locdata[location].x) # locdata is a dictionary with the co-ordinates of each named location
y_list.append(locdata[location].y)
z_list.append(locdata[location].z)
fig = plt.figure()
ax = fig.gca(projection='3d')
for i in range(len(x_list)-1):
xs = [x_list[i], x_list[i+1]]
ys = [y_list[i], y_list[i+1]]
zs = [z_list[i], z_list[i+1]]
ax.plot(xs,ys,zs)
plt.show()
I'm sure it doesn't need to be two separate for loops but for my little data set this was totally fine, and easy to read.

plotting 3d histogram/barplot in python matplotlib

I have an Nx3 matrix in scipy/numpy and I'd like to make a 3 dimensional bar graph out of it, where the X and Y axes are determined by the values of first and second columns of the matrix, the height of each bar is the third column in the matrix, and the number of bars is determined by N.
In other words, if "data" is the matrix then:
data[:, 0] # values of X-axis
data[:, 1] # values of Y-axis
data[:, 2] # values of each Z-axis bar
and there should be one bar for each len(data)
How can I do this in Matplotlib?
Secondly, as a variant of this, how can I do the same thing, but this time histogram the bars into N bins in each X, Y, Z dimension? I.e. instead of a bar for each point, just histogram the data into those bins in every dimension, and plot a bar for each bin.
thanks very much for your help.
Here is one example of a 3D bar plot.
Here is another.
Numpy has a function called histogram2d to do the rectangular binning you want.
I had a little of a hard time shaping the 'heights' of my data properly from the examples, but finally got it to work with the following code. Here, Z is a 3 dimensional array with all of my data, and x and rval are basically the 2-d indices corresponding to the datapoints.
xs = np.arange(biopsy_num)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for y in (np.arange(r_sweep)):
z = Z[:,y]
ax.bar(xs, z, zs=y, zdir='y', alpha=0.8)
ax.set_xlabel('biopsies')
ax.set_ylabel('radius of biopsy')
ax.set_zlabel('Shannon Index')
plt.show()

Categories

Resources