kwargs to ax.add_feature(BORDERS, **kwargs) is confusing
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
This looks like the same/similar issue as https://github.com/SciTools/cartopy/issues/803#issuecomment-366686339 which may be resolved by #1029.
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.
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?
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.
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.
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.