Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mask A Contour With Coastlines #2251

Open
SoundsSerious opened this issue Sep 27, 2023 · 3 comments
Open

Mask A Contour With Coastlines #2251

SoundsSerious opened this issue Sep 27, 2023 · 3 comments

Comments

@SoundsSerious
Copy link

SoundsSerious commented Sep 27, 2023

Hello,

I am in the process from switching from matplotlib.basemap to cartopy and the standout feature that is missing is the maskoceans / maskland feature set.

I see that there are ax.addFeature(LAND/OCEAN...) however this completely ruins the nice basemap I have included.

The data is already there, so how do we make a mask out of it. I understand that projection transforms are somewhat complicated but it should be doable ultimately.

Example of the map I am trying to make.
ECONOMICS_MODEL LCOE

Several requests for similar features, the only way to do this would be to plot twice and use PIL to mask the image from the LAND data
https://stackoverflow.com/questions/72078262/how-to-mask-data-that-appears-in-the-ocean-using-cartopy-and-matplotlib

@rcomer
Copy link
Member

rcomer commented Sep 28, 2023

From the basemap docs

mpl_toolkits.basemap.maskoceans(lonsin, latsin, datain, inlands=True, resolution='l', grid=5)(https://matplotlib.org/basemap/api/basemap_api.html#mpl_toolkits.basemap.maskoceans)
mask data (datain), defined on a grid with latitudes latsin longitudes lonsin so that points over water will not be plotted.

returns a masked array the same shape as datain with “wet” points masked.

So it seems this is about masking the input array rather than the plot itself?

There is an open WIP PR in Iris to mask data with a shapefile. Since Iris uses Cartopy underneath, it’s plausible that that could be adapted for inclusion in Cartopy (if Cartopy maintainers wanted it).
SciTools/iris#5470

Disclaimer: I am not a Cartopy maintainer nor have I been involved in that masking work. So I do not have authority to make decisions on either side!

cc @acchamber

@greglucas
Copy link
Contributor

I think this would be a nice feature to add to Cartopy! I think the request would be some way of making it easier to add a clip path to matplotlib. The Iris version is interesting though to do it via Shapely intersections first and create an entirely new object. I'm not sure what would be preferable (clip first through shapely, or keep all data intact and let the renderer do the clipping in matplotlib)

Here is a quick example of using the artist.set_clip_path() with the land natural earth feature. There are a few issues with it though: (1) it is quite verbose and not easy to parse what is going on, (2) the clipping does not respect the axes boundary when panning around (e.g. #2052), (3) it digs into private transform variables. I think all of these are probably not too hard to fix and make into a helper routine of some sort within Cartopy.

image

import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.mpl.patch import geos_to_path
from matplotlib import pyplot as plt
import matplotlib.path as mpath
import numpy as np

proj = ccrs.PlateCarree()

fig, (ax1, ax2) = plt.subplots(nrows=2, subplot_kw={"projection": proj})

xx, yy = np.meshgrid(np.linspace(-180, 180, 360), np.linspace(-90, 90, 180))
zz = xx**2 + yy**2

ax1.pcolormesh(xx, yy, zz)
mesh = ax2.pcolormesh(xx, yy, zz)

# Get the path of the land polygons
land_path = geos_to_path(list(cfeature.LAND.geometries()))
land_path = mpath.Path.make_compound_path(*land_path)
plate_carre_data_transform = proj._as_mpl_transform(ax2)
mesh.set_clip_path(land_path, plate_carre_data_transform)

ax1.coastlines()
ax2.coastlines()

plt.show()

@SoundsSerious
Copy link
Author

I agree this would be a really awesome feature to add to help display data in cartopy.

I think this could possibly be a suite of operations for grid based boolean operations, deciding what is inside or outside of a contour.

I have only just started with cartopy but your example helps alot!

I think this might be interesting as part of the feature call... if it returned a feature object that you could add on plot operations to such as oceans.inside.contourf(xx,yy,zz...) that ultimately aliased the mpl axis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants