Skip to content

Commit

Permalink
Unified WMTS element support across backends (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Feb 11, 2018
1 parent f1f2960 commit 5492589
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 83 deletions.
47 changes: 16 additions & 31 deletions geoviews/element/geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import numpy as np
from cartopy import crs as ccrs
from cartopy.feature import Feature as cFeature
from cartopy.io.img_tiles import GoogleTiles as cGoogleTiles
from cartopy.io.img_tiles import GoogleTiles
from cartopy.io.shapereader import Reader
from holoviews.core import Element2D, Dimension, Dataset as HvDataset, NdOverlay
from holoviews.core.util import basestring, pd, max_extents, dimension_range
Expand All @@ -29,7 +29,7 @@

from ..util import path_to_geom, polygon_to_geom

geographic_types = (cGoogleTiles, cFeature, BaseGeometry)
geographic_types = (GoogleTiles, cFeature, BaseGeometry)

def is_geographic(element, kdims=None):
"""
Expand Down Expand Up @@ -78,7 +78,7 @@ def __init__(self, data, kdims=None, vdims=None, **kwargs):
coord_sys = crs_data.coord_system()
if hasattr(coord_sys, 'as_cartopy_projection'):
crs = coord_sys.as_cartopy_projection()
elif isinstance(crs_data, (cFeature, cGoogleTiles)):
elif isinstance(crs_data, (cFeature, GoogleTiles)):
crs = crs_data.crs

supplied_crs = kwargs.get('crs', None)
Expand Down Expand Up @@ -138,51 +138,36 @@ def range(self, dim, data_range=True):

class WMTS(_GeoFeature):
"""
The WMTS Element represents a Web Map Tile Service
specified as a tuple of the API URL and
The WMTS Element represents a Web Map Tile Service specified as a
URL containing {x}, {y}, and {z} templating variables, e.g.:
https://maps.wikimedia.org/osm-intl/{Z}/{X}/{Y}@2x.png
"""

group = param.String(default='WMTS')

layer = param.String(doc="The layer on the tile service")

def __init__(self, data, kdims=None, vdims=None, **params):
if isinstance(data, tuple):
data = data
else:
data = (data,)

for d in data:
if WMTSTileSource and isinstance(d, WMTSTileSource):
if not 'crs' in params:
params['crs'] = ccrs.GOOGLE_MERCATOR
elif WebMapTileService and isinstance(d, WebMapTileService):
if 'crs' not in params and not self.crs:
raise Exception('Must supply coordinate reference '
'system with cartopy WMTS URL.')
elif not isinstance(d, basestring):
raise TypeError('%s data has to be a tile service URL'
% type(d).__name__)
elif not 'crs' in params:
params['crs'] = ccrs.GOOGLE_MERCATOR
if ((WMTSTileSource and isinstance(data, WMTSTileSource)) or
(GoogleTiles and isinstance(data, GoogleTiles))):
data = data.url
elif WebMapTileService and isinstance(data, WebMapTileService):
pass
elif not isinstance(data, basestring):
raise TypeError('%s data should be a tile service URL not a %s type.'
% (type(self).__name__, type(data).__name__) )
super(WMTS, self).__init__(data, kdims=kdims, vdims=vdims, **params)


class Tiles(_GeoFeature):
class Tiles(WMTS):
"""
Tiles represents an image tile source to dynamically
load data from depending on the zoom level.
"""

group = param.String(default='Tiles')

def __init__(self, data, kdims=None, vdims=None, **params):
if not isinstance(data, cGoogleTiles):
raise TypeError('%s data has to be a cartopy GoogleTiles type'
% type(data).__name__)
super(Tiles, self).__init__(data, kdims=kdims, vdims=vdims, **params)



class Dataset(_Element, HvDataset):
"""
Expand Down
20 changes: 4 additions & 16 deletions geoviews/plotting/bokeh/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,10 @@ def get_extents(self, element, ranges):
return extents

def get_data(self, element, ranges, style):
tile_source = None
for url in element.data:
if isinstance(url, util.basestring) and not url.endswith('cgi'):
try:
tile_source = WMTSTileSource(url=url)
break
except:
pass
elif isinstance(url, WMTSTileSource):
tile_source = url
break

if tile_source is None:
raise SkipRendering("No valid tile source URL found in WMTS "
"Element, rendering skipped.")
return {}, {'tile_source': tile_source}, style
if not isinstance(element.data, util.basestring):
SkipRendering("WMTS element data must be a URL string, "
"bokeh cannot render %r" % element.data)
return {}, {'tile_source': WMTSTileSource(url=element.data)}, style

def _update_glyph(self, renderer, properties, mapping, glyph):
allowed_properties = glyph.properties()
Expand Down
48 changes: 12 additions & 36 deletions geoviews/plotting/mpl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import numpy as np
import param
from cartopy import crs as ccrs
from cartopy.io.img_tiles import GoogleTiles

try:
from owslib.wmts import WebMapTileService
Expand Down Expand Up @@ -385,50 +386,25 @@ class WMTSPlot(GeoPlot):
Adds a Web Map Tile Service from a WMTS Element.
"""

style_opts = ['alpha', 'cmap', 'interpolation', 'visible',
'filterrad', 'clims', 'norm']

def get_data(self, element, ranges, style):
if WebMapTileService is None:
raise SkipRendering('WMTS element requires owslib and PIL '
'to be installed.')
tile_source = None
for url in element.data:
if isinstance(url, util.basestring):
try:
tile_source = WebMapTileService(url)
break
except:
pass
elif isinstance(url, WebMapTileService):
tile_source = url
break

if tile_source is None:
raise SkipRendering("No valid tile source URL found in WMTS "
"Element, rendering skipped.")
return (tile_source, element.layer), style, {}

def init_artists(self, ax, plot_args, plot_kwargs):
return {'artist': ax.add_wmts(*plot_args, **plot_kwargs)}


class TilePlot(GeoPlot):
"""
Draws image tiles specified by a Tiles Element.
"""

zoom = param.Integer(default=8, doc="""
Controls the zoom level of the tile source.""")

style_opts = ['alpha', 'cmap', 'interpolation', 'visible',
'filterrad', 'clims', 'norm']

def get_data(self, element, ranges, style):
return (element.data, self.zoom), style, {}
if isinstance(element.data, util.basestring):
tile_source = GoogleTiles(url=element.data)
return (tile_source, self.zoom), style, {}
else:
tile_source = element.data
return (tile_source, element.layer), style, {}

def init_artists(self, ax, plot_args, plot_kwargs):
return {'artist': ax.add_image(*plot_args, **plot_kwargs)}
if isinstance(plot_args[0], GoogleTiles):
return {'artist': ax.add_image(*plot_args, **plot_kwargs)}
return {'artist': ax.add_wmts(*plot_args, **plot_kwargs)}



class GeoAnnotationPlot(AnnotationPlot):
Expand Down Expand Up @@ -480,7 +456,7 @@ def draw_annotation(self, axis, data, crs, opts):
Image: GeoImagePlot,
Feature: FeaturePlot,
WMTS: WMTSPlot,
Tiles: TilePlot,
Tiles: WMTSPlot,
Points: GeoPointPlot,
Text: GeoTextPlot,
Layout: LayoutPlot,
Expand Down

0 comments on commit 5492589

Please sign in to comment.