matplotlib 3D ribbon plot - python

I'm using NumPy 1.6.2, SciPy 0.11.0, Matplotlib 1.1.1. Can I plot ribbons as in the picture?

This is the full code.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import griddata
from mpl_toolkits.mplot3d import Axes3D
data=np.genfromtxt('fluorescence_2.txt')
x=data[:,0]
fig=plt.figure()
ax=fig.gca(projection='3d')
for i in range(1,17,2):
y=data[:,i]
z=data[:,i+1]
xi=np.linspace(min(x),max(x))
yi=np.linspace(min(y),max(y))
X,Y=np.meshgrid(xi,yi)
Z=griddata(x,y,z,xi,yi)
ax.plot_surface(X,Y,Z,rstride=50,cstride=1,cmap='RdYlBu')
ax.set_zlim3d(np.min(Z),np.max(Z))
ax.set_title('Fluorescence spectra (WL ex = 350 nm)')
ax.set_xlabel('WL em (nm)')
ax.set_ylabel('Spectrum')
ax.set_yticks([])
ax.set_zlabel('Emission')
plt.show()

In my previous version was necessary to change the data table structure before the load into the script. The following version is my last and it plots the ribbons directly from the original data, a simple table of absorbances.
import itertools
import numpy as np
from matplotlib.mlab import griddata
from mpl_toolkits.mplot3d import Axes3D
from pylab import *
matplotlib.rcParams.update({'font.size':10})
spectra=loadtxt('C:/.../absorbance.txt')
fig=figure()
ax=fig.gca(projection='3d')
for i in range(0,7+1):
y=spectra[:,i]
x=sorted(range(1,len(y)+1)*2)
a=[i,i+1]*len(y)
b=list(itertools.chain(*zip(y,y)))
xi=np.linspace(min(x),max(x))
yi=np.linspace(min(a),max(a))
X,Y=np.meshgrid(xi,yi)
Z=griddata(x,a,b,xi,yi)
ax.plot_surface(X,Y,Z,rstride=50,cstride=1,cmap='Spectral')
ax.set_zlim3d(np.min(Z),np.max(Z))
ax.grid(False)
ax.w_xaxis.pane.set_visible(False)
ax.w_yaxis.pane.set_visible(False)
ax.w_zaxis.pane.set_color('gainsboro')
ax.set_title('Molecular spectra')
ax.set_xlim3d(0,23)
ax.set_xticks([1.6735,6.8367,12.0000,17.1633,22.3265])
ax.set_xticklabels(['350','400','450','500','550'])
ax.set_xlabel('Wavelength (nm)')
ax.set_yticks([0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5])
ax.set_yticklabels(['1','2','3','4','5','6','7','8'])
ax.set_ylabel('Spectrum')
ax.set_zlim3d(0,2)
ax.set_zlabel('Absorbance')
show()

Here is working code to create a ribbon plot. It is based off of the mplot3d example code: surface3d_demo.py and then modified to create ribbons. My code my not be the most efficient way to do it, but it works.
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
#create data
x = np.linspace(-10,5,200)
y = np.linspace(-5,5,40)
xGrid, yGrid = np.meshgrid(y, x)
z = np.sin(np.sqrt(xGrid**2 + yGrid**2))
numPts = x.shape[0]
numSets = y.shape[0]
fig = plt.figure()
ax = fig.gca(projection='3d')
#plot each "ribbon" as a surface plot with a certain width
ribbonWidth = 0.75
for i in np.arange(0,numSets-1):
X = np.vstack((x,x)).T
Y = np.ones((numPts,2))*i
Y[:,1] = Y[:,0]+ribbonWidth
Z = np.vstack((z[:,i],z[:,i])).T
surf = ax.plot_surface(X,Y,Z, rstride=1, cstride=1, cmap=cm.jet,
linewidth=0, vmin=-1, vmax=1)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
ax.set_xlabel('Data Points')
ax.set_ylabel('Data Set Number')
ax.set_ylim((0,numSets))
ax.set_zlabel('Z')
ax.set_zlim((-1, 1))
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()

Related

3D scatter with two axes in logscale

I am trying to get a scatter plot with 2 axes (x,z) in a log scale using set_scale but that doesn't work.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
x=np.linspace(0,500,10)
y=np.linspace(0,1,10)
z=np.linspace(0,100000,10)
fig = plt.figure()
ax = Axes3D(fig)
ax.plot(x, y, z,'o', c='g')
ax.grid()
#ax.set_xscale('log')
#ax.set_zscale('log')
#ax.set_xlim([min(x), max(x)])
#ax.set_zlim([min(z), max(z)])
plt.show()

3D scatter_plot across 3D surface_plot

With the following code I try to plot a single scatter point over a 3D surface plot. But it is not working. Have tried Axes3D.text(x, y, z, s, zdir=None, **kwargs) instead of Axes3D.scatter(xs, ys, zs=0, zdir='z', s=20, c=None, depthshade=True,*args, **kwargs) which works. So I am curious why scatter is not working. What am I doing wrong?
Code
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from matplotlib import cm
from pylab import figure
from mpl_toolkits.mplot3d import Axes3D
fig = figure(figsize=(30,30))
ax = Axes3D(fig)
x=160+np.linspace(-100,100,100)
y=245+np.linspace(-100,100,100)
X,Y=np.meshgrid(x.round(0),y.round(0))
print(threshold1)
Z=Y-X
ax.plot_surface(X,Y,Z,cmap=cm.coolwarm,linewidth=3)
ax.scatter(160,245,85,s=400,c="b")
ax.tick_params(labelsize=35,direction='out', length=6, width=2)
plt.show()
Figure

