matplotlib contour not encapsulating the limits as expected - python

I'm trying to make a figure that shows both a heatmap and a contourplot of the same data.
Currently the contour does not connect to the edges of the image, leaving the '6's and '8's at the edge of the plots out of the contour plot.
I would want the contour to actually enclose all the values containing the values specified in the levels.
# make array
a = np.array( [(1,2,3,4,5,6),
(2,3,4,5,6,7),
(3,4,5,6,7,8),
(4,5,6,7,8,9),
(5,6,7,8,9,10)])
fig,ax = plt.subplots(figsize=(10,4.5))
#plot both colors and contour
im = ax.pcolormesh(a,norm=colors.LogNorm(vmin=1, vmax=10),
cmap='rainbow')
contour = ax.contour(a,levels=[2,4,6,8],colors='k')
# indicate the data
for i in range(0,6):
for j in range(0,5):
plt.text(i+.5,j+.5,str(a[j,i]))
Figure showing heatmap and contours:
UPDATE:
I've provisionally solved the problem by enlarging the dataset and zooming in on the original frame.

Related

Plotting a scatter plot on an image Python

I have plotted some data that are defined by specific coordinates and a value.
I have plotted this with a scatterplot, and would now like to plot this on top of an image, to reflect where the data points are located.
I have tried to use matplotlib.image and import img to be able to show the image. Unfortunately, the image of my location does not match up with the data completely (due to stretching, I believe).
When I edit the extent Python either edits out some of the image, instead of moving my data. I would like to be able to move the image/crop it to fit with the data or use some sort of package to load in a map (as I have the coordinates). This needs to show a local stream in Denmark.
x and y are our coordinates (lat, lon) and z is the value each coordinate have.
plt.figure(figsize=(20,10))
plt.scatter(x,y, cmap = 'gist_heat' ,s=100,c=z)
plt.colorbar()
plt.ylim(np.min(y),np.max(y))
plt.xlim(np.min(x),np.max(x))
img = plt.imread("grindsted4_sattelit.png")
ext = [np.min(x),np.max(x), np.min(y), np.max(y)]
plt.imshow(img, zorder=0, extent=ext)
aspect=img.shape[0]/float(img.shape[1])*((ext[1]-ext[0])/(ext[3]-ext[2]))
plt.gca().set_aspect(aspect)
plt.show()
The plot are the colored dots, and the black and white dots are my coordinates in Google Earth.
Thank you!

Plotting vertical and horizontal lines inside a seaborn heatmap plot

I had some data on which I had to do some image processing to obtain the centers of the 4 'circles' (refer figure). I was able to do that correctly using the Blob detection function of the OpenCV library in Python.
I want to plot the lines perpendicular to the x and y axis to indicate these centers on the seaborn heatmap output. I'm unable to do so. I have the co-ordinates for the lines in a separate list.
But I'm unable to plot even one line to begin with.
plt.figure(figsize = (12,8))
sns.heatmap(df_scaled)
plt.axvline(x = -10.86,color='white',linewidth=2) # For now let's assume value of x as -10.86
plt.tight_layout()
plt.show()]

Generating Heatmaps from pixel coordinates

I have a set of pixel values that I wanted to map on an image as a heatmap. My pixel values look something like this: they are x,y coordinates of image pixels of an arbitrary resolution.
pixel values = [[1,1],[2,1],[3,1],[4,1],[2,1]]
I have tried using OpenCV but I fail to understand how to get it to work. I assume a probability/density distribution needs to be generated, or perhaps the plotting function can do this automatically ? Since the image is loaded using OpenCV, I was looking for an OpenCV function, if Matplotlib works, please do comment.
heatmap_array = np.array(heatmap)
cv_colormap = cv2.applyColorMap(heatmap_array[0:], cv2.COLORMAP_HOT)
cv2.imwrite("colormap_gen.jpg", cv_colormap)
There needs to be an slightly opaque overlay of the heatmap on top of the original image.
You can try with Matplotlib:
# sample data
# xy can be np.array(pixel_values)
np.random.seed(1)
xy = np.random.multivariate_normal([300,300], [[2000,400],[400,1000]], 2000000)
# compute the hist
# bins here are the size of the image
hist,_,_ = np.histogram2d(xy[:,0], xy[:,1], bins=(600,800))
# show heatmap by plt
# you can use plt to save the figure
fig = plt.figure(figsize=(12,8))
plt.imshow(hist,cmap='hot')
plt.axis('off')
plt.show()
Output:

