holoviz / geoviews

Simple, concise geographical visualization in Python
http://geoviews.org
BSD 3-Clause "New" or "Revised" License
587 stars 75 forks source link

Scale of NaturalEarthFeature is ignored (always plotting coarse) #56

Closed andreas-h closed 6 years ago

andreas-h commented 7 years ago

Using Geoviews 1.1.0, I have the problem that the scale of any NaturalEarthFeature from cartopy seems to be ignored.

from cartopy.feature import NaturalEarthFeature
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
%matplotlib inline
import holoviews as hv
import geoviews as gv
hv.notebook_extension()
import xarray as xr

I am using the sample data file from https://github.com/SciTools/iris-sample-data/blob/master/iris_sample_data/sample_data/E1_north_america.nc?raw=true

ds = xr.open_dataset('E1_north_america.nc')
arr = ds['air_temperature'][0]
gvds = gv.Dataset(
        arr.to_dataset(), kdims=['longitude', 'latitude'],
        vdims=['air_temperature'])

I define a function to return the correct coastline feature for a given scale, just to be sure to use the same objects in both matplotlib and geoviews cases:

def coastline(scale):
    return NaturalEarthFeature(
            category='physical', name='coastline', scale=scale,
            edgecolor='black', facecolor='none')

Using pure matplotlib, everything works as expected:

fig, axs = plt.subplots(
        figsize=(8, 15), nrows=3,
        subplot_kw=dict(projection=ccrs.PlateCarree()))

for ax, scale in zip(axs, ['10m', '50m', '110m']):
    arr.plot.pcolormesh(ax=ax, x='longitude', y='latitude', 
                    transform=ccrs.PlateCarree())
    ax.add_feature(coastline(scale))
    ax.set_title('Scale: {}'.format(scale))

img_matplotlib

However, when using Geoviews, it seems like always the 110m scale is displayed, even though I'm using a higher resolution feature:

%%output backend='matplotlib' size=450

def create_overlay(ds, scale):
    return hv.Overlay([
            ds.to(gv.Image, ['longitude', 'latitude']).relabel(scale),
            gv.Feature(coastline(scale)),
            ]).collate()

plots = [create_overlay(gvds, sc) for sc in ['10m', '50m', '110m']]
hv.Layout(plots).cols(1)

img_geoviews

philippjfr commented 7 years ago

You can control the scale of a feature by setting it as a plot option, e.g.

img = ds.to(gv.Image, ['longitude', 'latitude'])
hv.Layout([(img*gv.feature.coastline(plot=dict(scale=scale))).relabel(scale)
           for scale in ['10m', '50m', '110m']]).cols(1)

The reason why we ignore the scale set on the object itself is so you can reuse the same feature in multiple contexts with different scales.

andreas-h commented 7 years ago

Thanks! It would be helpful if this were mentioned in the documentation; especially at http://geo.holoviews.org/Geometries.html you have an example where you load the graticules from NaturalEarth and set the scale there (and not when plotting).

When doing it like you mention (which works fine), how do I control the linewidth of the coastline (without the %%opts magic)? Doing gv.feature.coastline(plot=dict(scale=scale, linewidth=1.5)) doesn't work for me (ValueError in line 148 of holoviews/ipython/display_hooks.pyc).

philippjfr commented 7 years ago

Thanks! It would be helpful if this were mentioned in the documentation; especially at http://geo.holoviews.org/Geometries.html you have an example where you load the graticules from NaturalEarth and set the scale there (and not when plotting).

Agreed, I'll leave the issue open until it's documented.

When doing it like you mention (which works fine), how do I control the linewidth of the coastline (without the %%opts magic)? Doing gv.feature.coastline(plot=dict(scale=scale, linewidth=1.5)) doesn't work for me (ValueError in line 148 of holoviews/ipython/display_hooks.pyc).

Have a look at the HoloViews Options Tutorial, basically we make a distinction between plot and style options, so what you want to do in this case is this:

gv.feature.coastline(plot=dict(scale=scale), style=dict(linewidth=1.5))

andreas-h commented 7 years ago

Wonderful, works like a charm -- thanks a lot!

poplarShift commented 5 years ago

I've just been stumbling over the same issue. The first example of http://geo.holoviews.org/Geometries.html about Features still leads one to believe that selecting a different scale in the call to cartopy's NaturalEarthFeature should change anything.

Now I wonder whether this is related to #254 @philippjfr ?