SciTools / cartopy

Cartopy - a cartographic python library with matplotlib support
https://scitools.org.uk/cartopy/docs/latest
BSD 3-Clause "New" or "Revised" License
1.44k stars 368 forks source link

Gallery addition: Contour plot with high res US State boundaries #1366

Open djgagne opened 5 years ago

djgagne commented 5 years ago

Description

One common weather plot missing from the gallery is a contour plot of a typical weather field, like temperature or winds with high resolution US state boundaries and coastlines. I suspect that a fair number of the Basemap users that have not switched over have waited because it requires knowing the web addresses of the state boundaries datasets to plot them in Cartopy whereas with Basemap you can just call the drawstates command.

I can post some example code tomorrow as a starting point for the example.

Code to reproduce

Traceback

Full environment definition ### Operating system ### Cartopy version ### conda list ``` ``` ### pip list ``` ```
greglucas commented 5 years ago

You shouldn't need to know the web address for the high-resolution states/coastlines. The tricky part is realizing that Cartopy can get these for you and what resolutions are even available to the user. See this example for feature creation. There should probably be a more clear example of what you're looking to do though. https://scitools.org.uk/cartopy/docs/latest/gallery/feature_creation.html#sphx-glr-gallery-feature-creation-py

For example, to get different resolutions you can just make a bunch of features.

import matplotlib.pyplot as plt

import cartopy.crs as ccrs
import cartopy.feature as cfeature

scale = '10m'
states10 = cfeature.NaturalEarthFeature(
            category='cultural',
            name='admin_1_states_provinces_lines',
            scale=scale,
            facecolor='none',
            edgecolor='g')

scale = '50m'
states50 = cfeature.NaturalEarthFeature(
            category='cultural',
            name='admin_1_states_provinces_lines',
            scale=scale,
            facecolor='none',
            edgecolor='b')

scale = '110m'
states110 = cfeature.NaturalEarthFeature(
            category='cultural',
            name='admin_1_states_provinces_lines',
            scale=scale,
            facecolor='none',
            edgecolor='r')

fig, ax = plt.subplots(figsize=(10, 10), subplot_kw={"projection": ccrs.PlateCarree()})

ax.add_feature(states110, zorder=1, linewidth=1.5)
ax.add_feature(states50, zorder=2, linewidth=1.5)
ax.add_feature(states10, zorder=3, linewidth=1.5)

ax.set_extent([-95, -90, 30, 35], crs=ccrs.PlateCarree())
ax.text(-93, 34, '110m', c='r', size=20)
ax.text(-93, 33.75, '50m', c='b', size=20)
ax.text(-93, 33.5, '10m', c='g', size=20)

image

dopplershift commented 5 years ago

It's actually easier than that. As of 0.16, STATES is a baked in feature (using the admin_1_states_provinces_lakes instead of admin_1_states_provinces_lines):

import matplotlib.pyplot as plt

import cartopy.crs as ccrs
import cartopy.feature as cfeature

fig, ax = plt.subplots(figsize=(10, 10), subplot_kw={"projection": ccrs.PlateCarree()})

ax.add_feature(cfeature.STATES, zorder=1, linewidth=1.5, edgecolor='r')
ax.add_feature(cfeature.STATES.with_scale('50m'), zorder=2, linewidth=1.5, edgecolor='b')
ax.add_feature(cfeature.STATES.with_scale('10m'), zorder=3, linewidth=1.5, edgecolor='g')

ax.set_extent([-95, -90, 30, 35], crs=ccrs.PlateCarree())
ax.text(-93, 34, '110m', c='r', size=20)
ax.text(-93, 33.75, '50m', c='b', size=20)
ax.text(-93, 33.5, '10m', c='g', size=20)

The fact that neither of you were aware of this is a pretty damning indictment of the discoverability of the library and the quality of the docs, though.

mubali101 commented 1 year ago

@dopplershift why is it that scaling cfeature.STATES to 50 m starts plotting Canadian states too and scaling to 10 m will plot Mexican states, etc. Is there a way to only get high resolution US state boundaries?

dopplershift commented 1 year ago

That's all controlled by the Natural Earth dataset we use, it's not a decision made by us. If you wanted to filter only to US features, you'd have to do some manual parsing of the features. This example might be a useful starting point.

mubali101 commented 1 year ago

Thanks for the quick reply. Yes, the Katrina example is where I started with but I notice data misalignment around the coastlines when overlaying a filled contour map with a land mask. Therefore, it needs a high resolution underlying States.

I have managed a work around using regionmask package.