Plot ConvexHull in basemap - python

I am making a ConvexHull in python, by a set of latitude and longitudinal positions. Then I want to plot the points, alongside the ConvexHull in a basemap. Everything works fine if I plot them in a normal plot without a map,as I follow the instructions from http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.ConvexHull.html#scipy.spatial.ConvexHull. When I try to plot them with a basemap, I just get the regular plot. What do I do wrong?
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.basemap import Basemap
map = Basemap(projection='merc',
resolution = 'c', area_thresh = 40,
llcrnrlon=27.72, llcrnrlat=69.41,
urcrnrlon=28.416, urcrnrlat=70.95)
con = lite.connect(databasepath)
with con:
cur = con.execute("SELECT DISTINCT latitude, longitude FROM MessageType1 where latitude>= 70.55 and latitude<= 70.7 and longitude >= 27.72 and longitude <= 28.416 limit 100 ")
points = [[float(x[1]), float(x[0])] for x in cur]
points = np.array(points)
hull = ConvexHull(points)
x,y = map(points[:,0], points[:,1])
plt.plot(x, y, 'o')
for simplex in hull.simplices:
x,y = map(points[simplex,0], points[simplex,1])
plt.plot(x,y, 'k-')
plt.show()

You need to add some methods after setting up the Basemap to draw the map features. Eg:
map.drawcoastlines()
map.drawstates()
map.drawcountries()
map.drawmapboundary()
See the documentation: http://matplotlib.org/basemap/users/geography.html

Related

Griddata and Contourf produce artifacts with increasing steps/levels

