cartopy icon indicating copy to clipboard operation
cartopy copied to clipboard

kwargs to ax.add_feature(BORDERS, **kwargs) is confusing

Open WeatherGod opened this issue 8 years ago • 6 comments

Description

ax.add_feature(BORDERS, **kwargs) is a bit confusing. There is nothing in the documentation explaining the nature of BORDERS. I was treating it like a MultiLineString when it seems that it is actually a MultiPolygon? So, some of the options I was trying to set was producing confusing and counter-intuitive results. Perhaps there should be some sort of kwarg fudging, or at least some more documentation about how these objects are treated?

See below my code to reproduce for what I mean.

Code to reproduce

import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.feature import BORDERS


lats = np.arange(25, 45)
lons = np.arange(-125, -60)
data = np.random.random((len(lats), len(lons)))

fig, ax = plt.subplots(subplot_kw={'projection': ccrs.LambertCylindrical()})
ax.imshow(data, extent=(lons[0], lons[-1], lats[0], lats[-1]),
          # Help make the outlines more visible
          vmin=-2, vmax=2)
ax.add_feature(BORDERS,
               # get white artifacts
               #color='w', linestyle=':', linewidth=1

               # get black dotted lines, no artifacts
               #color='w', linestyle=':'

               # get black solid lines, no artifacts
               #color='w', linewidth=1

               # What I really wanted, and couldn't figure out until
               # much trial & error
               edgecolor='w', linewidth=1, linestyle=':'
               )
plt.show()

Cartopy version

v0.15.1

WeatherGod avatar Feb 21 '18 16:02 WeatherGod

This looks like the same/similar issue as https://github.com/SciTools/cartopy/issues/803#issuecomment-366686339 which may be resolved by #1029.

ajdawson avatar Feb 21 '18 16:02 ajdawson

yes, that would probably be a significant help. Certainly would help make sense of why saying color='w' would sometimes work and sometimes not. Still might be nice to add some more documentation, but at least that would help cut down on unexpected behaviors.

WeatherGod avatar Feb 21 '18 16:02 WeatherGod

Thanks for the feedback @WeatherGod. I agree that the interaction between color and edgecolor / facecolor is ugly (it is a magnification of the underlying mpl ugliness).

With regards to the docs, the following is already available:

http://scitools.org.uk/cartopy/docs/latest/matplotlib/geoaxes.html?highlight=add_feature#cartopy.mpl.geoaxes.GeoAxes.add_feature

Adds the given Feature instance to the axes.

-> Following the Feature link through to:

http://scitools.org.uk/cartopy/docs/latest/matplotlib/feature_interface.html#cartopy.feature.Feature

Represents a collection of points, lines and polygons with convenience methods for common drawing and filtering operations.

So in answer to your question, it can be any simple geometry, not just one type (i.e. it is neither a MultiLineString or MultiPolygon).

Do you have a suggestion for how the docs might be improved in this?

pelson avatar Feb 21 '18 19:02 pelson

So, let's look at it from a user's point of view. When adding a coastline, one can just specify color='w', linewidth=1, linestyle=':', and it'll work just fine. Then when the user goes to do the same thing for a border feature, the same set of keywords doesn't work. That's something that the proposed fix will help with.

Now, let's look at it from another direction. You have the convenience method, .coastlines(). If you specify edgecolor='w', nothing (seems) to happen, it comes out black (ditto for facecolor). But, if you specify color='w', then it works! So, as a user, you see one approach that makes the feature act like line2d objects, but then another approach that seems to behave like polygon objects, but nothing in the documentation makes that clear.

WeatherGod avatar Feb 22 '18 20:02 WeatherGod

On master, in all the cases involving the color argument to add_feature where facecolor should not be set, you will now get the following warning:

UserWarning: facecolor will have no effect as it has been defined as "never".

If you are seeing this warning, it is because you are setting the matplotlib keyword argument color, which for add_geometries always means facecolor AND edgecolor. The feature you are adding is not allowed to have a facecolor (hence the "never"), so the correct approach is to simply change the color argument to edgecolor.

What remains of this issue is to improve the documentation to make it clear that FeatureArtist creates PathCollection objects, and it is therefore those kwargs that are allowed to be controlled.

pelson avatar Jan 10 '19 06:01 pelson

Just ran into this issue, and while @pelson's answer above is very explanatory, it's still a shame that the documentation doesn't specify which features do or do not support facecolor. From the features listed here, I've gathered:

Feature kwarg support
BORDERS  edgecolor
COASTLINE  edgecolor
LAKES  facecolor and edgecolor
LAND  facecolor and edgecolor
OCEAN  facecolor and edgecolor
RIVERS  edgecolor
STATES  edgecolor

Perhaps this is self-evident to others, but I found RIVERS quite surprising as some can be wider than lakes.

seangtkelley avatar Jun 25 '25 11:06 seangtkelley