Colorbars close to subplots - python

How can I put colorbars beside each colormap that is in a subplot? A simplified version of my real code is here that shows my problem. As you can see all the colorbars are at the bottom right and also are making the last plot smaller.
from matplotlib import pyplot as plt
import numpy as np
def plots():
fig,ax=plt.subplots(2,2)
for i in range(2):
rho_mat,C_mat=np.random.uniform(size=(50,50)),np.random.uniform(size=(50,50))
ax[0,i].set_title(r"$\rho_{X,Y}$")
p=ax[0,i].imshow(np.fliplr(rho_mat).T,extent=[0.,1,0.,1],vmin=0,vmax=1, interpolation='none')
ax[0,i].set_xlabel(r'$\epsilon_1$')
ax[0,i].set_ylabel(r'$\epsilon_2$')
fig.colorbar(p, shrink=0.5)
ax[1,i].set_title(r"$C_{X,Y}$")
p2=ax[1,i].imshow(np.fliplr(C_mat).T,extent=[0.,1,0.,1],vmin=0,vmax=1, interpolation='none')
ax[1,i].set_xlabel(r'$\epsilon_1$')
ax[1,i].set_ylabel(r'$\epsilon_2$')
fig.colorbar(p2, shrink=0.5)
plt.tight_layout()
plt.show()
plots()

The colorbar method has an optional keyword argument that allows you to specify the axes it is associated with.
In your code you could change the call to colorbar to something like this:
fig.colorbar(p, ax=ax[0,i], shrink=0.5)
fig.colorbar(p2, ax=ax[1,i], shrink=0.5)

Related

matplotlib last tick label still visible [duplicate]

I have a semilogx plot and I would like to remove the xticks. I tried:
plt.gca().set_xticks([])
plt.xticks([])
ax.set_xticks([])
The grid disappears (ok), but small ticks (at the place of the main ticks) remain. How to remove them?
The plt.tick_params method is very useful for stuff like this. This code turns off major and minor ticks and removes the labels from the x-axis.
Note that there is also ax.tick_params for matplotlib.axes.Axes objects.
from matplotlib import pyplot as plt
plt.plot(range(10))
plt.tick_params(
axis='x', # changes apply to the x-axis
which='both', # both major and minor ticks are affected
bottom=False, # ticks along the bottom edge are off
top=False, # ticks along the top edge are off
labelbottom=False) # labels along the bottom edge are off
plt.show()
plt.savefig('plot')
plt.clf()
Not exactly what the OP was asking for, but a simple way to disable all axes lines, ticks and labels is to simply call:
plt.axis('off')
Alternatively, you can pass an empty tick position and label as
# for matplotlib.pyplot
# ---------------------
plt.xticks([], [])
# for axis object
# ---------------
# from Anakhand May 5 at 13:08
# for major ticks
ax.set_xticks([])
# for minor ticks
ax.set_xticks([], minor=True)
Here is an alternative solution that I found on the matplotlib mailing list:
import matplotlib.pylab as plt
x = range(1000)
ax = plt.axes()
ax.semilogx(x, x)
ax.xaxis.set_ticks_position('none')
There is a better, and simpler, solution than the one given by John Vinyard. Use NullLocator:
import matplotlib.pyplot as plt
plt.plot(range(10))
plt.gca().xaxis.set_major_locator(plt.NullLocator())
plt.show()
plt.savefig('plot')
Try this to remove the labels (but not the ticks):
import matplotlib.pyplot as plt
plt.setp( ax.get_xticklabels(), visible=False)
example
This snippet might help in removing the xticks only.
from matplotlib import pyplot as plt
plt.xticks([])
This snippet might help in removing the xticks and yticks both.
from matplotlib import pyplot as plt
plt.xticks([]),plt.yticks([])
Those of you looking for a short command to switch off all ticks and labels should be fine with
plt.tick_params(top=False, bottom=False, left=False, right=False,
labelleft=False, labelbottom=False)
which allows type bool for respective parameters since version matplotlib>=2.1.1
For custom tick settings, the docs are helpful:
https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.tick_params.html
# remove all the ticks (both axes), and tick labels on the Y axis
plt.tick_params(top='off', bottom='off', left='off', right='off', labelleft='off', labelbottom='on')
Modify the following rc parameters by adding the commands to the script:
plt.rcParams['xtick.bottom'] = False
plt.rcParams['xtick.labelbottom'] = False
A sample matplotlibrc file is depicted in this section of the matplotlib documentation, which lists many other parameters like changing figure size, color of figure, animation settings, etc.
A simple solution to this problem is to set the color of the xticks to White or to whatever the background color is. This will hide the text of the xticks but not the xticks itself.
import matplotlib.pyplot as plt
plt.plot()
plt.xticks(color='white')
plt.show()
Result

Controlling legend across multiple subplots with windrose axes

I cannot figure out how to make the legends not overlap with my figures (see below figure) in subplots. The problem is my axes are complicated because they are from a windrose. To get the axes:
1) I have downloaded the windrose.py from https://github.com/akrherz/windrose/tree/darylchanges
2) I copied the windrose.py into the same path with my python script, example.py
3) I changed windrose.py so that it is able to do subplots, according to the steps from Subplot of Windrose in matplotlib . Those steps were to make WindroseAxes as a projection into matplotlib. I edited the file windrose.py:
3a) Include an
import from matplotlib.projections import register_projection
at the beginning of the file.
3b) Then add a name variable :
class WindroseAxes(PolarAxes):
name = 'windrose'
...
3c) Finally, at the end of windrose.py, you add:
register_projection(WindroseAxes)
Once that is done, you can easily create your windrose axes using the projection argument to the matplotlib axes.
4) Now I ran my script below (example of my real script)
from windrose import WindroseAxes
import numpy as np
import matplotlib.pyplot as plt
from windrose_subplot import WindroseAxes
wind_speeds1 = np.array([12,10,13,15])
wind_dirs1 = np.array([60,76,32,80]) # in degrees
wind_speeds2 = np.array([23,12,10,8])
wind_dirs2 = np.array([23,45,29,13])
fig = plt.figure()
ax1 = fig.add_subplot(231,projection='windrose')
ax1.bar(wind_dirs1,wind_speeds1,normed=True,opening=0.8,edgecolor='white')
ax2 = fig.add_subplot(232,projection='windrose')
ax2.bar(wind_dirs2,wind_speeds2,normed=True,opening=0.8,edgecolor='white')
ax1.legend()
ax2.legend()
plt.tight_layout()
plt.show()
Ideally, I would like to create one legend with the max/min of all the subplots because they are all the same units . This legend will have to be the corresponding colors for each subplot for the same values across subplots (eg, a single normal legend relevant to all subplots). There will be 6 subplots in the real script but 2 here for now shows the point.
This is simple to fix. In order to only plot one legend, comment out or delete where you plot the first legend. In order to move the legend off of the plot, use bbox_to_anchor=() with some logical location. See below for an example that works for this example.
import numpy as np
import matplotlib.pyplot as plt
from windrose_subplot import WindroseAxes
wind_speeds1 = np.array([12,10,13,15])
wind_dirs1 = np.array([60,76,32,80]) # in degrees
wind_speeds2 = np.array([23,12,10,8])
wind_dirs2 = np.array([23,45,29,13])
fig = plt.figure()
ax1 = fig.add_subplot(231,projection='windrose')
ax1.bar(wind_dirs1,wind_speeds1,normed=True,opening=0.8,edgecolor='white')
ax2 = fig.add_subplot(232,projection='windrose')
ax2.bar(wind_dirs2,wind_speeds2,normed=True,opening=0.8,edgecolor='white')
# ax1.legend()
ax2.legend(bbox_to_anchor=(1.2 , -0.1))
plt.tight_layout()
plt.show()
However, note the bbox_to_anchor is reliant on the axis that the legend comes from, so
ax1.legend(bbox_to_anchor=1.2, -0.1))
#ax2.legend()
would display the legend underneath the second axis:
Thank you Hazard11, I found your answer very useful :) There is an issue with the answer though is the legend does not represent the first subplot because the bins are generated when creating the second subplot.
I just solved this issue by calculating the bins using numpy.histogram first and then passing that to windrose.WindroseAxes.bar() when creating each wind rose. Doing it this way means you need to pick which one you want to use to generate the bins. Another way to do it would be to define the bins manually or to create a function which generates some efficient binning for both which could then be used.
wind_speeds1 = np.array([12,10,13,15])
wind_dirs1 = np.array([60,76,32,80]) # in degrees
wind_speeds2 = np.array([23,12,10,8])
wind_dirs2 = np.array([23,45,29,13])
wind_speeds_bins = np.histogram(wind_speeds2, 5)[1]
fig = plt.figure()
ax1 = fig.add_subplot(231, projection='windrose')
ax1.bar(wind_dirs1 ,wind_speeds1, normed=True, opening=0.8, edgecolor='white', bins=wind_speeds_bins)
ax2 = fig.add_subplot(232, projection='windrose')
ax2.bar(wind_dirs2, wind_speeds2, normed=True, opening=0.8, edgecolor='white', bins=wind_speeds_bins)
# ax1.legend()
ax2.legend(bbox_to_anchor=(1.2 , -0.1))
plt.tight_layout()
plt.show()