I am using SciPy Griddata to interpolate data in its Cartesian form and then plot these data using contourf with a polar projection. When the Cartesian interpolated data is plotted with contourf there are no artifacts. However, when the projection is polar, artifacts develop with increasing "levels".
The artifacts are polygons or rays that form near regions of steep gradients. The code below plots the brightness of the sky with the moon. With graphlevels of "12" there isn't an issue. Artifacts develop with graphlevel of "25." My desired level is 80 or more - which shows terrible artifacts. The below is example real data from one night. These artifacts always occur. See images with Levels = 12 and Levels = 80
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata
gridsize =150
graphlevels =12
plt.figure(figsize=(12,10))
ax = plt.subplot(111,projection='polar')
x = [72.90,68.00,59.14,44.38,29.63,63.94,59.68,51.92,38.98,26.03,47.34,44.20,38.46,28.89,19.31,23.40,20.40,15.34,10.28,-0.18,-0.14,-0.09,-0.04,0.02,-25.39,-23.66,-20.57,-15.40,-10.23,-47.56,-44.34,-38.54,-28.89,-19.22,-64.01,-59.68,-51.89,-38.90,-25.90,-72.77,-67.84,-58.98,-44.21,-29.44,-72.75,-67.83,-58.96,-44.18,-29.41,-59.63,-51.82,-38.83,-25.84,-47.42,-44.20,-38.40,-28.76,-19.12,-23.40,-20.32,-15.19,-10.08,0.27,0.25,0.23,0.20,23.92,20.80,15.63,10.46,47.93,44.67,38.86,29.17,19.48,64.40,60.03,52.20,39.18,26.15,73.08,68.12,59.26,44.47,29.68,-4.81]
y = [12.93,12.01,10.38,7.67,4.99,37.03,34.49,29.93,22.33,14.77,56.60,52.75,45.82,34.26,22.72,64.60,56.14,42.02,27.90,73.66,68.67,59.68,44.68,29.68,69.12,64.45,56.00,41.92,27.84,56.26,52.45,45.56,34.08,22.61,36.59,34.11,29.61,22.11,14.62,12.48,11.62,10.04,7.43,4.83,-13.33,-12.31,-10.78,-8.21,-5.58,-34.84,-30.36,-22.87,-15.36,-57.04,-53.20,-46.31,-34.83,-23.34,-65.20,-56.72,-42.62,-28.53,-69.33,-60.31,-45.31,-30.31,-65.09,-56.63,-42.55,-28.47,-56.81,-52.99,-46.13,-34.69,-23.23,-36.99,-34.53,-30.08,-22.66,-15.22,-12.73,-11.93,-10.44,-7.94,-5.40,-1.22,]
skybrightness = [19.26,19.31,19.21,19.65,19.40,19.26,19.23,19.43,19.57,19.52,19.19,19.31,19.33,19.68,19.50,19.29,19.45,19.50,19.23,18.98,19.28,19.46,19.54,19.22,19.03,19.18,19.35,19.37,19.08,18.99,18.98,19.26,19.36,19.08,18.79,18.85,19.13,19.17,19.05,18.51,18.64,18.88,18.92,18.93,18.12,18.34,18.72,18.82,18.74,18.22,18.46,18.76,18.26,18.13,18.24,18.46,18.58,17.30,18.38,18.08,18.24,17.68,18.34,18.46,18.65,18.23,18.70,18.52,18.79,18.83,18.18,18.51,19.01,19.08,19.08,18.99,19.02,19.07,19.20,19.27,19.06,19.01,19.28,19.46,19.30,18.94]
xgrid = np.linspace(min(x), max(x),gridsize)
ygrid = np.linspace(min(y), max(y),gridsize)
xgrid, ygrid = np.meshgrid(xgrid, ygrid, indexing='ij')
nsb_grid = griddata((x,y),skybrightness,(xgrid, ygrid), method='linear')
r = np.sqrt(xgrid**2 + ygrid**2)
theta = np.arctan2(ygrid, xgrid)
plt.rc('ytick', labelsize=16)
ax.set_facecolor('#eeddcc')
colors = plt.cm.get_cmap('RdYlBu')
levels,steps = np.linspace(min(skybrightness), max(skybrightness)+0.3,graphlevels, retstep=True)
ticks = np.linspace(min(skybrightness), max(skybrightness)+0.3,12)
cax = ax.contourf(theta, r, nsb_grid, levels=levels, cmap=colors)
cbar = plt.colorbar(cax, fraction=0.046, pad=0.04, ticks=ticks)
cbar.set_label(r'mag/arcsec$^2$')
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
ax.set_rmax(75)
ax.set_yticks(range(10, 80, 20))
ax.set_xticklabels([r'N', r'NE', r'E', r'SE', r'S', r'SW', r'W', r'NW'])
ax.grid(alpha=0.3)
plt.savefig('StackOverflowHELP.png')
I am going to leave my question and this answer on StackOverflow... because I did get an answer from the developers of Matploblib. The problem is Contourf . In its attempt to project data in polar dimensions there are overlaps and extensions of polygons at the cyclic boundaries that cause problems. The only way to avoid this is to add points at the boundary. To quote the developer:
The workaround is a lot of effort and has to be tuned to each particular problem, so is a very long way from being ideal. We (Matplotlib) should do better in these situations. Inserting extra points into the triangulation isn't the right approach, we should instead correct the lines/polygons that traverse the discontinuity to provide a general solution.
See https://github.com/matplotlib/matplotlib/issues/20060 for the full discussion
The answer I settled on is to interpolate and render the result in Cartesian space. Then I format an empty polar plot with axes and labels to overlay on the top... and get on with my life!
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata
gridsize =150
graphlevels = 200
fig = plt.figure(figsize=(12,10))
ax = fig.add_subplot(111, aspect='equal')
pax = fig.add_subplot(111,projection='polar')
pax.set_facecolor('none')
ax.set_axis_off()
ax.set_xlim([-75,75])
ax.set_ylim([-75,75])
x = [72.90,68.00,59.14,44.38,29.63,63.94,59.68,51.92,38.98,26.03,47.34,44.20,38.46,28.89,19.31,23.40,20.40,15.34,10.28,-0.18,-0.14,-0.09,-0.04,0.02,-25.39,-23.66,-20.57,-15.40,-10.23,-47.56,-44.34,-38.54,-28.89,-19.22,-64.01,-59.68,-51.89,-38.90,-25.90,-72.77,-67.84,-58.98,-44.21,-29.44,-72.75,-67.83,-58.96,-44.18,-29.41,-59.63,-51.82,-38.83,-25.84,-47.42,-44.20,-38.40,-28.76,-19.12,-23.40,-20.32,-15.19,-10.08,0.27,0.25,0.23,0.20,23.92,20.80,15.63,10.46,47.93,44.67,38.86,29.17,19.48,64.40,60.03,52.20,39.18,26.15,73.08,68.12,59.26,44.47,29.68,-4.81]
y = [12.93,12.01,10.38,7.67,4.99,37.03,34.49,29.93,22.33,14.77,56.60,52.75,45.82,34.26,22.72,64.60,56.14,42.02,27.90,73.66,68.67,59.68,44.68,29.68,69.12,64.45,56.00,41.92,27.84,56.26,52.45,45.56,34.08,22.61,36.59,34.11,29.61,22.11,14.62,12.48,11.62,10.04,7.43,4.83,-13.33,-12.31,-10.78,-8.21,-5.58,-34.84,-30.36,-22.87,-15.36,-57.04,-53.20,-46.31,-34.83,-23.34,-65.20,-56.72,-42.62,-28.53,-69.33,-60.31,-45.31,-30.31,-65.09,-56.63,-42.55,-28.47,-56.81,-52.99,-46.13,-34.69,-23.23,-36.99,-34.53,-30.08,-22.66,-15.22,-12.73,-11.93,-10.44,-7.94,-5.40,-1.22,]
skybrightness = [19.26,19.31,19.21,19.65,19.40,19.26,19.23,19.43,19.57,19.52,19.19,19.31,19.33,19.68,19.50,19.29,19.45,19.50,19.23,18.98,19.28,19.46,19.54,19.22,19.03,19.18,19.35,19.37,19.08,18.99,18.98,19.26,19.36,19.08,18.79,18.85,19.13,19.17,19.05,18.51,18.64,18.88,18.92,18.93,18.12,18.34,18.72,18.82,18.74,18.22,18.46,18.76,18.26,18.13,18.24,18.46,18.58,17.30,18.38,18.08,18.24,17.68,18.34,18.46,18.65,18.23,18.70,18.52,18.79,18.83,18.18,18.51,19.01,19.08,19.08,18.99,19.02,19.07,19.20,19.27,19.06,19.01,19.28,19.46,19.30,18.94]
xgrid = np.linspace(min(x), max(x),gridsize)
ygrid = np.linspace(min(y), max(y),gridsize)
xgrid, ygrid = np.meshgrid(xgrid, ygrid, indexing='ij')
nsb_grid = griddata((x,y),skybrightness,(xgrid, ygrid), method='linear')
plt.rc('ytick', labelsize=16) #colorbar font
colors = plt.cm.get_cmap('RdYlBu')
levels,steps = np.linspace(min(skybrightness), max(skybrightness)+0.3,graphlevels, retstep=True)
ticks = np.linspace(min(skybrightness), max(skybrightness)+0.3,12)
cax = ax.contourf(xgrid, ygrid, nsb_grid, levels=levels, cmap=colors)
cbar = plt.colorbar(cax, fraction=0.046, pad=0.04, ticks=ticks)
cbar.set_label(r'mag/arcsec$^2$')
pax.set_theta_zero_location('N')
pax.set_theta_direction(-1)
pax.set_rmax(75)
pax.set_yticks(range(10, 80, 20))
pax.set_xticklabels([r'N', r'NE', r'E', r'SE', r'S', r'SW', r'W', r'NW'])
pax.grid(alpha=0.3)

Cartopy plotting extra points at poles when passed one at a time

When plotting an orthographic projection with some points on the other side of the globe, how come the first approach plots as expected, but the second takes all the points that would be on the other side of the globe and plots them at the pole of the projection? Is there a solution beyond filtering out the points that are out of sight, and if not what is the best way to do that for a pole at an arbitrary lon/lat (as opposed to the north pole, which is relatively trivial)?
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
projection = ccrs.Orthographic(0, 90)
transform = ccrs.Geodetic()
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection = projection)
ax.coastlines()
ax.set_global()
ax.gridlines()
npoints = 100
np.random.seed(71077345)
lon = np.random.sample(npoints) * 360
lat = np.random.sample(npoints) * 180 - 90
plt.plot(lon,
lat,
'ro',
alpha = 0.3,
transform = transform)
for i in range(npoints):
plt.plot(lon[i],
lat[i],
'b.',
alpha = 0.3,
transform = transform)
(Partial answer to the question)
To filter the points on the upper hemisphere, use this code
for i in range(npoints):
if lat[i]>=0:
# this plots points above/on equator
ccode = 'b^'
ax.plot( lon[i], lat[i],
ccode,
alpha = .3,
transform = ccrs.PlateCarree()
)
else:
# this skips points below equator
pass
This bug has been fixed in v0.19 and beyond by #1710.

Aligning data (contourf) on Basemap

I've started working with Basemap, which seems potentially very useful.
If I plot some global data on a latitude/longitude grid as filled contours, it works great: Iff I leave the lat_0 and lon_0 as zero. Once I change the center location, the map moves but the data doesn't. I would be grateful for advice.
I've created a simple version of the code I'm using, with some simple sample data that illustrates the problem. The values should be (are) large at the equator but small at the poles. If you run the code with lat_0 and lon_0 = 0, it works fine. But if you change the center location to a different coordinate, the same pattern/data is presented even though the map has moved.
from mpl_toolkits.basemap import Basemap, cm
import matplotlib.pyplot as plt
import numpy as np
# create data
lat = np.linspace(-90,90,num=180)
lon = np.linspace(-180,180,num=361)
h2o_north = np.linspace(1,65,num=90)
h2o_south = np.flipud(h2o_north)
h2o = np.append(h2o_north,h2o_south)
data = np.transpose(np.tile(h2o,(len(lon),1)))
# create figure and axes instances
fig = plt.figure(figsize=(10,10))
ax = fig.add_axes([0.1,0.1,0.8,0.8])
# create map
m = Basemap(projection='ortho',lon_0=-50,lat_0=50,resolution='l')
# draw coastlines and country boundaries
m.drawcoastlines()
m.drawcountries()
# draw parallels
parallels = np.arange(-90.,90,10.)
m.drawparallels(parallels)
# draw meridians
meridians = np.arange(180.,360.,10.)
m.drawmeridians(meridians)
ny = data.shape[0]
nx = data.shape[1]
lons, lats = m.makegrid(nx, ny) # get lat/lons of ny by nx evenly space grid
x, y = m(lons, lats) # compute map projection coordinates
# draw filled contours.
clevs = np.linspace(0,70,num=281)
cs = m.contourf(x,y,data,clevs,cmap=plt.cm.jet)
# colorbar
cbar = m.colorbar(cs,location='bottom',pad="5%",ticks=np.linspace(0,70,15))
cbar.set_label('Scale of the data')
plt.title('Some global data', fontsize=14)
Use np.meshgrid() to create the meshgrid of lon-lat, then, convert it to projection coordinates, and the data are ready to generate contours and plot.
Here is the working code:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
# data for z (2D array)
h2o_north = np.linspace(1, 65, num=90)
h2o_south = np.flipud(h2o_north)
h2o = np.append(h2o_north, h2o_south)
data = np.transpose(np.tile(h2o, (len(h2o_north), 1)))
# create figure and axes instances
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot()
# create basemap instance
m = Basemap(projection='ortho', lon_0=-50, lat_0=50, resolution='c', ax=ax)
# create meshgrid covering the whole globe with ...
# conforming dimensions of the `data`
lat = np.linspace(-90, 90, data.shape[0])
lon = np.linspace(-180, 180, data.shape[1])
xs, ys = np.meshgrid(lon, lat) # basic mesh in lon, lat (degrees)
x, y = m(xs, ys) # convert (lon,lat) to map (x,y)
# draw filled contours
clevs = np.linspace(0, np.max(data), 60)
cs = m.contourf(x, y, data, clevs, cmap=plt.cm.jet)
m.drawcoastlines()
m.drawcountries()
m.drawmeridians(range(-180, 180, 30))
m.drawparallels(range(-90, 90, 30))
# draw colorbar
cbar = m.colorbar(cs, location='bottom', pad="5%", ticks=np.linspace(0, np.max(data), 5))
cbar.set_label('Scale of the data')
plt.show()
The resulting plot:

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()

Plot only on continent in matplotlib

I am drawing a map using basemap from matplotlib. The data are spreaded all over the world, but I just want to retain all the data on the continent and drop those on the ocean. Is there a way that I can filter the data, or is there a way to draw the ocean again to cover the data?
There's method in matplotlib.basemap: is_land(xpt, ypt)
It returns True if the given x,y point (in projection coordinates) is over land, False otherwise. The definition of land is based upon the GSHHS coastline polygons associated with the class instance. Points over lakes inside land regions are not counted as land points.
For more information, see here.
is_land() will loop all the polygons to check whether it's land or not. For large data size, it's very slow. You can use points_inside_poly() from matplotlib to check an array of points quickly. Here is the code. It doesn't check lakepolygons, if you want remove points in lakes, you can add your self.
It took 2.7 seconds to check 100000 points on my PC. If you want more speed, you can convert the polygons into a bitmap, but it's a little difficult to do this. Please tell me if the following code is not fast enought for your dataset.
from mpl_toolkits.basemap import Basemap
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.nxutils as nx
def points_in_polys(points, polys):
result = []
for poly in polys:
mask = nx.points_inside_poly(points, poly)
result.extend(points[mask])
points = points[~mask]
return np.array(result)
points = np.random.randint(0, 90, size=(100000, 2))
m = Basemap(projection='moll',lon_0=0,resolution='c')
m.drawcoastlines()
m.fillcontinents(color='coral',lake_color='aqua')
x, y = m(points[:,0], points[:,1])
loc = np.c_[x, y]
polys = [p.boundary for p in m.landpolygons]
land_loc = points_in_polys(loc, polys)
m.plot(land_loc[:, 0], land_loc[:, 1],'ro')
plt.show()
The HYRY's answer won't work on new versions of matplotlib (nxutils is deprecated). I've made a new version that works:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from matplotlib.path import Path
import numpy as np
map = Basemap(projection='cyl', resolution='c')
lons = [0., 0., 16., 76.]
lats = [0., 41., 19., 51.]
x, y = map(lons, lats)
locations = np.c_[x, y]
polygons = [Path(p.boundary) for p in map.landpolygons]
result = np.zeros(len(locations), dtype=bool)
for polygon in polygons:
result += np.array(polygon.contains_points(locations))
print result
The simplest way is to use basemap's maskoceans.
If for each lat, lon you have a data and you want to
use contours:
After meshgrid and interpolation:
from scipy.interpolate import griddata as gd
from mpl_toolkits.basemap import Basemap, cm, maskoceans
xi, yi = np.meshgrid(xi, yi)
zi = gd((mlon, mlat),
scores,
(xi, yi),
method=grid_interpolation_method)
#mask points on ocean
data = maskoceans(xi, yi, zi)
con = m.contourf(xi, yi, data, cmap=cm.GMT_red2green)
#note instead of zi we have data now.
Update (much faster than in_land or in_polygon solutions):
If for each lat, lon you don't have any data, and you just want to scatter the points only over land:
x, y = m(lons, lats)
samples = len(lons)
ocean = maskoceans(lons, lats, datain=np.arange(samples),
resolution='i')
ocean_samples = np.ma.count_masked(ocean)
print('{0} of {1} points in ocean'.format(ocean_samples, samples))
m.scatter(x[~ocean.mask], y[~ocean.mask], marker='.', color=colors[~ocean.mask], s=1)
m.drawcountries()
m.drawcoastlines(linewidth=0.7)
plt.savefig('a.png')
I was answering this question, when I was told that it would be better to post my answer over here. Basically, my solution extracts the polygons that are used to draw the coastlines of the Basemap instance and combines these polygons with the outline of the map to produce a matplotlib.PathPatch that overlays the ocean areas of the map.
This especially useful if the data is coarse and interpolation of the data is not wanted. In this case using maskoceans produces a very grainy outline of the coastlines, which does not look very good.
Here is the same example I posted as answer for the other question:
from matplotlib import pyplot as plt
from mpl_toolkits import basemap as bm
from matplotlib import colors
import numpy as np
import numpy.ma as ma
from matplotlib.patches import Path, PathPatch
fig, ax = plt.subplots()
lon_0 = 319
lat_0 = 72
##some fake data
lons = np.linspace(lon_0-60,lon_0+60,10)
lats = np.linspace(lat_0-15,lat_0+15,5)
lon, lat = np.meshgrid(lons,lats)
TOPO = np.sin(np.pi*lon/180)*np.exp(lat/90)
m = bm.Basemap(resolution='i',projection='laea', width=1500000, height=2900000, lat_ts=60, lat_0=lat_0, lon_0=lon_0, ax = ax)
m.drawcoastlines(linewidth=0.5)
x,y = m(lon,lat)
pcol = ax.pcolormesh(x,y,TOPO)
##getting the limits of the map:
x0,x1 = ax.get_xlim()
y0,y1 = ax.get_ylim()
map_edges = np.array([[x0,y0],[x1,y0],[x1,y1],[x0,y1]])
##getting all polygons used to draw the coastlines of the map
polys = [p.boundary for p in m.landpolygons]
##combining with map edges
polys = [map_edges]+polys[:]
##creating a PathPatch
codes = [
[Path.MOVETO] + [Path.LINETO for p in p[1:]]
for p in polys
]
polys_lin = [v for p in polys for v in p]
codes_lin = [c for cs in codes for c in cs]
path = Path(polys_lin, codes_lin)
patch = PathPatch(path,facecolor='white', lw=0)
##masking the data:
ax.add_patch(patch)
plt.show()
This produces the following plot:
Hope this is helpful to someone :)

Categories

Resources