How do you scale a polygon patch in matplotlib?

In the example below, I create a rectangular patch using matplotlib.patches.Polygon. Is there a way to scale the patch before adding it to the plot?
I've tried using matplotlib.transforms.Affine2D in a variety of ways with no success. As usual, the matplotlib documentation on transformations is woefully insufficient.
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot([-3,3],[-3,3])
x = [-1,0,1,1,0,-1]
y = [1,1,1,-1,-1,-1]
poly = Polygon( zip(x,y), facecolor='red', edgecolor='red', alpha=0.5)
ax.add_patch(poly)
plt.show()
If by scale you mean multiplication by a factor, you can easily do this via numpy.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot([-3,3],[-3,3])
x = [-1,0,1,1,0,-1]
y = [1,1,1,-1,-1,-1]
scale = 2
poly = Polygon( np.c_[x,y]*scale, facecolor='red', edgecolor='red', alpha=0.5)
ax.add_patch(poly)
plt.show()
The same can be achieved with a matplotlib.transforms.Affine2D() transform.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import matplotlib.transforms as transforms
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot([-3,3],[-3,3])
x = [-1,0,1,1,0,-1]
y = [1,1,1,-1,-1,-1]
trans = transforms.Affine2D().scale(2) + ax.transData
poly = Polygon( np.c_[x,y], facecolor='red', edgecolor='red', alpha=0.5,
transform=trans)
ax.add_patch(poly)
plt.show()
Although it seems a bit overkill for a simple scaling like this.

Plot serial port 3d points data on 3d coordinate system using python

I have searched for this in google, but found solutions for 2d points in real time.How can I achieve this for stream of 3d point.
Here I should be able to add new points to plot.
I tried this, its just plots series of data. How to update?
You could just plot in interactive mode, for example the following keeps adding new points,
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plt.ion()
plt.show()
x = np.linspace(0.,np.pi*4.,100)
ax.set_xlim([0.,13.])
ax.set_ylim([-1.5,1.5])
ax.set_zlim([-1.5,1.5])
for i in x:
ax.scatter(i, np.sin(i), np.cos(i))
print(i)
plt.pause(0.01)
UPDATE: added example of labelling
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plt.ion()
plt.show()
lsp = np.linspace(0.,np.pi*4.,100)
ax.set_xlim([0.,13.])
ax.set_ylim([-1.5,1.5])
ax.set_zlim([-1.5,1.5])
for i, x in enumerate(lsp):
y = np.sin(x)
z = np.cos(x)
ax.scatter(x, y, z)
if i%10 == 0:
ax.text(x, y, z, str(np.round(x,3))+", "
+str(np.round(y,3))+", "
+str(np.round(z,3)))
plt.pause(0.01)

End ticks in colorbar - matplotlib

I am trying to plot a colorbar in Python using the matplotlib libraries. The plot works well, but the color bar wont show the end ticks on the color bar.
Using the following command plots the colorbar properly, but I only have ticks ranging from -1.6 to +1.6 ( the top and bottom ticks are absent). The range of my data is from -2 to +2.
fig.colorbar(surf, shrink=1, aspect=12)
This is seen in the following figure:
I tried using the command:
cbar.set_ticks([-2,-1,0,1,2]);
But that also failed to get the correct result.
UPDATE:
I tried using the ticks=[-2,0,2] parameter, but that did not work as well. This is a snippet of my plotting code:
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')
CHI = np.linspace(-45, 45, 35);
M = np.linspace(0, 1, 35)
CHI, M = np.meshgrid(CHI, M)
R = 2*M*np.sin( 2 * np.deg2rad(CHI) )
surf = ax.plot_surface(CHI, M, R, rstride=1, cstride=1, cmap=cm.hsv,linewidth=0, antialiased=False)
ax.set_xlim(-45,45)
cbar = plt.colorbar(surf, shrink=1, aspect=12, ticks=[-2,-1,0,1,2])
plt.show()
This produces the following plot:
As seen, the colorbar lacks the end ticks, viz. -2 and 2
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')
CHI = np.linspace(-45, 45, 35);
M = np.linspace(0, 1, 35)
CHI, M = np.meshgrid(CHI, M)
R = 2*M*np.sin( 2 * np.deg2rad(CHI) )
surf = ax.plot_surface(CHI, M, R, rstride=1, cstride=1, cmap=cm.hsv,linewidth=0, antialiased=False)
surf.set_clim([-2, 2]) # <- this is the important line
ax.set_xlim(-45,45)
cbar = plt.colorbar(surf, shrink=1, aspect=12, ticks=[-2,-1,0,1,2])
plt.show()
Something is going wrong with the auto-scaling (I would guess issues with floating point equality tests), if you explicitly set the clim to [-2, 2] it works.
You should be able to set the ticks parameter when calling plt.colorbar:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
cmap = plt.get_cmap('jet')
data = np.random.randint(-2,3, size=(10,10))
im = ax.imshow(data, interpolation='nearest', cmap=cmap)
cbar = plt.colorbar(im, ticks=[-2,-1,0,1,2])
plt.show()

Categories

Resources