rotate the fill function of matplotlib in a figure - python

I am trying to make a three joint plot. The frame of one of the plots is rotated by 90 degrees with respect to the other and perpendicular to the axis of the other. So I can make a histogram plot in this frame but when I use kde and generate data and use fill to overlay to the hist it won't rotate.
import pylab as plt
import seaborn as sns
from scipy.stats import gaussian_kde
import numpy as np
from astroML.plotting import hist
from mpl_toolkits.axes_grid1 import make_axes_locatable
sns.set_style("ticks")
axScatter = plt.subplot(111)
xmin, xmax = x.min(), x.max()
ymin, ymax = y.min(), y.max()
# Peform the kernel density estimate
xx, yy = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
positions = np.vstack([xx.ravel(), yy.ravel()])
values = np.vstack([x, y])
kernel = gaussian_kde(values)
f = np.reshape(kernel(positions).T, xx.shape)
axScatter.set_xlim(xmin, xmax)
axScatter.set_ylim(ymin, ymax)
# Contourf plot
cfset = axScatter.contourf(xx, yy, f, cmap='Blues')
## Or kernel density estimate plot instead of the contourf plot
#ax.imshow(np.rot90(f), cmap='Blues', extent=[xmin, xmax, ymin, ymax])
# Contour plot
cset = axScatter.contour(xx, yy, f, colors='k')
# Label plot
axScatter.scatter(x, y, marker='o', s=1, alpha=0.2, color='k')
axScatter.set_aspect('auto')
axScatter.set_xlabel(r'$X$')
axScatter.set_ylabel(r'$Y$')
# create new axes on the right and on the top of the current axes.
divider = make_axes_locatable(axScatter)
axHistx = divider.append_axes("top", size=1.2, pad=0.1, sharex=axScatter)
axHisty = divider.append_axes("right", size=1.2, pad=0.1, sharey=axScatter)
# the scatter plot:
# histograms
kde = gaussian_kde(x)
X_plot = np.linspace(xmin, xmax, 1000)
X_dens = kde.evaluate(X_plot)
axHistx.fill(X_plot, X_dens, fc='#AAAAFF',alpha=0.2)
hist(x, bins='knuth', ax=axHistx, color='black', histtype='step', normed=True)
kde = gaussian_kde(y)
Y_plot = np.linspace(ymin,ymax, 1000)
Y_dens = kde.evaluate(Y_plot)
axHisty.fill(Y_plot, Y_dens, fc='#AAAAFF' ,alpha=0.2)
hist(y, bins='knuth', ax=axHisty, color='black', histtype='step', normed=True, orientation='horizontal')
How can I rotate the fill function in right panel?

You can use the fill_betweenx function of the axHisty axes to do this:
axHisty.fill_betweenx(Y_plot, Y_dens, color='#AAAAFF' ,alpha=0.2)
Note the fill_betweenx doesn't take fc as a kwarg, but does take color.
I modified the scatter_hist.py example from the matplotlib gallery to have histograms and fills in the same style as your plot, and used the fill_betweenx line above, to create this plot:

Related

Plotting satellite orbit on python

I am trying to plot the orbit of a satellite around earth and the moon after using a RK4 numerical integration method for the orbital motions. But i dont quite know how display this or create the image. I kindly ask if anyone knows how this can be done. Below is the code section for the plotting;
from matplotlib import pyplot as plt
# We only plot the x, y components (view on the ecliptic plane)
x, y, v_x, v_y, t = Orbit(x_0, y_0, v_x0, v_y0, tmin, tmax, N)
kinetic_energy, potential_energy, total_energy = Energy(x,y,v_x,v_y)
# Set a dark background... since... space is dark
plt.style.use('dark_background')
# Create a figure and ax
fig, ax = plt.subplots(figsize=(12, 8))
# Create a yellow circle that represents the Sun, add it to the ax
Earth_circ = plt.Circle((0.0, 0.0), R_E, color='yellow', alpha=0.8)
ax.add_artist(Earth_circ)
# Plot the SSB movement
ax.plot(x, y, ls='solid', color='royalblue')
# Set some parameters for the plot, set an equal ratio, set a grid, and set
# the x and y limits
ax.set_aspect('equal')
ax.grid(True, linestyle='dashed', alpha=0.5)
# Set Axes limits to trajectory coordinate range, with some padding
xmin, xmax = min(x), max(x)
ymin, ymax = min(y), max(y)
dx, dy = xmax - xmin, ymax - ymin
PAD = 0.05
ax.set_xlim(xmin - PAD*dx, xmax + PAD*dx)
ax.set_ylim(ymin - PAD*dy, ymax + PAD*dy)
# Some labelling
ax.set_xlabel('X in Earths-Radius')
ax.set_ylabel('Y in Earths-Radius')
# Saving the figure in high quality
plt.tight_layout()
plt.savefig('orbit.png', dpi=300)
plt.show()