pcolormesh () and contourf() do not work

Esteemed experts, am back with a problem I presented about two months ago, I have been working on it since with no success. This concerns superposition of contours on a basemap. I have looked at numerous examples on this, e.g. the example here: http://nbviewer.ipython.org/github/Unidata/tds-python-workshop/blob/master/matplotlib.ipynb
A sample of the data is on one of my previous posts, here: Contours with map overlay on irregular grid in python.
After preparing the data, here are plotting methods:
# Setting the plot size and text
fig = plt.figure(figsize=(10,8))
lev = [15, 20, 25, 30, 35, 40,45]
norm1 = colors.BoundaryNorm(lev, 256)
# Draw filled contours
# 1. pcolor does not show the filled contours
#cs = plt.pcolor(x,y,zi, cmap = cm.jet, norm = norm1)
# 2. pcolormesh does not show the filled contours
#cs = plt.pcolormesh(x,y,zi, shading = "flat", cmap=cmap)
# 3. contourf does not show the filled contours
#cs = plt.contourf(xi, yi, zi) #, levels=np.linspace(zi.min(),zi.max(),5))
cs = plt.contourf(xi, yi, zi, cmap = cm.jet, levels = lev, norm = norm1)
# 4. Draw line contours with contour()
#cs = m.contour(x,y,zi,linewidths=1.2) # This works
plt.scatter(data.Lon, data.Lat, c=data.Z, s=100,
vmin=zi.min(), vmax=zi.max()) # Does not work at all
# Color bar
#cbar = m.colorbar(fig,location='right',pad="10%")
fig.colorbar(cs)
# Plot a title
plt.figtext(.5,.05,'Figure 1. Mean Rainfall Onset Dates',fontsize=12,ha='center')
plt.show()
Sorry I am not able to post the plot examples, but:
pcolor, pcolormesh and contourf above all give a map without any filled contours but with a colorbar
the above plots without the map object give filled contours including scatter plot (without map background)
contour gives the map with contour lines superposed:
I am baffled because this is an example copy-pasted from the example in the link quoted above.
Any hint as to a possible cause of the problem would be appreciated
Zilore Mumba
you need to use the basemap to plot the contours vs using matplotlib.pyplot. see my example for some of my code.
#Set basemap and grid
px,py=n.meshgrid(x,y)
m=Basemap(projection='merc',llcrnrlat=20,urcrnrlat=55,
llcrnrlon=230,urcrnrlon=305,resolution='l')
X,Y=m(px,py)
#Draw Latitude Lines
#labels[left,right,top,bottom] 1=True 0=False
parallels = n.arange(0.,90,10.)
m.drawparallels(parallels,labels=[1,0,0,0],fontsize=10,linewidth=0.)
# Draw Longitude Lines
#labels[left,right,top,bottom] 1=True 0=False
meridians = n.arange(180.,360.,10.)
m.drawmeridians(meridians,labels=[0,0,0,1],fontsize=10,linewidth=0)
#Draw Map
m.drawcoastlines()
m.drawcountries()
m.drawstates()
m.fillcontinents(color='grey',alpha=0.1,lake_color='aqua')
#Plot Contour lines and fill
levels=[5.0,5.1,5.2,5.3,5.4,5.6,5.7,5.8,5.9,6.0]
cs=m.contourf(px,py,thickness,levels,cmap=p.cm.RdBu,latlon=True,extend='both')
cs2=m.contour(px,py,thickness,levels,latlon=True,colors='k')
#Plot Streamlines
m.streamplot(px,py,U,V,latlon=True,color='k')
#Add Colorbar
cbar = p.colorbar(cs)
cbar.add_lines(cs2)
cbar.ax.set_ylabel('1000 hPa - 500 hPa Thickness (km)')
#Title
p.title('Geostrophic Winds with Geopotential Thickness')
p.show()
Without knowing how your data look like it's a bit difficult to answer your question, but I'll try anyway. You might want to grid your data, for example, with an histogram, then contour the results.
For example, if you're interested in plotting 2D contours of points that have coordinates (x,y) and a third property (z) you want to use for the colors, you might give this a try
from numpy import *
H=histogram2d(x,y,weights=z)
contourf(H[0].T,origin='lower')
But, like I said, it's hard to understand what you're looking for if you're not giving details about your data. Have a look at the matplotlib guide for more examples http://matplotlib.org/examples/pylab_examples/contourf_demo.html