Adjust whitespace margins on animated Axes3D scatter plot (matplotlib)

I am using matplotlib 1.2.1 and am limited to that version for now. The problem I run into is the crowding of the axis labels and ticks in the bottom of the frame with this rotated plot. I have tried plt.adjust_subplots, I've tried tight_layout, changing the figure size, ax.dist and more but nothing seems to change the appearance as shown in the example image below. This is just one frame but often as the plot rotates, it goes out of frame at the bottom (especially when ticks and labels are bigger). Perhaps my problem is where I place the ax.dist argument?
How can I add a little more whitespace at the bottom of this animated plot? As a bonus, how can I get rid of the confusing double grid lines at the edges? Thank you.
import matplotlib as mpl
import matplotlib.pyplot as plt
plt.rcParams['animation.ffmpeg_path']='C:/FFMPEG/bin/ffmpeg.exe'
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D
def format_3d_ax(ax):
ax.w_xaxis.set_pane_color((1.0,1.0,1.0,1.0))
ax.w_yaxis.set_pane_color((1.0,1.0,1.0,1.0))
ax.w_zaxis.set_pane_color((1.0,1.0,1.0,1.0))
ax.w_xaxis._axinfo['grid'].update({'linewidth':0.25,'color':'black'})
ax.w_yaxis._axinfo['grid'].update({'linewidth':0.25,'color':'black'})
ax.w_zaxis._axinfo['grid'].update({'linewidth':0.25,'color':'black'})
def rotate(i,ax, angles, elev):
ax.view_init(elev,angles[i])
plt.draw()
return ax
def rotate_3d(fig,ax,angles,elev):
frames=len(angles)
ani=animation.FuncAnimation(fig,rotate, fargs=(ax,angles, elev),blit=True,
frames=frames, interval=200)
return ani
fig=plt.figure(figsize=(12,7.6))
ax=Axes3D(fig)
ax.view_init(elev=25, azim=0)
format_3d_ax(ax)
ax.set_xlabel('Reasonably sized x label')
ax.set_ylabel('Reasonably sized y label')
ax.set_zlabel('z label')
ax.scatter([1],[1],[1], marker='.', s=80)
ani=rotate_3d(fig,ax,range(0,45),25)
Writer=animation.writers['ffmpeg']
writer=Writer(fps=30, bitrate=2000)
ani.save('C:/Temp/test.mp4', writer=writer, dpi=300)
print ('Done') #helps to know when the writer is done.

x axis label disappearing in matplotlib and basic plotting in python

