Contour on color map: not continuous (Python) - python

I made some color maps in python. On top of them I wanted to add some continental contours, using the land-sea mask provided in the model I run. It consists of just 1 or 0, 1 for land and 0 for no-land.
There is some strange characters written into the contour plot. Does anyone here knows how I could get the contour to connect to itself so it's smooth instead of being broken with those small strange characters in between the ends of each line?
Here is what the figure looks like:
And here is a piece of the code (note this map was part of a plot containing other maps, so this is the map of index 9).
lsmfile = netcdf.netcdf_file("/Volumes/LaCie/Plasim/Earth2/high/1367/SOL1367earth050.nc","r")
lat = lsmfile.variables["lat"].data
lon = lsmfile.variables["lon"].data
mask = lsmfile.variables["lsm"].data
mask = mask[0]
cmap = plt.get_cmap('bwr')
fig, ax = plt.subplots(nrows=5,ncols=2,figsize=(16,14))
im9 = ax.flat[9].pcolormesh(lon, lat, surfalbearth, cmap=cmap,norm=norm)
fig.colorbar(im9, ax=ax.flat[9])
ax.flat[9].set_xlim(xmin=0, xmax=355)
ax.flat[9].set_ylim(ymin=-86, ymax=86)
CS = plt.contour(lon,lat,mask, 1,colors='k')
plt.clabel(CS, fontsize=3, inline=1)
fig.tight_layout()
plt.savefig('Maps')
plt.show()

It seems you have asked for having those contour labels (clabel) in your plot by using the line
plt.clabel(CS, fontsize=3, inline=1)
So if you remove that line, the contour labels should disappear.

Related

Matplotlib contourf plots with streamline numbers

