Hi I a have a data set which I project onto a sphere such that the magnitude of the data, as a function of theta and phi, is shown using a colour spectrum (which uses "ax.plot_surface", "plt.colorbar" and "facecolors"). My query is that at this stage I am limited to "cm.hot" and "cm.jet". Does anyone know of any other colour schemes which are available for this purpose. Please see my code and the figures below
Code:
from numpy import*
import math
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.cm as cm
#theta inclination angle
#phi azimuthal angle
n_theta = 100 #number of values for theta
n_phi = 100 #number of values for phi
r = 1 #radius of sphere
theta, phi = np.mgrid[0: pi:n_theta*1j,-pi:pi:n_phi*1j ]
x = r*np.sin(theta)*np.cos(phi)
y = r*np.sin(theta)*np.sin(phi)
z = r*np.cos(theta)
inp = []
f = open("data.dat","r")
for line in f:
i = float(line.split()[0])
j = float(line.split()[1])
val = float(line.split()[2])
inp.append([i, j, val])
inp = np.array(inp)
#reshape the input array to the shape of the x,y,z arrays.
c = inp[:,2].reshape((n_phi,n_theta))
#Set colours and render
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
#use facecolors argument, provide array of same shape as z
# cm.<cmapname>() allows to get rgba color from array.
# array must be normalized between 0 and 1
surf = ax.plot_surface(
x,y,z, rstride=1, cstride=1, facecolors=cm.jet(c), alpha=0.9, linewidth=1, shade=False)
ax.set_xlim([-2.0,2.0])
ax.set_ylim([-2.0,2.0])
ax.set_zlim([-2,2])
ax.set_aspect("equal")
plt.title('Plot with cm.jet')
#Label axis.
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
#Creates array for colorbar from 0 to 1.
a = array( [1.0, 0.5, 0.0])
#Creates colorbar
m = cm.ScalarMappable(cmap=cm.jet)
m.set_array(a)
plt.colorbar(m)
plt.savefig('facecolor plots')
f.close()
plt.show()
The following is a list of colormaps provided directly by matplotlib. It's taken from the Colormap reference example.
cmaps = [('Perceptually Uniform Sequential', [
'viridis', 'plasma', 'inferno', 'magma', 'cividis']),
('Sequential', [
'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']),
('Sequential (2)', [
'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia',
'hot', 'afmhot', 'gist_heat', 'copper']),
('Diverging', [
'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu',
'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']),
('Qualitative', [
'Pastel1', 'Pastel2', 'Paired', 'Accent',
'Dark2', 'Set1', 'Set2', 'Set3',
'tab10', 'tab20', 'tab20b', 'tab20c']),
('Miscellaneous', [
'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern',
'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg', 'hsv',
'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar'])]
To easily view them all you may e.g. use the following 3D colormap viewer (written in PyQt5).
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from PyQt5 import QtGui, QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import sys
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.main_widget = QtWidgets.QWidget(self)
self.fig = Figure()
self.canvas = FigureCanvas(self.fig)
self.ax = self.fig.add_subplot(111, projection=Axes3D.name)
u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)
x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))
# Plot the surface
self.surf = self.ax.plot_surface(x, y, z, cmap="YlGnBu")
self.cb = self.fig.colorbar(self.surf)
self.canvas.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Expanding)
self.canvas.updateGeometry()
self.dropdown1 = QtWidgets.QComboBox()
items = []
for cats in cmaps:
items.extend(cats[1])
self.dropdown1.addItems(items)
self.dropdown1.currentIndexChanged.connect(self.update)
self.label = QtWidgets.QLabel("A plot:")
self.layout = QtWidgets.QGridLayout(self.main_widget)
self.layout.addWidget(QtWidgets.QLabel("Select Colormap"))
self.layout.addWidget(self.dropdown1)
self.layout.addWidget(self.canvas)
self.setCentralWidget(self.main_widget)
self.show()
self.update()
def update(self):
self.surf.set_cmap(self.dropdown1.currentText())
self.fig.canvas.draw_idle()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec_())
Related
I have some x and y data, with which I would like to generate a 3D histogram, with a color gradient (bwr or whatever).
I have written a script which plot the interesting values, in between -2 and 2 for both x and y abscesses:
import numpy as np
import numpy.random
import matplotlib.pyplot as plt
# To generate some test data
x = np.random.randn(500)
y = np.random.randn(500)
XY = np.stack((x,y),axis=-1)
def selection(XY, limitXY=[[-2,+2],[-2,+2]]):
XY_select = []
for elt in XY:
if elt[0] > limitXY[0][0] and elt[0] < limitXY[0][1] and elt[1] > limitXY[1][0] and elt[1] < limitXY[1][1]:
XY_select.append(elt)
return np.array(XY_select)
XY_select = selection(XY, limitXY=[[-2,+2],[-2,+2]])
heatmap, xedges, yedges = np.histogram2d(XY_select[:,0], XY_select[:,1], bins = 7, range = [[-2,2],[-2,2]])
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
plt.figure("Histogram")
#plt.clf()
plt.imshow(heatmap.T, extent=extent, origin='lower')
plt.show()
And give this correct result:
Now, I would like to turn this into a 3D histogram. Unfortunatly I don't success to plot it correctly with bar3d because it takes by default the length of x and y for abscisse.
I am quite sure that there is a very easy way to plot this in 3D with imshow. Like an unknow option...
I finaly succeded in doing it. I am almost sure there is a better way to do it, but at leat it works:
import numpy as np
import numpy.random
import matplotlib.pyplot as plt
# To generate some test data
x = np.random.randn(500)
y = np.random.randn(500)
XY = np.stack((x,y),axis=-1)
def selection(XY, limitXY=[[-2,+2],[-2,+2]]):
XY_select = []
for elt in XY:
if elt[0] > limitXY[0][0] and elt[0] < limitXY[0][1] and elt[1] > limitXY[1][0] and elt[1] < limitXY[1][1]:
XY_select.append(elt)
return np.array(XY_select)
XY_select = selection(XY, limitXY=[[-2,+2],[-2,+2]])
xAmplitudes = np.array(XY_select)[:,0]#your data here
yAmplitudes = np.array(XY_select)[:,1]#your other data here
fig = plt.figure() #create a canvas, tell matplotlib it's 3d
ax = fig.add_subplot(111, projection='3d')
hist, xedges, yedges = np.histogram2d(x, y, bins=(7,7), range = [[-2,+2],[-2,+2]]) # you can change your bins, and the range on which to take data
# hist is a 7X7 matrix, with the populations for each of the subspace parts.
xpos, ypos = np.meshgrid(xedges[:-1]+xedges[1:], yedges[:-1]+yedges[1:]) -(xedges[1]-xedges[0])
xpos = xpos.flatten()*1./2
ypos = ypos.flatten()*1./2
zpos = np.zeros_like (xpos)
dx = xedges [1] - xedges [0]
dy = yedges [1] - yedges [0]
dz = hist.flatten()
cmap = cm.get_cmap('jet') # Get desired colormap - you can change this!
max_height = np.max(dz) # get range of colorbars so we can normalize
min_height = np.min(dz)
# scale each z to [0,1], and get their rgb values
rgba = [cmap((k-min_height)/max_height) for k in dz]
ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color=rgba, zsort='average')
plt.title("X vs. Y Amplitudes for ____ Data")
plt.xlabel("My X data source")
plt.ylabel("My Y data source")
plt.savefig("Your_title_goes_here")
plt.show()
I use this example, but I modified it, because it introduced an offset. The result is this:
You can generate the same result using something as simple as the following:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-2, 2, 7)
y = np.linspace(-2, 2, 7)
xx, yy = np.meshgrid(x, y)
z = xx*0+yy*0+ np.random.random(size=[7,7])
plt.imshow(z, interpolation='nearest', cmap=plt.cm.viridis, extent=[-2,2,2,2])
plt.show()
from mpl_toolkits.mplot3d import Axes3D
ax = Axes3D(plt.figure())
ax.plot_surface(xx, yy, z, cmap=plt.cm.viridis, cstride=1, rstride=1)
plt.show()
The results are given below:
from __future__ import division
import numpy as np
import math
from scipy.special import kv #calling bassel func
from scipy.special import iv #calling bassel func
from scipy.integrate import quad
from scipy.misc import derivative
import matplotlib.pylab as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
#######################################################
def B(x):
#bassel func~~~~~
#first
v0 = 0 #order of bessel func
K0 = kv(v0, r/x) #BESSEL Function
I0 = iv(v0, r/x) #BESSEL Function
#~~~second
v1 = 1 #order of bessel func
K1 = kv(v1, r/x) #BESSEL Function
I1 = iv(v1, r/x) #BESSEL Function
c = (I0*K0)-(I1*K1)
return c
#######################################################
Ms = 3e+11
ms1 = 1e11
#~~~~~~~~~~~~~~~~~~
mh = np.linspace(9.5,11.5,20)
mhalo = 10**((-0.0210331*mh**5) + (1.042316*mh**4) - (20.553*mh**3) + (201.74*mh**2) - (985.821*mh) + (1929.48))
Mh = mhalo
#~ r = 6 #in Kpc
r = np.linspace(0.01,6,20) #in Kpc
#~~~~~~~~~~~~~~~~~~
#virial radius:
Rv = 259.3*(Mh/1e12)**(1/3)
#Disk mass halo mass relation:
Md = 2.3e10*(Mh/Ms)**(3.1)/(1+(Mh/Ms)**(2.2))
#disk length to halo mass relation:
Rd = 10**(0.633+(0.379*np.log10(Md/ms1)) + (0.069*(np.log10(Md/ms1))**2))
#optical radius:
Ropt = 3.2*Rd
#Burkert-halo central density:
rho0 = 10**(-23.5153 - 0.918*(Md/ms1)**(0.308))
#burket core radius:
r0 = 10**(0.66+0.58*(np.log10(Mh/ms1)))
#burket halo density:
rho = rho0*r0**3/((r+r0)*((r**2)+(r0**2)))
#burket Halo mass:
Mhr = (1.48e31*1.6*4*rho0*r0**3)*(np.log(1+(r/r0))- np.arctan(r/r0) + 0.5*(np.log(1+(r/r0)**2)))
#Halo velocity:
Vh = 658.1*(Mhr/(ms1*r))**0.5
#disk velocity:
x = 2*Rd
Vd = 658.1*((0.5*Md/(ms1*Rd))**0.5)*(r/Rd)*B(x)**0.5
#total velocity:
vurc = ((Vd**2) + (Vh**2))**0.5
XX = r
YY = vurc
ZZ = mh
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
img = ax.plot_surface(XX, YY, ZZ)
plt.tick_params(axis='x', which='major', labelsize=15)
plt.tick_params(axis='y', which='major', labelsize=15)
plt.tick_params(axis='z', which='major', labelsize=15)
ax.set_xlabel('R/Ropt', fontsize = 15)
ax.set_ylabel('V/Vopt', fontsize = 15)
ax.set_zlabel('log(M_vir)', fontsize = 15)
plt.show()
In this code below, 3D plotting commands are not working neither giving any errors, just plotting the empty box. While, my all arrays are of same size. Could anyone hlep me out.
i plotted a density map with histograme2d and pcolomesh using a csv file containning lat/lon.
Now i want to turn the histogram2d output into contours matplotlib.
my code is as shown below:
import csv
import numpy as np
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
lats, lons = [], []
with open('fou.csv') as f:
reader = csv.reader(f)
next(reader) # Ignore the header row.
lonMin, lonMax, dLon = -20.0, 5.0, 5
latMin, latMax, dLat = 18.0, 40.0, 5
for row in reader:
lat = float(row[2])
lon = float(row[3])
# filter lat,lons to (approximate) map view:
if lonMin <= lon <= lonMax and latMin <= lat <= latMax:
lats.append( lat )
lons.append( lon )
m = Basemap(llcrnrlon=lonMin, llcrnrlat=latMin, urcrnrlon=lonMax, urcrnrlat=latMax, projection='merc', resolution='f')
m.drawcoastlines()
m.drawcountries()
m.drawstates()
db = 1 # bin padding
lon_bins = np.linspace(min(lons)-db, max(lons)+db, 100) # 10 bins
lat_bins = np.linspace(min(lats)-db, max(lats)+db, 100) # 13 bins
density, xbins, ybins =(np.histogram2d(lats, lons, [lat_bins, lon_bins]))
plt.contourf(density.transpose(),extent=[xbins[0],xbins[-1],ybins[0],ybins[-1]],levels = [1,5,10,25,50,70,80,100])
cbar = plt.colorbar(orientation='horizontal', shrink=0.625, aspect=20, fraction=0.2,pad=0.02)
cbar.set_label('the keraunic level density',size=18)
plt.gcf().set_size_inches(15,15)
plt.show()
what am I missing ?
I am new to Matplotlib. Based on my code in following, I wanted to update the data,title,xlabel,ylabel at same time. However, the title and labels did not been updated, but data did.Someone can give me a solution? That will help me a lot.Thank you.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def updata(frame_number):
current_index = frame_number % 3
a = [[1,2,3],[4,5,6],[7,8,9]]
idata['position'][:,0] = np.asarray(a[current_index])
idata['position'][:,1] = np.asarray(a[current_index])
scat.set_offsets(idata['position'])
ax.set_xlabel('The Intensity of Image1')
ax.set_ylabel('The Intensity of Image2')
ax.set_title("For Dataset %d" % current_index)
fig = plt.figure(figsize=(5,5))
ax = fig.add_axes([0,0,1,1])
idata = np.zeros(3,dtype=[('position',float,2)])
ax.set_title(label='lets begin',fontdict = {'fontsize':12},loc='center')
scat = ax.scatter(idata['position'][:,0],idata['position'][:,1],s=10,alpha=0.3,edgecolors='none')
animation = FuncAnimation(fig,updata,interval=2000)
plt.show()
Running the code, I see an empty window. The reason is that the axes span the complete figure (fig.add_axes([0,0,1,1])). In order to see the title and labels, you would need to make the axes smaller than the figure, e.g. by
ax = fig.add_subplot(111)
Also, the scale of the axes is not defined, so the animation will happen outside the axes limits. You can use ax.set_xlim and ax.set_ylim to prevent that.
Here is a complete running code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def updata(frame_number):
current_index = frame_number % 3
a = [[1,2,3],[4,5,6],[7,8,9]]
idata['position'][:,0] = np.asarray(a[current_index])
idata['position'][:,1] = np.asarray(a[current_index])
scat.set_offsets(idata['position'])
ax.set_xlabel('The Intensity of Image1')
ax.set_ylabel('The Intensity of Image2')
ax.set_title("For Dataset %d" % current_index)
fig = plt.figure(figsize=(5,5))
ax = fig.add_subplot(111)
idata = np.zeros(3,dtype=[('position',float,2)])
ax.set_title(label='lets begin',fontdict = {'fontsize':12},loc='center')
scat = ax.scatter(idata['position'][:,0],idata['position'][:,1],
s=25,alpha=0.9,edgecolors='none')
ax.set_xlim(0,10)
ax.set_ylim(0,10)
animation = FuncAnimation(fig,updata,frames=50,interval=600)
plt.show()
I have the following code to create a 3D plot of a Bivariate Gaussian Distribution:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
class Data(object):
data = None
columns = 0
rows = 0
def __init__(self, path='file.txt'):
self.data = np.loadtxt(path, delimiter=' ', dtype='float32')
self.rows, self.columns = self.data.shape
def _pdf(self, x, mu, cov):
part1 = 1 / ( ((2* np.pi)**(len(mu)/2)) * (np.linalg.det(cov)**(1/2)) )
part2 = (-1/2) * ((x-mu).T.dot(np.linalg.inv(cov))).dot((x-mu))
return float(part1 * np.exp(part2))
def compute_Z(self):
mu = np.array([[2.99413181],[3.05209659]], dtype="float")
cov = np.array([[1.01023423, 0.02719138], [0.02719138, 2.93782296]], dtype="float")
Z = []
for i, j in zip(X, Y):
x = np.array([i,j]).reshape(2,1)
Z.append(self._pdf(x, mu, cov))
return np.array(Z)
if __name__ == "__main__":
data = Data()
X = data.data[:, 0]
Y = data.data[:, 1]
Z = data.compute_Z()
X, Y = np.meshgrid(X, Y)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, color='0.9', alpha=0.9, linewidth=1)
plt.show()
But this is taking a lot of time and also using a lot of RAM. Is there some way to reduce it? Or there is a better method to create this plot?
Thanks!
matplotlib 3D plotting isn't very good for large amount of data.
You can use mayavi, which has very similar interface using mlab.
from mayavi import mlab
mlab.figure()
mlab.surf(X, Y, Z)
mlab.show()