I am new to matplotlib, and I am finding it very confusing. I have spent quite a lot of time on the matplotlib tutorial website, but I still cannot really understand how to build a figure from scratch. To me, this means doing everything manually... not using the plt.plot() function, but always setting figure, axis handles.
Can anyone explain how to set up a figure from the ground up?
Right now, I have this code to generate a double y-axis plot. But my xlabels are disappearing and I dont' know why
fig, ax1 = plt.subplots()
ax1.plot(yearsTotal,timeseries_data1,'r-')
ax1.set_ylabel('Windspeed [m/s]')
ax1.tick_params('y',colors='r')
ax2 = ax1.twinx()
ax2.plot(yearsTotal,timeseries_data2,'b-')
ax2.set_xticks(np.arange(min(yearsTotal),max(yearsTotal)+1))
ax2.set_xticklabels(ax1.xaxis.get_majorticklabels(), rotation=90)
ax2.set_ylabel('Open water duration [days]')
ax2.tick_params('y',colors='b')
plt.title('My title')
fig.tight_layout()
plt.savefig('plots/my_figure.png',bbox_inches='tight')
plt.show()
Because you are using a twinx, it makes sense to operate only on the original axes (ax1).
Further, the ticklabels are not defined at the point where you call ax1.xaxis.get_majorticklabels().
If you want to set the ticks and ticklabels manually, you can use your own data to do so (although I wouldn't know why you'd prefer this over using the automatic labeling) by specifying a list or array
ticks = np.arange(min(yearsTotal),max(yearsTotal)+1)
ax1.set_xticks(ticks)
ax1.set_xticklabels(ticks)
Since the ticklabels are the same as the tickpositions here, you may also just do
ax1.set_xticks(np.arange(min(yearsTotal),max(yearsTotal)+1))
plt.setp(ax1.get_xticklabels(), rotation=70)
Complete example:
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)
yearsTotal = np.arange(1977, 1999)
timeseries_data1 = np.cumsum(np.random.normal(size=len(yearsTotal)))+5
timeseries_data2 = np.cumsum(np.random.normal(size=len(yearsTotal)))+20
fig, ax1 = plt.subplots()
ax1.plot(yearsTotal,timeseries_data1,'r-')
ax1.set_ylabel('Windspeed [m/s]')
ax1.tick_params('y',colors='r')
ax1.set_xticks(np.arange(min(yearsTotal),max(yearsTotal)+1))
plt.setp(ax1.get_xticklabels(), rotation=70)
ax2 = ax1.twinx()
ax2.plot(yearsTotal,timeseries_data2,'b-')
ax2.set_ylabel('Open water duration [days]')
ax2.tick_params('y',colors='b')
plt.title('My title')
fig.tight_layout()
plt.show()
Based on your code, it is not disappear, it is set (overwrite) by these two functions:
ax2.set_xticks(np.arange(min(yearsTotal),max(yearsTotal)+1))
ax2.set_xticklabels(ax1.xaxis.get_majorticklabels(), rotation=90)
set_xticks() on the axes will set the locations and set_xticklabels() will set the xtick labels with list of strings labels.

Add an extra information in a python plot?

Suppose we have a figure with three plots in it for three different parameters. But for the all three plots We have same temperature T=4K . Then how can I add this information in the figure?
I am not interested to write it in the Caption. I want it on the figure itself.
figtext would work well.
The advantage of figtext over text and annotate is that figtext defaults to using the figure coordinates, whereas the others default to using the coordinates of the axes (and therefore "T=4K" would move around if your axes are different between the different plots).
import matplotlib.pyplot as plt
plt.figure()
plt.xlim(-10, 10)
plt.ylim(0, .01)
plt.figtext(.8, .8, "T = 4K")
plt.show()
Here's a demonstration of using annotate. Check out this example for different styles of annotation.
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
fig, ax = plt.subplots()
x = np.linspace(0,4,100)
plt.plot(x,2*x)
plt.plot(x,x**2)
plt.plot(x,np.sqrt(8*x))
ax.annotate('T = 4K', xy=(2,4), xycoords='data',
xytext=(-100,60), textcoords='offset points',
arrowprops=dict(arrowstyle='fancy',fc='0.6',
connectionstyle="angle3,angleA=0,angleB=-90"))
plt.show()
raw_input()
figtext can make annotations at the bootom of multiple subplots figure like a comment independent of figures so you can make additional comments or remarks all in one picture. I was looking for this too. Thank you guys! :-)
import matplotlib.pyplot as plt
plt.figure(1)
plt.suptitle("SOME TITLE HERE")
#FIRST SUBPLOT
plt.subplot(311)
plt.ylabel(r"$a [m/s^2]$") # YOU CAN USE LaTeX TYPESETTING IN PYPLOT STRINGS!
plt.xlabel("time [s]")
plt.grid(True)
plt.plot(some_data)
# SECOND SUBPLOT
plt.subplot(312)
...
# THIRD SUBPLOT
plt.subplot(313)
...
# BOTTOM LABEL
plt.figtext(0.5, 0, "SOME LABEL BELOW ALL SUBPLOTS", ha="center", fontsize=7, bbox={"facecolor":"orange", "alpha":0.5, "pad":5})
# DRAW THE PLOT
plt.show()
Notre ha=center will center the string if x=0.5. You can also use fontsize and bbox parameters to change appearance of the string and its area.
Well, I'm not sure what you mean, but you can add text to the plot with the text() method.
Plot text in matplotlib pyplot
I suggest a grey horizontal zone around the T=4K zone
If you look at axhspan(ymin, ymax, xmin=0, xmax=1, **kwargs) in the matplotlib documentation for axes, you can make things like that:

Categories

Resources