matplotlib - savefig with text very slow - python

I just wondered about the performance of matplotlib.pyplot.savefig(). It's a simple map. With only the country-borders it takes around 1 sec.
When i print a grid of only 21x19 values with text() on the map it needs 3 sec! Why is that so? Is there a workatound?
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import pickle
import numpy as np
import time
plt.clf()
m = pickle.load(open('a.pickle','rb'))
c = pickle.load(open('b.pickle','rb'))
x, y = m(lons, lats) # compute map proj coordinates
for i in range(322,343,1): # lons
for j in range(97,116,1): # lats
plt.text(x[j,i], y[j,i], int(round(data[j,i])),fontsize=7, color='k', ha='center', va='center')
print time.clock()-t1
plt.savefig('/var/www/img/test.png', bbox_inches='tight',pad_inches=0.05, dpi=100)
print time.clock()-t1
plt.close('all')

Related

Mpl toolkits plot_surface not showing any output

I am trying to plot z transforms of some signals using the mpl_toolkits in python, but the output is totally blank. What am I doing wrong? The input numpy arrays have non-zero values. Here is my code:
import numpy as np
import matplotlib.pyplot as plt
import math
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
# initialize r and theta
r = 10
theta = r*np.linspace(-math.pi,math.pi,100)
theta = np.meshgrid(theta,theta)[0]
# calculate z
z = r*(np.cos(theta) + 1j*np.sin(theta))
# calculate z transform for first signal
xs1 = np.abs(z/(z-2))
# calculate z transform for second signal
xs2 = np.abs((np.power(z,3)+2*np.power(z,2)+3*z+3)/np.power(z,3))
# plot the transforms
fig1 = plt.figure(0)
ax1 = fig1.add_subplot(111, projection='3d')
fig2 = plt.figure(1)
ax2 = fig2.add_subplot(111, projection='3d')
ax1.plot_surface(z.real,z.imag,xs1,cmap = cm.coolwarm)
ax2.plot_surface(z.real,z.imag,xs2,cmap = cm.coolwarm)
plt.show()
Here is one of the output:

Matplotlib: points changing alpha mysteriously

I'm working on a simple 3D animation in matplotlib within an IPython notebook, but my points are changing alpha values mysteriously:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation
from IPython.display import HTML
import requests
%matplotlib inline
requests.get('https://gist.github.com/duhaime/023897b9bda70e7728c7db9792a11bd3/raw/b632e2ea9fb693f303908f546a684a3afcc329c0/data.npy')
X = np.load('data.npy')
def update_points(time, points):
arr = np.array([[ X[time][i][0], X[time][i][1] ] for i in range(int(X.shape[1]))])
points.set_offsets(arr) # set x, y values
points.set_3d_properties(X[time][:,2][:], zdir='z') # set z value
def get_plot():
fig = plt.figure()
ax = p3.Axes3D(fig)
ax.set_xlim(-10,10)
ax.set_ylim(-10,10)
ax.set_zlim(-10,10)
points = ax.scatter(X[0][:,0][:], X[0][:,1][:], X[0][:,2][:]) # x,y,z vals
return animation.FuncAnimation(fig,
update_points,
200, # steps
interval=100, # how often to refresh plot
fargs=(points,),
blit=False
).to_jshtml()
HTML(get_plot())
Does anyone know why the points' alpha values are changing? Any suggestions others can offer would be very helpful!
Use the depthshade argument of Axes3d.scatter
depthshade Whether or not to shade the scatter markers to give the appearance of depth. Default is True.
Set this to False to have no alpha changes in your plot.
This doesn't explain what's mutating the alpha values, but one can mutate them back to 1 in the update function:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation
from IPython.display import HTML
import requests
%matplotlib inline
requests.get('https://gist.github.com/duhaime/023897b9bda70e7728c7db9792a11bd3/raw/b632e2ea9fb693f303908f546a684a3afcc329c0/data.npy')
X = np.load('data.npy')
def update_points(time, points):
arr = np.array([[ X[time][i][0], X[time][i][1] ] for i in range(int(X.shape[1]))])
points.set_offsets(arr) # set x, y values
points.set_3d_properties(X[time][:,2][:], zdir='z') # set z value
points.set_alpha(1)
def get_plot(lim=3):
fig = plt.figure()
ax = p3.Axes3D(fig)
ax.set_xlim(-lim, lim)
ax.set_ylim(-lim, lim)
ax.set_zlim(-lim, lim)
points = ax.scatter(X[0][:,0][:], X[0][:,1][:], X[0][:,2][:]) # x,y,z vals
return animation.FuncAnimation(fig,
update_points,
200, # steps
interval=100, # how often to refresh plot
fargs=(points,),
blit=False
).to_jshtml()
HTML(get_plot())

