I have a 3d line plot of the solar spectrum, which I plotted using the command,
from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib.collections import PolyCollection, LineCollection
from matplotlib.colors import colorConverter, ListedColormap, BoundaryNorm
import matplotlib.cm as cm
fig = plt.figure(figsize(15, 8))
ax = fig.gca(projection='3d')
x = SpectrumDF['Wavelength']
z = SpectrumDF['DNI']
y = SpectrumDF['TESTNUM']
ax.plot(x, y, z)
ax.set_xlabel('Wavelength')
ax.set_ylabel('Test Number')
ax.set_zlabel('Intensity')
The resultant plot is solid blue and takes whichever individual color I give in the function: plot( ).
I have been trying to create a color gradient along the z-axis, intensity, without any success.
I have around 500 test numbers, each has 744 data points.
Thank you for the help!
This wouldn't let me post images because I don't have enough reputation. Anyway, here's the link to the plot I get using this code https://plus.google.com/106871046257785761571/posts/fMYsDF5wAQa
Using the example - Line colour of 3D parametric curve in python's matplotlib.pyplot - I got a scatter plot with color gradient along the z axis - here's the link to the image of that plot - https://plus.google.com/u/0/106871046257785761571/posts/SHTsntgQxTw?pid=6133159284332945618&oid=106871046257785761571
I used the following command:
fig = plt.figure(figsize(15,8))
ax = fig.gca(projection='3d')
x = FilteredDF['Wavelength']
z = FilteredDF['DNI']
y = FilteredDF['TESTNUM']
ax.scatter(x, y, z, c=plt.cm.jet(z/max(z)))
ax.set_xlabel('Wavelength')
ax.set_ylabel('Test Number')
ax.set_zlabel('Intensity')
plt.show()
I am still working on getting a colored line plot because I have a lot of points, which makes scatter plot very slow to work with.
Thank you
Related
I have three variables for my plot and I colour by the fourth variable. I have made a scatter plot via the following code, but I want a contour plot. My code:
import numpy as np
import matplotlib.pyplot as plt
a=np.linspace(4.0,14.0,3)
b=np.linspace(0.5,2.5,3)
c=np.linspace(0.0,1.0,3)
d=np.random.rand(len(a),len(b),len(c)) #colour by this variable
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
z,y,x=np.meshgrid(c,a,b)
img = ax.scatter(x, y, z, c=d, cmap='RdGy')
fig.colorbar(img, pad=0.2).set_label('colour')
ax.set_xlabel('c')
ax.set_ylabel('a')
ax.set_zlabel('b')
I want a filled contour instead of scatter plot. I know mayavi.mlab has this feature, but I cannot import mlab for some reason. Is there an alternative, or is there a better way of presenting this data?
Here is how I would present this 3-dimensional data. Each plot is a cross-section through the cube. This makes sense intuitively.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(4.0, 14.0, 3)
y = np.linspace(0.5, 2.5, 3)
z = np.linspace(0.0, 1.0, 3)
data = np.random.rand(len(x), len(y), len(z))
fig, axes = plt.subplots(len(z), 1, figsize=(3.5, 9),
sharex=True,sharey=True)
for i, (ax, d) in enumerate(zip(axes, data.swapaxes(0, 2))):
ax.contour(x, y, d)
ax.set_ylabel('y')
ax.grid()
ax.set_title(f"z = {z[i]}")
axes[-1].set_xlabel('x')
plt.tight_layout()
plt.show()
My advice: 3D plots are rarely used for serious data visualization. While they look cool, it is virtually impossible to read any data points with any accuracy.
Same thing goes for colours. I recommend labelling the contours rather than using a colour map.
You can always use a filled contour plot to add colours as well.
I have a data file in which there are 3 columns representing the x, y and z values. The z points are derived from a relation between x and y (so for each couple x[i]y[i] there is a z[i]). I'd like, using Matplotlib, to obtain a contour plot and coloring the surface by z values and then similarly a 3D plot. In lot of examples I've seen that it's possible to use numpy to meshgrid x and y (something that I cannot do because the huge amount of data) and then define z as f(x,y) but, as I said, I already have the z values for x and y.
With GnuPlot is quite simple do that but in this case I cannot really understand how it does.
Can you please help? Thank you in advance
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
data=pd.read_csv('data.dat')
x=np.array(data.iloc[:,0])
y=np.array(data.iloc[:,1])
z=np.array(data.iloc[:,2])
contour = plt.tricontour(x, y, z, 20, colors='k', extent=[min(x), max(x), min(y), max(y)], origin='lower', alpha=0.3) #obtain contour plot
plt.imshow(z, extent=[min(x), max(x), min(y), max(y)], origin='lower') #of course here comes the error about the shape of z
I solved as follow:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
###read file and set variables##
df=pd.read_csv('file.dat') #with some parameters#
D=df.iloc[:,:3]
x=np.array(D.iloc[:,0])
y=np.array(D.iloc[:,1])
z=np.array(D.iloc[:,2])
cv1=np.array(x[0:len(x):100])
cv2=np.array(y[0:len(y):100])*(180/np.pi)
fes=np.array(z[0:len(z):100])
### set plot ###
m=cm.ScalarMappable(cmap=cm.coolwarm)
m.set_array([min(fes),max(fes)])
m.set_clim(vmin=min(fes),vmax=max(fes))
fig=plt.figure()
surf=plt.axes(projection='3d')
surf.plot_trisurf(cv1,cv2,fes, cmap='coolwarm')
plt.tricontour(cv1,cv2,fes, colors='k', zdir='z', offset=-np.abs(min(z)), alpha=0.3)
plt.tricontourf(cv1,cv2,fes, cmap='coolwarm', zdir='z', offset=-np.abs(min(z)))
###finally set labels, ticks and colorbar###
I have this code which contains a 3D plot. I run the code in Spyder; I want to know if it is possible to make this plot a rotating one (360 degrees) and save it.
Thanks!
P.s. Sorry if it is a silly question, but I am a newby in Python.
import matplotlib.pyplot as plt
import numpy as np
from scipy import array
jet = plt.get_cmap('jet')
from matplotlib import animation
fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.linspace(70,40,4)
Y = np.linspace(5,2,4)
X,Y= np.meshgrid(X, Y)
Z = array ([
[1223.539555, 1428.075086,1714.479425, 2144.053223],
[1567.26647,1829.056119,2990.416079,2745.320067],
[2135.163957,2491.534201, 2990.416079,3738.761638],
[3257.280827, 3800.655101, 4561.372117, 5702.458776],
])
surf = ax.plot_surface(X, Y, Z, rstride = 1, cstride = 1, cmap = jet,linewidth = 0,alpha= 1)
ax.set_zlim3d(0, Z.max())
fig.colorbar(surf, shrink=0.8, aspect=5)
ax.set_xlabel('Axial Length [mm]')
ax.set_ylabel('nbTurns')
ax.set_zlabel('RPM')
plt.show()
You need to define a function in order to get a specific animation. In your case it is a simple rotation:
def rotate(angle):
ax.view_init(azim=angle)
Then use the matplotlib animation:
rot_animation = animation.FuncAnimation(fig, rotate, frames=np.arange(0,362,2),interval=100)
This will call the rotate function with the frames argument as angles and with an interval of 100ms, so this will result in a rotation over 360° with a 2° step each 100ms. To save the animation as a gif file:
rot_animation.save('path/rotation.gif', dpi=80, writer='imagemagick')
I am looking to make a plot similar to the one found here, with the simple difference that I would like to to set the distance from the center for each point. Ie, given a slice of the plot is a circle, where I would like each of the points to be at a definable distance from the center.
What I a starting with, given a simple modification of the previously mentioned answer:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib
import numpy as np
from scipy.interpolate import interp1d
from matplotlib import cm
from matplotlib import pyplot as plt
step = 0.04
maxval = 1.0
fig = plt.figure()
ax = Axes3D(fig)
# u here would define the desired distance from radial axis
# u=np.array([0,1,2,1,0,2,4,6,4,2,1])
v=np.array([4,4,6,3,6,4,1,4,4,4,4])
r=np.array([0,1,2,3,4,5,6,7,8,9,10])
f=interp1d(r,u)
# walk along the circle
p = np.linspace(0,2*np.pi,len(r))
R,P = np.meshgrid(r,p)
# transform them to cartesian system
X,Y = R*np.cos(P),R*np.sin(P)
Z=f(R)
ax.scatter(X, Y, Z)#, rstride=1, cstride=1, cmap=cm.jet)
ax.set_xticks([])
fig.savefig(str(output_prefix + '3d..png'), dpi=(200))
What I would like to plot (apologies for the blurred sketch):
I have tried using interp2d to add the u variable commented out above, but no luck. Changing Z to the array u threw the error that X, Y, and Z must be the same size ("Argument 'zs' must be of same size as 'xs' ", understandably as X and Y are now interpolated) What do I need to do? Any tips would be appreciated!
I don't know exactly what you meant in your question.
I made v to be the offset of the center of the circles in x-axis.
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from scipy.interpolate import interp1d
from matplotlib import pyplot as plt
step = 0.04
maxval = 1.0
fig = plt.figure()
ax = Axes3D(fig)
# v here would define the desired distance from radial axis
u=np.array([0,1,2,1,0,2,4,6,4,2,1])
v=np.array([4,4,6,3,6,4,1,4,4,4,4])
r=np.array([0,1,2,3,4,5,6,7,8,9,10])
f=interp1d(r,u)
# walk along the circle
V = np.tile(v, (len(u), 1))
p = np.linspace(0,2*np.pi,len(r))
R,P = np.meshgrid(r,p)
# transform them to cartesian system
X,Y = V + R*np.cos(P),R*np.sin(P)
Z=f(R)
ax.scatter(X, Y, Z)#, rstride=1, cstride=1, cmap=cm.jet)
ax.set_xticks([])
plt.show()
x,y are positions of the circles and r is the radius - all vectors.I want to plot them all at once. Something like:
import matplotlib.pyplot as plt
from matplotlib.patches Circle
#define x,y,r vectors
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
plt.Circle((x,y),r,color='r')
plt.show()
Thanks.
plt.scatter allows you to define a radius of the points plotted.
From the doc
matplotlib.pyplot.scatter(x, y, s=20, c='b', marker='o')
[...]
s:
size in points^2. It is a scalar or an array of the same length as x and y.
Playing with facecolor and edgecolor you should be able to get what you want
You can find an example in How to set_gid() for each bubble in matplot scatter chart?
I am not informed about the Circles patch, but here is how you can do it with the standard plot command:
import numpy as np
import matplotlib.pyplot as plt
x = np.array([0.2,0.4])
y = np.array([0.2,1.2])
r = np.array([0.5,0.3])
phi = np.linspace(0.0,2*np.pi,100)
na=np.newaxis
# the first axis of these arrays varies the angle,
# the second varies the circles
x_line = x[na,:]+r[na,:]*np.sin(phi[:,na])
y_line = y[na,:]+r[na,:]*np.cos(phi[:,na])
plt.plot(x_line,y_line,'-')
plt.show()
The basic idea is to give the plt.plot(...) command two 2D arrays. In that case they are interpreted as a list of plots. Espacially for many plots (=many circles) this is much faster, than plotting circle by circle.