I am trying to generate a contour plot with line numbers inside! I used plt.contourf to draw the contour plot and plt.clabel to draw the lines on my contour plot! The numbers in my plot are incorrect as shown in the figure!
Contour plot with lines and wrong numbers
Contour lines with correct numbers
X = Data3.iloc[:,0].drop_duplicates()
Y = Data3.iloc[:,1].drop_duplicates()
Z = Data3.pivot('Battery capacity (kWh)','Solar capacity (kW)', 'Diesel electricity generation
(kWh)')
plt.figure(figsize=(7, 5))
contours = plt.contourf(X, Y, Z, 10, cmap='viridis', alpha=0.8 )
plt.colorbar();
plt.clabel(contours, inline = True, fontsize=8, fmt='%d', colors = 'black')
plt.xlabel('Solar Capacity (kW)',fontsize = 13) # x-axis label with fontsize 12
plt.ylabel('Battery Capacity (kWh)',fontsize = 12) # y-axis label with fontsize 12
plt.title('Diesel Electricity Generation (% of total generation)',fontsize = 15)
plt.scatter(x=(233*1.83*0.16), y=250, color = 'r', marker='o')
I also used plt.contour and plt.clabel, the numbers were placed correctly! How can I draw lines on plt.contourf without mixing the line numbers?
this question is almost a MRE. It would be helpful if it was because then I'd be able to copy and paste this code and run it on my computer. The only thing that's missing is the definitions for X,Y and Z, so I made a version of the question that is reproducible where it tries to graph a simpler contour plot:
import numpy as np
import itertools
from matplotlib import pyplot as plt
# Initialize the contour map data as a multiplication table
X= np.arange(10)
Y= np.arange(10)
Z= np.zeros((10, 10))
for i in range(10):
for j in range(10):
Z[i][j] = i*j
# Rest of example:
contours = plt.contour(X, Y, Z, 10, cmap='viridis', alpha=0.8 )
plt.colorbar();
plt.clabel(contours, inline = True, fontsize=8, fmt='%d', colors = 'black')
plt.xlabel('Solar Capacity (kW)',fontsize = 13) # x-axis label with fontsize 12
plt.ylabel('Battery Capacity (kWh)',fontsize = 12) # y-axis label with fontsize 12
plt.title('Diesel Electricity Generation (% of total generation)',fontsize = 15)
# Change location of single red point:
plt.scatter(x=5, y=7, color = 'r', marker='o')
When I run my example though, the contour labels show up correctly.
I'm wondering if this problem has to do with the input data in the Data3 variable.
Edit: I tried plotting this data with contourf to match the original question with contours = plt.contourf(X, Y, Z, 10, cmap='viridis', alpha=0.8 )
and I now see the problems with the contour labels:
I tried playing with all of the options to clabels and couldn't come up with something that outputs something suitable.
I suspect this is a bug with contourf. I couldn't find a bug report for this, so would you be comfortable with opening a bug ticket here in matplotlib?
In the short term, I suppose you could work around this by using contour() to plot. Then, if the plot really needs filled contours, my best idea is to fill them in manually with MS Paint or something -- but that's not a very good idea at all.

How to make an inset plot with mollweide projection?

I want to make a skymap using the Mollweide projection for a main set of axes and for an inset axes. This is easy for the main axes but not for the inset. I've tried a few different things but it doesn't work for the inset. Please help!
Here you can find the latitude and longitude data, and here you can find the sky location probability density data.
First, I make the main plot:
xmin = min(l)
xmax = max(l)
ymin = min(b)
ymax = max(b)
X, Y = np.meshgrid(np.linspace(xmin, xmax, 100), np.linspace(ymin, ymax, 100))
mpl.rcParams["text.usetex"] = True
fig = plt.figure(1)
fig.set_figheight(8)
fig.set_figwidth(8)
ax = plt.axes(projection='mollweide')
ax.grid()
# skypost is the sky location probability-density data accessible above
plt.contour(X, Y, skypost, colors='blue', levels=[5, 50, 95])
which works fine. Next, I define the inset axes and plot the contours, however there seems to be no way that completely works for this. What I want is for the inset to zoom-in on the contours while keeping the mollweide projection. I've tried to do as the example on ligo.skymaps, i.e.,
axesinset = plt.axes(
[0.0, 0.2, 0.25, 0.25],
projection='astro degrees zoom',
center='110d +20d',
radius='10 deg' )
plt.sca(axesinset)
axesinset.contour(X, Y, skypost, colors='blue', levels=[5, 50, 95])
axesinset.grid()
but this doesn't work since the contours don't even appear! I don't understand why they don't appear. I also do not understand why the x-axis of the inset is backwards?
Instead, I've tried just plotting a new mollweide projection in the inset, and restricting the xlim and ylim, but it says these options are not supported for the mollweide projection. Is there a way around this to restrict the axes limits?
Lastly, I've tried just doing a regular inset without the mollweide, which works, however the shape of the contours are distorted relative to the contours on the main mollweide plot which is physically relevant for my case. So this is very sub-optimal.
Any suggestions and advice are greatly appreciated.
To have the axis in the correct way, you can rotate the subplot by using rotate.
Concerning the fact that your contour are not shown, it is probably because you have to add the transform keyword. If you don't specify it, it is plotted in pixel coordinates by default (https://docs.astropy.org/en/stable/visualization/wcsaxes/overlays.html).
The example below shows that the desired point (in blue) is obtained by adding ax.get_transform("world").
The blue and green points are in the lower right corner because of the rotate.
I guess that it should be the same for contour.
ax = plt.subplot(111, projection='geo degrees zoom',
center="0d - 0d", radius='10 deg', rotate='180 deg')
ax.grid()
ax.set_xlabel(r"$\phi \, [deg]$")
ax.set_ylabel(r"$\theta \, [deg]$")
ax.scatter(0,0, color = "blue")
ax.scatter(100,0, color = "green")
ax.scatter(0,0, color = "red", transform = ax.get_transform("world"))
I'm a bit late to the party, but I thought its worth mentioning that I've created a nice inset-map functionality for EOmaps...
It lets you create inset-maps in arbitrary projections and you can add whatever features you want!
from eomaps import Maps
m = Maps(Maps.CRS.Mollweide())
m.add_feature.preset.coastline()
# create a rectangular inset-map that shows a 5 degree rectangle
# centered around a given point
inset = m.new_inset_map(xy=(6, 43), xy_crs=4326,
radius=5, radius_crs=4326,
inset_crs=Maps.CRS.Mollweide(),
shape="rectangles")
inset.add_feature.preset.coastline()
inset.add_feature.preset.ocean()
inset.add_feature.cultural_10m.urban_areas(fc="r", ec="none")
m.apply_layout(
{'0_map': [0.01, 0.17333, 0.98, 0.65333],
'1_map': [0.05, 0.11667, 0.43341, 0.76667]})

how to change specific value's color in pcolormesh, such as -1,-2,-3, not NaN

I know there is a func cmap.set_bad to change NaN's color but I want to change color of more values such as -1,-2,-3, how to do it?
this plot is base on basemap
and I want to hold the color of the other area so I can't use the colormap built by myself
##### plot IMERG ####
latcorners = ([20.05, 54.051])
loncorners = ([73.05, 136.05])
m = Basemap(projection='cyl',llcrnrlat=latcorners[0],urcrnrlat=latcorners[1],llcrnrlon=loncorners[0],urcrnrlon=loncorners[1])
# Draw coastlines, state and country boundaries, edge of map.
m.drawcoastlines(color='darkgray')
m.drawstates(color='darkgray')
m.drawcountries(color='darkgray')
# Define the latitude and longitude data
X,Y = np.float32(np.meshgrid(theLons, theLats))
X1,Y1 = np.float16(np.meshgrid(lons_resized, lats_resized))
# Mask the values less than 0 because there is no data to plot.
masked_array = np.ma.masked_where(precip < 0,precip)
# Plot every masked value as grey
cmap = plt.get_cmap('gnuplot').copy()
cmap.set_bad('darkslategray', 1.)
# Draw filled contours.
clevs = np.arange(0,5,0.2)
m.readshapefile(r'../beijing/beijing', 'Shape_Leng', color='darkgrey')
# Plot the data,resized_precip is an ndarray which contains precipitation data, with shape(3401,6301), X1,Y1 are lon/lat of these points
cs = m.pcolormesh(X1,Y1,resized_precip, cmap=cmap, vmin=0, vmax=10)
parallels = np.arange(-90.,91,5.)
m.drawparallels(parallels,labels=[True,False,True,False],color='darkgray')
meridians = np.arange(-180.,180.,10.)
m.drawmeridians(meridians,labels=[False,False,False,True],color='darkgray')
# Add colorbar
cbar = m.colorbar(cs,location='right',pad="5%")
cbar.set_label('mm/h')
plt.show()
plt.close()
this is a program which is used to plot some precipitation data.
I want to plot these precipitation data properly,but I want to highlight some specific area with special color, and these points are flaged by special value.so how can I highlight these area by the same way as pcolormesh but not scatter?

Contour Labels not showing up

I am trying to overlay contours on top of a filled contour plot in matplotlib for some atmospheric data. However, my contour labels are not always showing up onscreen. Below is an example:
As you can see, the contour labels are only appearing on the innermost few contours.
Knowing that my contour range is defined earlier as
list(range(950,1052,4))
I have the following code to actually plot:
parallels = np.arange(0.,90,5.)
basem.drawparallels(parallels,labels=[1,0,0,0],fontsize=10)
# draw meridians
meridians = np.arange(180.,360.,5.)
basem.drawmeridians(meridians,labels=[0,0,0,1],fontsize=10)
basem.drawstates()
basem.drawcountries()
if clevs != 0:
cs = basem.contourf(x,y, plotted_var, clevs)
cl = basem.contour(x,y, plotted_var, clevsl, colors='k')
plt.clabel(cl, fmt="%1.0f", fontsize=8)
else:
cs = basem.contourf(x,y, plotted_var, cmap=plt.get_cmap(colorbar),
vmin = vmin, vmax = vmax)
cbar = basem.colorbar(cs, location='bottom', pad = "5%")
cbar.set_label(units)
Additionally, my basemap definition is:
basem = Basemap(width=5800000,height=3000000,
rsphere=(6378137.00,6356752.3142),\
resolution='h',area_thresh=1000.,projection='lcc',\
lat_1=45.,lat_2=55,lat_0=40,lon_0=-102.)
Is this a bug or is there just something I'm missing? I'm attempting to avoid the use of manual if I can.
The input data is a global dataset (GFS weather model). x, y are obtained by:
lons2, lats2 = np.meshgrid(lons, lats)
x,y = basem(lons2, lats2)
where lons, lats are:
lons = [0.0, 0.25, 0.5, 0.75, 1.0, ..., 359.75, 360.0]
lats = [-90, -89.75, ..., 89.75, 90]
I seem to have resolved the issue like so:
What I had to do was bound the data to what is able to be seen on basemap. My input dataset was a global dataset, and when I bound it (seen in the white areas below), the contour labels showed up mostly within the map boundaries. This still seems like a bug- my choice of a display region changes the locations of the contour labels in almost every other meteorological graphics program (like GrADS), but I'm going to mark this answered for now.

Matplotlib Contourf Plots Unwanted Outlines when Alpha < 1

I am using matplotlib in Python 2.7 to plot a filled contour plot. I want to overlay this over an image, so I am using the alpha keyword to make the plot semi-transparent. When I do this, the body of the contours are the correct transparency, but contourf() plots unwanted lines on the boundaries between different levels. I have attempted to eliminate them with the keyword argument linecolor='none', but this has not helped.
Code:
CS = map.contourf(xi, yi, zi, 25, alpha=0.3, linecolor='none')
A link to an image example of the problem; I would like the filled contours to meet without the bright boundary lines:
Any help or insight into this problem is appreciated.
Try turn on antialiased=True:
x, y = np.mgrid[-1:1:100j, -1:1:100j]
contourf(x, y, x**2+y**2 + np.random.rand(100, 100)*0.1, 10, alpha=0.3, antialiased=True)
here is my result:

Categories