#----------------------------------------------------------------------------- # Copyright (c) 2012 - 2021, Anaconda, Inc., and Bokeh Contributors. # All rights reserved. # # The full license is in the file LICENSE.txt, distributed with this software. #----------------------------------------------------------------------------- ''' Pre-configured tile sources for common third party tile services. get_provider Use this function to retrieve an instance of a predefined tile provider. Args: provider_name (Union[str, Vendors, xyzservices.TileProvider]) Name of the tile provider to supply. Use a ``tile_providers.Vendors`` enumeration value, or the string name of one of the known providers. Use :class:`xyzservices.TileProvider` to pass custom tile providers. Returns: WMTSTileProviderSource: The desired tile provider instance Raises: ValueError, if the specified provider can not be found Example: .. code-block:: python >>> from bokeh.tile_providers import get_provider, Vendors >>> get_provider(Vendors.CARTODBPOSITRON) >>> get_provider('CARTODBPOSITRON') >>> import xyzservices.providers as xyz >>> get_provider(xyz.CartoDB.Positron) The available built-in tile providers are listed in the ``Vendors`` enum: .. bokeh-enum:: Vendors :module: bokeh.tile_providers :noindex: Any of these values may be be passed to the ``get_provider`` function in order to obtain a tile provider to use with a Bokeh plot. Representative samples of each tile provider are shown below. CARTODBPOSITRON --------------- Tile Source for CartoDB Tile Service .. raw:: html CARTODBPOSITRON_RETINA ---------------------- Tile Source for CartoDB Tile Service (tiles at 'retina' resolution) .. raw:: html ESRI_IMAGERY ------------ Tile Source for ESRI public tiles. .. raw:: html OSM --- Tile Source for Open Street Maps. .. raw:: html STAMEN_TERRAIN -------------- Tile Source for Stamen Terrain Service .. raw:: html STAMEN_TERRAIN_RETINA --------------------- Tile Source for Stamen Terrain Service (tiles at 'retina' resolution) .. raw:: html STAMEN_TONER ------------ Tile Source for Stamen Toner Service .. raw:: html STAMEN_TONER_BACKGROUND ----------------------- Tile Source for Stamen Toner Background Service which does not include labels .. raw:: html STAMEN_TONER_LABELS ------------------- Tile Source for Stamen Toner Service which includes only labels .. raw:: html ''' #----------------------------------------------------------------------------- # Boilerplate #----------------------------------------------------------------------------- from __future__ import annotations import logging # isort:skip log = logging.getLogger(__name__) #----------------------------------------------------------------------------- # Imports #----------------------------------------------------------------------------- # Standard library imports import sys import types # Bokeh imports from bokeh.core.enums import enumeration # Bokeh imports from .util.dependencies import import_optional #----------------------------------------------------------------------------- # Globals and constants #----------------------------------------------------------------------------- # __all__ defined at the bottom on the class module xyzservices = import_optional('xyzservices') #----------------------------------------------------------------------------- # General API #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Dev API #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Private API #----------------------------------------------------------------------------- class _TileProvidersModule(types.ModuleType): _CARTO_ATTRIBUTION = ( '© OpenStreetMap contributors,' '© CartoDB' ) _STAMEN_ATTRIBUTION = ( 'Map tiles by Stamen Design, ' 'under CC BY 3.0. ' 'Data by OpenStreetMap, ' 'under %s.' ) _OSM_ATTRIBTION = ( '© OpenStreetMap contributors' ) _WIKIMEDIA_ATTRIBUTION = ( '© Wikimedia Maps contributors' ) _ESRI_IMAGERY_ATTRIBUTION = ( '© Esri, ' 'Earthstar Geographics' ) _SERVICE_URLS = dict( CARTODBPOSITRON='https://tiles.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', CARTODBPOSITRON_RETINA='https://tiles.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png', STAMEN_TERRAIN='https://stamen-tiles.a.ssl.fastly.net/terrain/{Z}/{X}/{Y}.png', STAMEN_TERRAIN_RETINA='https://stamen-tiles.a.ssl.fastly.net/terrain/{Z}/{X}/{Y}@2x.png', STAMEN_TONER='https://stamen-tiles.a.ssl.fastly.net/toner/{Z}/{X}/{Y}.png', STAMEN_TONER_BACKGROUND='https://stamen-tiles.a.ssl.fastly.net/toner-background/{Z}/{X}/{Y}.png', STAMEN_TONER_LABELS='https://stamen-tiles.a.ssl.fastly.net/toner-labels/{Z}/{X}/{Y}.png', OSM='https://c.tile.openstreetmap.org/{Z}/{X}/{Y}.png', WIKIMEDIA='https://maps.wikimedia.org/osm-intl/{Z}/{X}/{Y}@2x.png', ESRI_IMAGERY='https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{Z}/{Y}/{X}.jpg' ) _STAMEN_ATTRIBUTION_URLS = dict( STAMEN_TERRAIN='CC BY SA', STAMEN_TERRAIN_RETINA='CC BY SA', STAMEN_TONER='ODbL', STAMEN_TONER_BACKGROUND='ODbL', STAMEN_TONER_LABELS='ODbL', ) Vendors = enumeration('CARTODBPOSITRON', 'CARTODBPOSITRON_RETINA', 'STAMEN_TERRAIN', 'STAMEN_TERRAIN_RETINA', 'STAMEN_TONER', 'STAMEN_TONER_BACKGROUND', 'STAMEN_TONER_LABELS', 'OSM','WIKIMEDIA','ESRI_IMAGERY', case_sensitive=True) def get_provider(self, provider_name): from bokeh.models import WMTSTileSource if isinstance(provider_name, WMTSTileSource): # This allows `get_provider(CARTODBPOSITRON)` to work return WMTSTileSource(url=provider_name.url, attribution=provider_name.attribution) if xyzservices and isinstance(provider_name, xyzservices.TileProvider): return WMTSTileSource( url=provider_name.build_url(scale_factor="@2x"), attribution=provider_name.html_attribution, min_zoom=provider_name.get("min_zoom", 0), max_zoom=provider_name.get("max_zoom", 30), ) selected_provider = provider_name.upper() if selected_provider not in self.Vendors: raise ValueError('Unknown tile provider %s' % provider_name) url = self._SERVICE_URLS[selected_provider] if selected_provider.startswith('CARTO'): attribution = self._CARTO_ATTRIBUTION elif selected_provider.startswith('STAMEN'): attribution = self._STAMEN_ATTRIBUTION % self._STAMEN_ATTRIBUTION_URLS[selected_provider] elif selected_provider.startswith('OSM'): attribution = self._OSM_ATTRIBTION elif selected_provider.startswith('WIKIMEDIA'): attribution = self._WIKIMEDIA_ATTRIBUTION elif selected_provider.startswith('ESRI_IMAGERY'): attribution = self._ESRI_IMAGERY_ATTRIBUTION else: raise RuntimeError('Can not retrieve attribution for %s' % selected_provider) return WMTSTileSource(url=url, attribution=attribution) # Properties -------------------------------------------------------------- CARTODBPOSITRON = Vendors.CARTODBPOSITRON CARTODBPOSITRON_RETINA = Vendors.CARTODBPOSITRON_RETINA STAMEN_TERRAIN = Vendors.STAMEN_TERRAIN STAMEN_TERRAIN_RETINA = Vendors.STAMEN_TERRAIN_RETINA STAMEN_TONER = Vendors.STAMEN_TONER STAMEN_TONER_BACKGROUND = Vendors.STAMEN_TONER_BACKGROUND STAMEN_TONER_LABELS = Vendors.STAMEN_TONER_LABELS OSM = Vendors.OSM WIKIMEDIA = Vendors.WIKIMEDIA ESRI_IMAGERY = Vendors.ESRI_IMAGERY #----------------------------------------------------------------------------- # Code #----------------------------------------------------------------------------- _mod = _TileProvidersModule("bokeh.tile_providers") _mod.__doc__ = __doc__ _mod.__all__ = ( 'CARTODBPOSITRON', 'CARTODBPOSITRON_RETINA', 'STAMEN_TERRAIN', 'STAMEN_TERRAIN_RETINA', 'STAMEN_TONER', 'STAMEN_TONER_BACKGROUND', 'STAMEN_TONER_LABELS', 'OSM', 'WIKIMEDIA', 'ESRI_IMAGERY', 'get_provider', 'Vendors' ) sys.modules['bokeh.tile_providers'] = _mod del _mod, sys, types