Change shape of Ellipse handle in legend

I'm trying to plot the labels of some contours and an ellipse in a single legend. I'm almost there (code below), but I'd like the shape associated to the ellipse in the legend to be a straight line, instead of a rectangle as it is by default.
How can I change this?
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
# Random data
ndim, nsamples = 2, 1000
samples = np.random.randn(ndim * nsamples).reshape([nsamples, ndim])
fig, ax = plt.subplots()
x, y = samples.T
H, X, Y = plt.hist2d(x, y, bins=20, cmap=plt.get_cmap('Greys'))[:-1]
# Plot two contours
contour = ax.contour(
H.T, levels=(5, 10), extent=[x.min(), x.max(), y.min(), y.max()])
# Plot ellipse
ellipse = Ellipse(xy=(0., 0.), width=3., height=2, angle=45, edgecolor='r', fc='None', label='ellipse')
ax.add_patch(ellipse)
# Get ellipse's handle and label
ellip, ellip_lbl = ax.get_legend_handles_labels()
# Plot legend
plt.legend(ellip + list(reversed(contour.collections)), ellip_lbl + ['1s', '2s'])
plt.show()
Below is the solution based on this answer. The main idea here is to use ls="-", by plotting an empty list and grabbing its handle. Store the ellipse's patch in ax1 and use it to get the label.
ellipse = Ellipse(xy=(0., 0.), width=3., height=2, angle=45, edgecolor='r', fc='None', label='ellipse')
ax1 = ax.add_patch(ellipse)
# Get ellipse's handle and label
ellip, ellip_lbl = ax.get_legend_handles_labels()
plt.legend(handles = [plt.plot([],ls="-", color='r')[0]] + list(reversed(contour.collections)),
labels=[ax1.get_label()] + ['1s', '2s'])

Log-log density-colour plot in matplotlib

