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")
Related
I'm trying to plot a series of frequency spectra in a 3D space using PolyCollection. My goal is to set "facecolors" as a gradient, i.e., the higher the magnitude, the lighter the color.
Please see this image for reference (I am not looking for the fancy design, just the gradients).
I tried to use the cmap argument of the PollyCollection, but I was unsuccessful.
I came this far with the following code adapted from here:
import matplotlib.pyplot as plt
from matplotlib.collections import PolyCollection
from mpl_toolkits.mplot3d import axes3d
import numpy as np
from scipy.ndimage import gaussian_filter1d
def plot_poly(magnitudes):
freq_data = np.arange(magnitudes.shape[0])[:,None]*np.ones(magnitudes.shape[1])[None,:]
mag_data = magnitudes
rad_data = np.linspace(1,magnitudes.shape[1],magnitudes.shape[1])
verts = []
for irad in range(len(rad_data)):
xs = np.concatenate([[freq_data[0,irad]], freq_data[:,irad], [freq_data[-1,irad]]])
ys = np.concatenate([[0],mag_data[:,irad],[0]])
verts.append(list(zip(xs, ys)))
poly = PolyCollection(verts, edgecolor='white', linewidths=0.5, cmap='Greys')
poly.set_alpha(.7)
fig = plt.figure(figsize=(24, 16))
ax = fig.add_subplot(111, projection='3d', proj_type = 'ortho')
ax.add_collection3d(poly, zs=rad_data, zdir='y')
ax.set_xlim3d(freq_data.min(), freq_data.max())
ax.set_xlabel('Frequency')
ax.set_ylim3d(rad_data.min(), rad_data.max())
ax.set_ylabel('Measurement')
ax.set_zlabel('Magnitude')
# Remove gray panes and axis grid
ax.xaxis.pane.fill = False
ax.xaxis.pane.set_edgecolor('white')
ax.yaxis.pane.fill = False
ax.yaxis.pane.set_edgecolor('white')
ax.zaxis.pane.fill = False
ax.zaxis.pane.set_edgecolor('white')
ax.view_init(50,-60)
plt.show()
sample_data = np.random.rand(2205, 4)
sample_data = gaussian_filter1d(sample_data, sigma=10, axis=0) # Just to smoothe the curves
plot_poly(sample_data)
Besides the missing gradients I am happy with the output of the code above.
I have a data with coordinates X,Y similar to a Vertical Sine function, I want to fill the area between left edge and the curve generated using variable color with colormap on matplot, changes in color whith X value as the image (From Blue to Red). I've tried and get this result where start point and final point are conected by a line. I need to fill the left area.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib.patches import PathPatch
#Data
y=np.arange(0,10,0.01)
x=np.sin(y)*y+2
#Set Array
xx=np.asarray(x)
yy=np.asarray(y)
path = Path(np.array([xx,yy]).transpose())
patch = PathPatch(path, facecolor='none')
plt.gca().add_patch(patch)
im = plt.imshow(xx.reshape(yy.size,1), cmap=plt.cm.coolwarm,interpolation="nearest",
origin='left',extent=[-5,10,0,10],aspect="auto", clip_path=patch, clip_on=True)
im.set_clip_path(patch)
You could add two additional points lying on the y-axis to create the desired shape:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib.patches import PathPatch
y = np.linspace(0, 10, 200)
x = np.sin(y) * y + 2
path = Path(np.array([np.append(x, [-5, -5]), np.append(y, [y[-1], y[0]])]).T)
patch = PathPatch(path, facecolor='none')
plt.gca().add_patch(patch)
im = plt.imshow(x.reshape(y.size, 1), cmap=plt.cm.coolwarm, interpolation="nearest",
origin='lower', extent=[-5, 10, 0, 10], aspect="auto", clip_path=patch, clip_on=True)
plt.show()
I am trying to plot a graph given the adjancecy matrix and the coordinates of the nodes with this code below, using matplotlib. Yet when I vizualize the graph, it's not the same as the adjancecy matrix, and mainly some edges are missing. Any insights?
NB: for now I am only plotting 2D Graph so my Z are 0, so if you have any other idea on how to do so (maybe with networkx) I'll appreciate your help too
from scipy.spatial import Delaunay
import numpy as np
#from numpy import sin, cos, sqrt
import matplotlib.tri as mtri
#from sklearn import preprocessing
import mpl_toolkits.mplot3d as plt3d
import matplotlib.pyplot as plt
plt.rcParams.update({'figure.max_open_warning': 0})
plt.switch_backend('agg')
def draw_surface( points_coord, adj):
'''points_coord.shape: (num_points, coord=3),
adj.shape:(num_points,num_points)'''
name= 'img'
fig = plt.figure(figsize=(12,10))
# Plot the surface.
ax = fig.add_subplot(1, 1, 1, projection='3d')
#ax.plot_trisurf(triang, z, cmap=cm.jet)#cmap=plt.cm.CMRmap)
x = points_coord[:,0]
y = points_coord[:,1]
if len(points_coord) == 3:
z = points_coord[:,2]
else:
z = np.zeros_like(points_coord[:,0])
max_val = np.max(adj)
list_edges = []
#plot lines from edges
for i in range(adj.shape[0]):
for j in range(i,adj.shape[1]):
if adj[i][j]:
line = plt3d.art3d.Line3D([x[i],x[j]], [y[i],y[j]], [z[i],z[j]], \
linewidth=0.4, c="black", alpha = round( adj[i,j], 4 ))
list_edges.append((i,j))
ax.add_line(line)
ax.scatter(x,y,z, marker='.', s=15, c="blue", alpha=0.6)
#ax.view_init(azim=25)
plt.axis('off')
plt.show()
plt.savefig(name+'.png', dpi=120)
plt.clf()
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()
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')