End ticks in colorbar - matplotlib - python

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()

Related

3D plotting in Python - Adding a Legend to Scatterplot

from mpl_toolkits.mplot3d import Axes3D
ax.scatter(X_lda[:,0], X_lda[:,1], X_lda[:,2], alpha=0.4, c=y_train, cmap='rainbow', s=20)
plt.legend()
plt.show()
Essentially I'd like to add a legend for the scatterplot that shows the unique values in y_train and what color point it corresponds to on the plot.
The output plot:
Producing either a legend or a colorbar for a scatter is usually quite simple:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
x,y,z = (np.random.normal(size=(300,4))+np.array([0,2,4,6])).reshape(3,400)
c = np.tile([1,2,3,4], 100)
fig, ax = plt.subplots(subplot_kw=dict(projection="3d"))
sc = ax.scatter(x,y,z, alpha=0.4, c=c, cmap='rainbow', s=20)
plt.legend(*sc.legend_elements())
plt.colorbar(sc)
plt.show()

Creating a graph with 2 planes and colormaps via Python

I have two 2D arrays and I want to use to produce an image similar to the one that fallows, just with different limits on the axis.
Here is my attempt so far:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(-2.01, 2.01)
ax.set_ylim(-2.01, 2.01)
ax.set_zlim(-2.01, 2.01)
cmap = plt.cm.gray
im = ax.imshow(np.asarray(array1), cmap=cmap)
im.remove()
fig.colorbar(im)
plt.show()
The arrays I have, (array1 and array2) are two dimensional with sizes n by n. Any help or a point in the right direction will be greatly appreciated!
With help of Matplotlib - Plot a plane and points in 3D simultaneously, I am able to achieve this:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
ax.set_xticks([0, 0.2, 0.4, 0.6, 0.8, 1])
ax.set_yticks([0, 0.5, 1])
ax.set_zticks([0, 0.2, 0.4, 0.6, 0.8, 1])
cmap = plt.cm.gray
#plot vertical surface
y = 0.5
xx, zz = np.meshgrid(np.linspace(0,1,10), np.linspace(0,1,10))
p = ax.plot_surface(xx, y, zz, cmap=cmap, alpha=0.5)
x = 0.2
yy, zz = np.meshgrid(np.linspace(0,1,10), np.linspace(0,1,10))
p = ax.plot_surface(x, yy, zz, cmap=cmap, alpha=0.5)
fig.colorbar(p)
plt.show()
Note that I didn't use normal or dot just as another question do, because here you want to plot vertical planes.
Here's what I got(I'm working on the right occlusion):

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.

Matplotlib: Add colorbar to non-mappable object

I have a series of lines representing the change of a variable; each with a unique color. For that reason I want to add a colorbar next to the plot. The desired output is shown below.
The problem is that plot is a non-mappable object, i.e. the colorbar has to be added manually. I consider my current solution (below) sub-optimal as it involves size parameters of which I have no interest in controlling. I'd prefer a similar solution as for a mappable object (example below current solution).
Desired output
Current solution
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
x = np.linspace(0, 5, 100)
N = 20
cmap = plt.get_cmap('jet',N)
fig = plt.figure(figsize=(8,6))
ax1 = fig.add_axes([0.10,0.10,0.70,0.85])
for i,n in enumerate(np.linspace(0,2,N)):
y = np.sin(x)*x**n
ax1.plot(x,y,c=cmap(i))
plt.xlabel('x')
plt.ylabel('y')
ax2 = fig.add_axes([0.85,0.10,0.05,0.85])
norm = mpl.colors.Normalize(vmin=0,vmax=2)
cb1 = mpl.colorbar.ColorbarBase(ax2,cmap=cmap,norm=norm,orientation='vertical')
plt.show()
Desired solution
(obviously replacing imshow)
fig,ax = plt.subplots()
cax = ax.imshow(..)
cbar = fig.colorbar(cax,aspect=10)
plt.show()
You may define your own ScalarMappable and use it just as if it was present in the plot.
(Note that I changed the numbero f colors to 21 to have nice spacings of 0.1)
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
x = np.linspace(0, 5, 100)
N = 21
cmap = plt.get_cmap('jet',N)
fig = plt.figure(figsize=(8,6))
ax1 = fig.add_axes([0.10,0.10,0.70,0.85])
for i,n in enumerate(np.linspace(0,2,N)):
y = np.sin(x)*x**n
ax1.plot(x,y,c=cmap(i))
plt.xlabel('x')
plt.ylabel('y')
norm = mpl.colors.Normalize(vmin=0,vmax=2)
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
plt.colorbar(sm, ticks=np.linspace(0,2,N),
boundaries=np.arange(-0.05,2.1,.1))
plt.show()

matplotlib 3D ribbon plot

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()

Categories

Resources