Plotting an ellipse but ellipse is not showing up

I am attempting to plot an ellipse surrounding scattered data points, but when the pyplot displays my plot only the data points are showing up and ellipse isn't. Do I need to install the patch somehow?
Here is my code:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as pp
import numpy as np
from matplotlib import cm
import pandas as pd
from matplotlib.patches import Ellipse
data_to_plot = pd.read_csv("positions.csv", sep = ",", index_col=False)
xs = data_to_plot['x']
ys = data_to_plot['y']
zs = data_to_plot['z']
covxy = np.cov(xs, ys)
lambda_xy, vxy = np.linalg.eig(covxy)
lambda_xy = np.sqrt(lambda_xy)
ax1 = pp.subplot(221)
for j in xrange(1, 4):
ell = Ellipse(xy=(xav, yav),
width=lambda_xy[0]*j*2, height=lambda_xy[1]*j*2,
angle=-np.rad2deg(np.arccos(vxy[0, 0])))
ell.set_facecolor('none')
ax1.add_artist(ell)
ax1.set_xlabel("x distance from the sun / AU")
ax1.set_ylabel("y distance from the sun / AU")
pp.scatter(xs, ys)
pp.xlim(xav-0.001,xav+0.0013)
pp.ylim(yav-0.001,yav+0.001)
ell.set_facecolor('none') seems counterproductive. If the intention is to show the ellipse, it should not have 'none' as color. Or it should have at least an edgecolor being set, e.g.
ell.set_edgecolor("limegreen")
Or consider giving the colors as arguments to the ellipse
Ellipse(..., fc="none", ec="limegreen")

Problems with unpacking Matplotlib hist2d outputs

I'm using Matplotlib's function hist2d() and I want to unpack the output in order to further use it. Here's what I do: I simply load with numpy a 2-column file containing my data and use the following code
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np
traj = np.loadtxt('trajectory.txt')
x = traj[:,0]
y = traj[:,1]
M, xe, ye, img = plt.hist2d(x, y, bins = 80, norm = LogNorm())
plt.imshow(M)
plt.show()
The result I get is the following:
Instead, if I try to directly plot the hist2d results without unpacking them:
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np
traj = np.loadtxt('trajectory.txt')
x = traj[:,0]
y = traj[:,1]
plt.hist2d(x, y, bins = 80, norm = LogNorm())
plt.show()
I get the whole plot without the strange blue box. What am I doing wrong?
You can create a histogram plot directly with plt.hist2d. This calculates the histogram and plots it to the current axes. There is no need to show it yet another time using imshow.
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np; np.random.seed(9)
x = np.random.rayleigh(size=9900)
y = np.random.rayleigh(size=9900)
M, xe, ye, img = plt.hist2d(x, y, bins = 80, norm = LogNorm())
plt.show()
Or, you may first calculate the histogram and afterwards plot the result as an image to the current axes. Note that the histogram produced by numpy is transposed, see Matplotlib 2D histogram seems transposed, making it necessary to call imshow(M.T). Also note that in order to obtain the correct axes labeling, you need to set the imshow's extent to the extremal values of the xe and ye edge arrays.
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np; np.random.seed(9)
x = np.random.rayleigh(size=9900)
y = np.random.rayleigh(size=9900)
M, xe, ye = np.histogram2d(x, y, bins = 80)
extent = [xe[0], xe[-1], ye[0], ye[-1]]
plt.imshow(M.T, extent=extent, norm = LogNorm(), origin="lower")
plt.show()

