So I've seen examples where you have two 1D arrays and use a meshgrid then just use the two values from that and your z array to create the contour. But I have 3 inherently 2D arrays that I need for a contour, but so far this is what is being displayed. Any ideas? (Ignore the dummy variable names) Photo and code as listed:enter image description here
fig = plt.figure(figsize=(16,16))
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
contourOne = ax1.contourf(data,data2, np.log(data3))
ax1.set_title("title")
ax1.set_xlabel("idk")
ax1.set_ylabel("idk")
divider = make_axes_locatable(ax1)
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(contourOne, cax=cax, orientation='vertical')
contourTwo = ax2.contourf(data4,data5, np.log(data6))
ax2.set_title("title")
ax2.set_xlabel("idk")
ax2.set_ylabel("idk")
divider = make_axes_locatable(ax2)
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(contourTwo, cax=cax, orientation='vertical')
#Set graph spacing and show graphs
plt.subplots_adjust(wspace=0.4,hspace=0.5)
plt.show()
Related
I would like to set some space between the image and the colorbar, I have tried the pad but do nothing, so...
This is the image I have:
and this is the code:
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.colors import LogNorm
from matplotlib.ticker import LogLocator
from matplotlib import rcParams
rcParams['font.size']=35
x = np.arange(0,16,1)
yx= np.linspace(-50,0,38)
mx = np.random.rand(15,38)
m2 = np.linspace(0,6,38)
fig, ax = plt.subplots(figsize=(40,30))
divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad=2)
im = ax.pcolor(x,yx,mx.T,norm=LogNorm(0.1, 100),cmap= 'jet')
cbar = fig.colorbar(im,pad = 2,cax=cax, orientation='vertical')
cbar.ax.yaxis.set_major_locator(LogLocator()) # <- Why? See above.
cbar.ax.set_ylabel('Resistividade \u03C1 [ohm.m]', rotation=270)
ax2=ax.twiny()
ax2.plot(m2,yx,'k--',linewidth=10)
#ax2.set_xlim([0,60])
ax2.set_xlabel('Resistividade \u03C1 [ohm.m]')
ax.set_xlabel('Aquisição')
ax.set_ylabel('Profundidade [m]')
#fig.tight_layout()
plt.savefig('mrec_1'+'.png',bbox_inches = "tight", format='png', dpi=300)
plt.show()
The secondary axes occupies all of the space in the figure that is meant for axes. Therefore, no matter what padding you give to the colorbar of ax, it wont affect ax2.
A hacky-ish solution would be to also spit your secondary axes exactly the same as the primary axes, and then delete the axes where the second colorbar goes:
fig, ax = plt.subplots(figsize=(10, 8))
pad = 0.2 # change the padding. Will affect both axes
im = ax.pcolor(x, yx, mx.T, norm=LogNorm(0.1, 100), cmap='jet')
divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad=pad)
ax2 = ax.twiny()
ax2.plot(m2, yx, 'k--', linewidth=10)
ax2.set_xlim([0, 60])
ax2.set_xlabel('Resistividade \u03C1 [ohm.m]')
ax.set_xlabel('Aquisição')
ax.set_ylabel('Profundidade [m]')
cbar = fig.colorbar(im,pad = 2,cax=cax, orientation='vertical')
cbar.ax.yaxis.set_major_locator(LogLocator())
cbar.ax.set_ylabel('Resistividade \u03C1 [ohm.m]', rotation=270)
secondary_divider = make_axes_locatable(ax2) # divide second axes
redundant_cax = secondary_divider.append_axes('right', size='5%', pad=pad)
redundant_cax.remove() # delete the second (empty) colorbar
plt.show()
I'm trying to get a colorbar for an image, which is supposed to have the same height as the image. There are many solutions suggested here, but none of them work for an image which has an aspect ratio smaller than 1.
If you use the accepted answer from the linked question like this...
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
plt.figure()
ax = plt.gca()
im = ax.imshow(np.arange(100).reshape((10,10)), aspect = 0.4375)
# create an axes on the right side of ax. The width of cax will be 5%
# of ax and the padding between cax and ax will be fixed at 0.05 inch.
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
plt.colorbar(im, cax=cax)
plt.savefig("asdf.png", bbox_inches = "tight")
... (Note the aspect in imshow call!), I get this:
Leaving aspect out, it works just fine, but for my data, I need to set the aspect ratio, as the step size for the x-axis is much larger than for the y-axis.
Other solutions, like plt.colorbar(im,fraction=0.046, pad=0.04) or adding a seperate axis don't work either and produce similiar results.
How do I get the colorbar to have the same height in this case?
I finally found a solution here:
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
...
fig, ax = plt.subplots(1, 1)
im = ax.imshow(data, aspect = aspectRatio)
axins = inset_axes(ax, width = "5%", height = "100%", loc = 'lower left',
bbox_to_anchor = (1.02, 0., 1, 1), bbox_transform = ax.transAxes,
borderpad = 0)
fig.colorbar(im, cax = axins)
... where data is your array of values and 1.02 is the padding between the figure and the colorbar.
This creates colorbars with perfect height, regardless of the aspect ratio. No fiddling with magic numbers or anything of that sort.
After a bit of exploration, this works:
plt.figure()
ax = plt.gca()
im = ax.imshow(np.arange(100).reshape((10,10)))
# create an axes on the right side of ax. The width of cax will be 5%
# of ax and the padding between cax and ax will be fixed at 0.05 inch.
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
plt.colorbar(im, cax=cax)
ax.set_aspect(0.4375)
cax.set_aspect(8.75)
plt.savefig("asdf.png", bbox_inches = "tight")
Adding the .set_aspect() works. You may need to tweak the parameters. The result is:
For more information, see this.
I'm plotting a 2D temperature array over a world map, using Basemap. All works fine, except for the colorbar, that I want to fix within a certain range Tmin-Tmax. Unfortunately, vmin and vmax that I use for matplotlib, here seem not to work and I wasn't able to find the right keywords (if any) used for this purpose. Any suggestion? Thanks.
fig = plt.figure(figsize=(20,10))
map = Basemap(projection='cyl', lat_0 = 57, lon_0 = -135, resolution = RES, area_thresh = 0.1, llcrnrlon=-180., llcrnrlat=-90., urcrnrlon=180., urcrnrlat=90.)
map.drawcoastlines()
map.drawcountries()
map.drawparallels(np.arange(-90,90,15),labels=[1,1,0,1])
map.drawmeridians(np.arange(-180,180,15),labels=[1,1,0,1])
map.drawmapboundary()
map.imshow(IR1)
cbar = map.colorbar(location='right', pad="5%")
cbar.set_label('T [Celsius]')
plt.title("temperature")
plt.savefig("temperature.png")
Here I give an idea by using np.ma.masked. Any advice on my work would be appreciate.
I use an netcdf file and read the temperature of the whole area. This is similar with your job.
Before setting vmin and vmax
### Read the file
wrf_file1 = "wrf_201401.nc"
t_m1 = gdal.Open('NETCDF:"'+wrf_file1+'":T2')
lon = gdal.Open('NETCDF:"'+wrf_file1+'":XLONG')
lat = gdal.Open('NETCDF:"'+wrf_file1+'":XLAT')
### plot
fig =plt.figure(figsize=(6,4))
ax = plt.subplot()
map = basemap(llcrnrlon=xxx,llcrnrlat=xxx,urcrnrlon=xxx,urcrnrlat=xxx)
x, y = map(lon.ReadAsArray()[362], lat.ReadAsArray()[362])
t = t_m1.ReadAsArray()[30,:,:] ### select one dataframe
cf = map.pcolormesh(x, y,t,cmap=plt.cm.Spectral_r,alpha = 0.8)
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="3%", pad=0.4)
cbar = plt.colorbar(cf, cax=cax)
plt.show()
The colorbar represent that the temperature were range from 268.5 to 281.
If I want to plot the area which temperature were range from 270 to 275. Here is my solution.
Improvement
fig =plt.figure(figsize=(6,4))
ax = plt.subplot()
t = t_m1.ReadAsArray()[30,:,:]
t_mask_1 = np.ma.masked_greater(t,275)
t_mask_2 = np.ma.masked_less(t_mask_1,270)
cf = map.pcolormesh(x, y,t_mask_2,cmap=plt.cm.Spectral_r,alpha = 0.8)
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="3%", pad=0.4)
cbar = plt.colorbar(cf, cax=cax)
plt.show()
Does anyone have a matplotlib example of two plots sharing the y-axis (with no space between the plots) with a single color bar pertaining to both subplots? I have not been able to find examples of this yet.
I created the following code based on your question. Personally I do not like it to have no space between the subplots at all. If you do want to change this at some point all you need to do is to replace plt.subplots_adjust(wspace = -.059) with plt.tight_layout().
Hope this helps
import numpy
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
#Random data
data = numpy.random.random((10, 10))
fig = plt.figure()
ax1 = fig.add_subplot(1,2,1, aspect = "equal")
ax2 = fig.add_subplot(1,2,2, aspect = "equal", sharey = ax1) #Share y-axes with subplot 1
#Set y-ticks of subplot 2 invisible
plt.setp(ax2.get_yticklabels(), visible=False)
#Plot data
im1 = ax1.pcolormesh(data)
im2 = ax2.pcolormesh(data)
#Define locations of colorbars for both subplot 1 and 2
divider1 = make_axes_locatable(ax1)
cax1 = divider1.append_axes("right", size="5%", pad=0.05)
divider2 = make_axes_locatable(ax2)
cax2 = divider2.append_axes("right", size="5%", pad=0.05)
#Create and remove the colorbar for the first subplot
cbar1 = fig.colorbar(im1, cax = cax1)
fig.delaxes(fig.axes[2])
#Create second colorbar
cbar2 = fig.colorbar(im2, cax = cax2)
#Adjust the widths between the subplots
plt.subplots_adjust(wspace = -.059)
plt.show()
The result is the following:
I have 8 plots that I want to compare with 8 different but corresponding plots. So I set up 8 subplots, then try to use axes_grid1.make_axes_locatable to divide the subplots. However, it appears that when I use the new_vertical function it returns something of the type matplotlib.axes.AxesSubplot.
Here's the code I have:
fig = plt.figure()
for i in range(7):
ax = fig.add_subplot(4,2,i+1)
idarray = ice_dict[i]
mdarray = model_dict[i]
side_by_side(ax, idarray, mdarray)
def side_by_side(ax1, idata, mdata):
from mpl_toolkits.axes_grid1 import make_axes_locatable
global mycmap
global ice_dict, titles
divider = make_axes_locatable(ax1)
ax2 = divider.new_vertical(size="100%", pad=0.05)
fig1 = ax1.get_figure()
fig1.add_axes(ax2)
cax1 = divider.append_axes("right", size = "5%", pad= 0.05)
plt.sca(ax1)
im1 = ax1.pcolor(idata, cmap = mycmap)
ax1.set_xlim(space.min(), space.max()+1)
ax1.set_ylim(0, len(idata))
plt.colorbar(im1, cax=cax1)
im2 = ax2.pcolor(mdata, cmap = mycmap)
ax2.set_xlim(space.min(), space.max()+1)
for tl in ax2.get_xticklabels():
tl.set_visible(False)
ax2.set_ylim(0, len(mdata))
ax2.invert_yaxis()
Which produces something like this, where ax2 is on top and ax1 is on bottom in each subplot:
I should probably mention that they're on a different scale so I cant just use the same colorbar for both. Thanks in advance.
tl;dr how can I get a colorbar on ax2, an AxesSubplot, as well as ax1, an Axes? Or is there a better way to get the same look?