Color differences between contour and contourf in matplotlib

I'm trying to produce a plot which uses both contour and contourf where they both use the same colormap, plotting the same data. However, contourf is only used to plot data which is 'significant' in some way (using a masked array). Meanwhile, contour is used to plot all the data. The aim is to produce a plot where all the information is available, but the eye is drawn to the more important areas.
I nearly have this working as I would like, but I am finding that the color of the contour lines is slightly different from the color of the filled contours from contourf.
I'm guessing that the differences come from the fact that either the contour colors are actually half-way between the contour colors (which would make sense, as the contour lines are defined at a value, e.g. 1, 2, etc, and the filled contours are between 1 and 2, i.e. with a 'value' of 1.5 etc).
I am defining my colormap as
cmap = cm.coolwarm
cnorm=clrs.Normalize(cmap,clip=False)
cmap.set_under(color=cmap(0.0),alpha=1.0)
cmap.set_over(color=cmap(1.0),alpha=1.0)
my contour levels, used for both contour and contourf are
clevs = [-3.,-2.,-1.,1.,2.,3.]
The contour lines are plotted as
cplot=map.contour(x,y,diff,clevs,\
cmap=cmap,\
norm=cnorm,\
extend='both')
and the filled contours are plotted as
cplot=map.contourf(x,y,true_mask,clevs,cmap=cmap,\
norm=cnorm,
extend='both')
Is there a straight-forward way to have the colors of the contour lines 'match' those of the filled contours, i.e. the line at 1 is the color of the 1-2 filled contour, the line at 2 is the color of the 2-3 filled contour, the line at -1 have the color of the -2--1 filled contour etc.?
Many thanks for your help.
I think that one possible solution here is to create a new colormap for the call to contour. If the original colormap is defined as
cmap = matplotlib.cm.coolwarm
cnorm=matplotlib.colors.Normalize(cmap,clip=False)
cmap.set_under(color=cmap(0.0),alpha=1.0)
cmap.set_over(color=cmap(1.0),alpha=1.0)
and the contour levels to plot as
clevs = [-3.,-2.,-1.,1.,2.,3.]
then the new colormap can be created by
cw=matplotlib.cm.get_cmap('coolwarm',8*(len(clevs)+1))
cw_vals=cw(np.arange(8*(len(clevs)+1)))
new_cw_vals=np.zeros([len(clevs),cw_vals.shape[1]],dtype=np.float128)
new_cw_vals_t = np.float128(cw_vals[4::8,:])
new_cw_vals_b = np.float128(cw_vals[12::8,:])
for i in np.arange(new_cw_vals.shape[0]):
if clevs[i] < 0.0:
new_cw_vals[i,:]=np.float32(new_cw_vals_t[i,:])
else:
new_cw_vals[i,:]=np.float32(new_cw_vals_b[i,:])
newcmap = matplotlib.colors.LinearSegmentedColormap.from_list("newcw", new_cw_vals)
newcnorm=matplotlib.colors.Normalize(newcmap,clip=False)
I had to put a shift in to allow for the fact that I'm not plotting the 0 line.
which is then used in the call to contour
cplot=map.contour(x,y,diff,clevs,
cmap=newcmap,
norm=newcnorm,
vmin=vmin,vmax=vmax)
Essentially I am creating a colormap with 8 times the number of points, and then picking out the mid-points. It isn't quite perfect though, the colors are ever-so-slightly off from the colors from contourf. This may be down to rounding differences (the colormap values seem to be float32). It is also a bit specific to the values used in clevs, although it could easily be changed for other values.

Categories

Resources