I am trying to create a density plot with a given data and using log scales in the two axes x,y, using the version of Matplotlib 2.0.0. I have made the following code, the problem is that for the log plot case don't give the correct functional behaviour.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
init = 0.0
points = 500
final_value = 100
steep = (final_value-init)/points
list_values_x = np.arange(init,final_value,steep)
list_values_y = np.arange(init,final_value,steep)
#WE CREATE OUT DATA FILE
f1 = open("data.txt", "w")
for i in list_values_x:
for j in list_values_y:
f1.write( str(i) +" "+str(j)+" "+str(0.0001*(i**2+j**2)) +"\n")
f1.close()
#NOW WE OPEN THE FILE WITH THE DATA AND MAKE THE PLOT
x,y,temp = np.loadtxt('data.txt').T #Transposed for easier unpacking
nrows, ncols = points, points
grid = temp.reshape((nrows, ncols))
# LINEAR PLOT
fig1 = plt.imshow(grid, extent=(x.min(), x.max(), y.max(), y.min()),
interpolation='nearest', cmap=cm.gist_rainbow)
plt.axis([x.min(), x.max(),y.min(), y.max()])
plt.colorbar()
plt.suptitle('Example', fontsize=15)
plt.xlabel('x', fontsize=16)
plt.ylabel('y', fontsize=16)
plt.show()
# LOG-LOG PLOT
fig, (ax1) = plt.subplots(ncols=1, figsize=(8, 4))
ax1.imshow(grid, aspect="auto", extent=(1, 1e2, 1, 1e2), interpolation='nearest')
ax1.set_yscale('log')
ax1.set_xscale('log')
ax1.set_title('Example with log scale')
plt.show()
The data that I am using in order to make the plot is irrelevant, it's just an example. So that, the first plot is given with a linear scale. The second plot is given with a log-log scale, but is clear that it's incorrect, the behaviour beetwen the two plots is absolutely different and I am using the same data. Moreover, I don't know how put a colorbar in the log-log plot
Any idea why this happens? Thanks for your attention.
PD: In order to build the log-log plot, I have used part of the code that apears in "Non-linear scales on image plots" given in (http://matplotlib.org/devdocs/users/whats_new.html#non-linear-scales-on-image-plots)
Using the extent keyword and it with extent=(xmin, xmax, ymin, ymax) makes more sense when additionally using origin="lower" in imshow. You might also want to set the limits for the axes, since the automatic feature does not work too well for log scales.
Here is the complete example:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from mpl_toolkits.axes_grid1 import make_axes_locatable
points = 500
init = 0.0
final_value = 100
steep = (final_value-init)/points
x = np.arange(init,final_value,steep)
y = np.arange(init,final_value,steep)
X,Y = np.meshgrid(x,y)
Z = 0.0001*(X**2+Y**2)
fig, (ax, ax1) = plt.subplots(ncols=2, figsize=(8, 4))
# LINEAR PLOT
im = ax.imshow(Z, extent=(x.min(), x.max(), y.min(), y.max() ),
interpolation='nearest', cmap=cm.gist_rainbow, origin="lower")
ax.set_title('lin scale')
#make colorbar
divider = make_axes_locatable(ax)
ax_cb = divider.new_horizontal(size="5%", pad=0.05)
fig.add_axes(ax_cb)
fig.colorbar(im, cax = ax_cb, ax=ax)
# LOG-LOG PLOT
im1 = ax1.imshow(Z, extent=(1, 1e2, 1, 1e2),
interpolation='nearest',cmap=cm.gist_rainbow, origin="lower")
ax1.set_yscale('log')
ax1.set_xscale('log')
ax1.set_xlim([1, x.max()])
ax1.set_ylim([1, y.max()])
ax1.set_title('log scale')
#make colorbar
divider1 = make_axes_locatable(ax1)
ax_cb1 = divider1.new_horizontal(size="5%", pad=0.05)
fig.add_axes(ax_cb1)
fig.colorbar(im1, cax = ax_cb1, ax=ax1)
plt.tight_layout()
plt.show()

Set equal aspect in plot with colorbar

I need to generate a plot with equal aspect in both axis and a colorbar to the right. I've tried setting aspect='auto', aspect=1, and aspect='equal' with no good results. See below for examples and the MWE.
Using aspect='auto' the colorbars are of the correct height but the plots are distorted:
Using aspect=1 or aspect='equal' the plots are square (equal aspect in both axis) but the colorbars are distorted:
In both plots the colorbars are positioned too far to the right for some reason. How can I get a square plot with colorbars of matching heights?
MWE
import numpy as np
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
def col_plot(params):
gs, i, data = params
xarr, yarr, zarr = zip(*data)[0], zip(*data)[1], zip(*data)[2]
xmin, xmax = min(xarr), max(xarr)
ymin, ymax = min(yarr), max(yarr)
#plt.subplot(gs[i], aspect='auto')
plt.subplot(gs[i], aspect=1)
#plt.subplot(gs[i], aspect='equal')
plt.xlim(xmin, xmax)
plt.ylim(xmin, xmax)
plt.xlabel('$x axis$', fontsize=20)
plt.ylabel('$y axis$', fontsize=20)
# Scatter plot.
cm = plt.cm.get_cmap('RdYlBu_r')
SC = plt.scatter(xarr, yarr, marker='o', c=zarr, s=60, lw=0.25, cmap=cm,
zorder=3)
# Colorbar.
ax0 = plt.subplot(gs[i + 1])
cbar = plt.colorbar(SC, cax=ax0)
cbar.set_label('$col bar$', fontsize=21, labelpad=-2)
# Generate data.
data0 = np.random.uniform(0., 1., size=(50, 3))
data1 = np.random.uniform(0., 1., size=(50, 3))
# Create the top-level container
fig = plt.figure(figsize=(14, 25))
gs = gridspec.GridSpec(4, 4, width_ratios=[1, 0.05, 1, 0.05])
# Generate plots.
par_lst = [[gs, 0, data0], [gs, 2, data1]]
for pl_params in par_lst:
col_plot(pl_params)
# Output png file.
fig.tight_layout()
plt.savefig('colorbar_aspect.png', dpi=300)
You can use an AxesDivider to do that. I have modified your code a bit to make use of an AxesDivider.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
def col_plot(data):
xarr, yarr, zarr = zip(*data)[0], zip(*data)[1], zip(*data)[2]
xarr = [2*x for x in xarr]
xmin, xmax = min(xarr), max(xarr)
ymin, ymax = min(yarr), max(yarr)
fig = plt.figure()
ax0 = fig.add_subplot(111, aspect='equal')
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
plt.xlabel('$x axis$', fontsize=20)
plt.ylabel('$y axis$', fontsize=20)
# Scatter plot.
cm = plt.cm.get_cmap('RdYlBu_r')
SC = ax0.scatter(xarr, yarr, marker='o', c=zarr, s=60, lw=0.25, cmap=cm,
zorder=3)
the_divider = make_axes_locatable(ax0)
color_axis = the_divider.append_axes("right", size="5%", pad=0.1)
# Colorbar.
cbar = plt.colorbar(SC, cax=color_axis)
cbar.set_label('$col bar$', fontsize=21, labelpad=-2)
# Generate data.
data0 = np.random.uniform(0., 1., size=(20, 3))
col_plot(data0)
And here is the result (I changed your data so it spans a range of [0, 2] in the x-direction for demonstration purposes):
On Joseph Long's blog there is the following nice solution.
1) Define a colorbar function as:
from mpl_toolkits.axes_grid1 import make_axes_locatable
def colorbar(mappable):
ax = mappable.axes
fig = ax.figure
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
return fig.colorbar(mappable, cax=cax)
2) Call colorbar(thing) when you want to make a colorbar. In your case:
SC = ax0.scatter(xarr, yarr, marker='o', c=zarr, s=60, lw=0.25, cmap=cm,
zorder=3)
colorbar(SC)
3) And you get:

plt.plot when using subplots

I have a matplotlib code for creating a set of three subplots which share the same axes. My problem is that I am trying to plot an ellipse on each of these subplots, but the ellipse only shows up on one of the subplots. Can anyone tell me what I'm doing wrong?
Sorry if this kind of thing has already been answered elsewhere, I've been looking for a while but can't find an answer!
from pylab import *
import numpy as np
import sys
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import scipy.interpolate
import matplotlib
from matplotlib.patches import Ellipse
from numpy import linspace
from scipy import pi,sin,cos
data = np.genfromtxt(sys.argv[1]);
name1 = (sys.argv[1]);
name = ( sys.argv[2] );
print(sys.argv)
font = {'family' : 'normal',
'size' : 16}
matplotlib.rc('font', **font)
def ellipse(ra,rb,ang,x0,y0,Nb=50):
xpos,ypos=x0,y0
radm,radn=ra,rb
an=ang
co,si=cos(an),sin(an)
the=linspace(0,2*pi,Nb)
X=radm*cos(the)*co-si*radn*sin(the)+xpos
Y=radm*cos(the)*si+co*radn*sin(the)+ypos
return X,Y
def plot(x, y, z, name1, name):
# I2 = scipy.interpolate.NearestNDInterpolator((x, y), z)
I2 = scipy.interpolate.Rbf(x, y, z, function='linear')
xi, yi = np.linspace(x.min(), x.max(), 100), np.linspace(y.min(), y.max(), 100)
xig, yig = np.meshgrid(xi, yi)
zi = I2(xig, yig)
plt.clf()
#creating plot
f, axarr = plt.subplots(1,3,sharey=True)
plt.setp(axarr.flat, aspect=1.0, adjustable='box-forced')
#first plot
im1=axarr[2].imshow(zi, vmin=0, vmax=1,cmap='gist_heat_r', origin='lower', extent=[x.min(), x.max(), y.min(), y.max()])
# axarr[2].set_title('Sharing both axes')
X,Y=ellipse(7.36,2.29,0,0,0,Nb=70)
plt.plot(X,Y,"g.-",ms=1) # green ellipse
#second plot
im2=axarr[1].imshow(zi, vmin=0, vmax=1,cmap='gist_heat_r', origin='lower', extent=[x.min(), x.max(), y.min(), y.max()])
X,Y=ellipse(7.36,2.29,0,0,0,Nb=70)
plt.plot(X,Y,"g.-",ms=1) # green ellipse
#third plot
im3=axarr[0].imshow(zi, vmin=0, vmax=1,cmap='gist_heat_r', origin='lower', extent=[x.min(), x.max(), y.min(), y.max()])
# axis labels
plt.xlabel('X AXIS (kpc)')
plt.ylabel('Y AXIS (kpc)')
f.subplots_adjust(hspace=0);
f.subplots_adjust(wspace=0);
X,Y=ellipse(7.36,2.29,0,0,0,Nb=70)
plt.plot(X,Y,"g.-",ms=1) # green ellipse
# Colorbar
from mpl_toolkits.axes_grid1 import make_axes_locatable
divider = make_axes_locatable(plt.gca())
cax = divider.append_axes("right", "5%", pad="3%")
plt.colorbar(im1,cax=cax)
# Save figure
plt.savefig(name1 + "_norm.eps", bbox_inches='tight');
plot(data[:,0], data[:,1], data[:,2], name1, name);
When you call plt.plot() on what axes do you expect it to be plotted on? It will plot on the current active axes, which in your case is probably the first.
You need to either change the current active axes with plt.sca(axarr[n]) before calling plt.plot(), or even better, stop mixing both the OO- and state machine interface and use axarr[n].plot().
You are using the OO-interface for .imshow(), so why not for .plot() as well?

Categories

Resources