Putting matplotlib hexbin into an Aitoff projection

I have the nice hexbin plot below, but I'm wondering if there is any way to get hexbin into an Aitoff projection? The salient code is:
import numpy as np
import math
import matplotlib.pyplot as plt
from astropy.io import ascii
filename = 'WISE_W4SNRge3_and_W4MPRO_lt_6.0_RADecl_nohdr.dat'
datafile= path+filename
data = ascii.read(datafile)
points = np.array([data['ra'], data['dec']])
color_map = plt.cm.Spectral_r
points = np.array([data['ra'], data['dec']])
xbnds = np.array([ 0.0,360.0])
ybnds = np.array([-90.0,90.0])
extent = [xbnds[0],xbnds[1],ybnds[0],ybnds[1]]
fig = plt.figure(figsize=(6, 4))
ax = fig.add_subplot(111)
x, y = points
gsize = 45
image = plt.hexbin(x,y,cmap=color_map,
gridsize=gsize,extent=extent,mincnt=1,bins='log')
counts = image.get_array()
ncnts = np.count_nonzero(np.power(10,counts))
verts = image.get_offsets()
ax.set_xlim(xbnds)
ax.set_ylim(ybnds)
plt.xlabel('R.A.')
plt.ylabel(r'Decl.')
plt.grid(True)
cb = plt.colorbar(image, spacing='uniform', extend='max')
plt.show()
and I've tried:
plt.subplot(111, projection="aitoff")
before doing the plt.hexbin command, but which only gives a nice, but blank, Aitoff grid.
The problem is that the Aitoff projection uses radians, from -π to +π. Not degrees from 0 to 360. I use the Angle.wrap_at function to achieve this, as per this Astropy example (which essentially tells you how to create a proper Aitoff projection plot).
In addition, you can't change the axis limits (that'll lead to an error), and shouldn't use extent (as ImportanceOfBeingErnest's answer also states).
You can change your code as follows to get what you want:
import numpy as np
import matplotlib.pyplot as plt
from astropy.io import ascii
from astropy.coordinates import SkyCoord
from astropy import units
filename = 'WISE_W4SNRge3_and_W4MPRO_lt_6.0_RADecl_nohdr.dat'
data = ascii.read(filename)
coords = SkyCoord(ra=data['ra'], dec=data['dec'], unit='degree')
ra = coords.ra.wrap_at(180 * units.deg).radian
dec = coords.dec.radian
color_map = plt.cm.Spectral_r
fig = plt.figure(figsize=(6, 4))
fig.add_subplot(111, projection='aitoff')
image = plt.hexbin(ra, dec, cmap=color_map,
gridsize=45, mincnt=1, bins='log')
plt.xlabel('R.A.')
plt.ylabel('Decl.')
plt.grid(True)
plt.colorbar(image, spacing='uniform', extend='max')
plt.show()
Which gives
I guess your problem lies in the use of the extent which is set to something other than the range of the spherical coordinate system.
The following works fine:
import matplotlib.pyplot as plt
import numpy as np
ra = np.linspace(-np.pi/2.,np.pi/2.,1000)
dec = np.sin(ra)*np.pi/2./2.
points = np.array([ra, dec])
plt.subplot(111, projection="aitoff")
color_map = plt.cm.Spectral_r
x, y = points
gsize = 45
image = plt.hexbin(x,y,cmap=color_map,
gridsize=45,mincnt=1,bins='log')
plt.xlabel('R.A.')
plt.ylabel(r'Decl.')
plt.grid(True)
cb = plt.colorbar(image, spacing='uniform', extend='max')
plt.show()

Categories

Resources