From c20110573044ef279122fcae2ab036feb72a8cee Mon Sep 17 00:00:00 2001 From: Dani Arribas-Bel Date: Sun, 5 Aug 2018 22:40:31 +0100 Subject: [PATCH 1/3] Adding add_attribution utility and placing it as default in all plotting methods --- contextily/__init__.py | 2 +- contextily/place.py | 19 +++++++++++++------ contextily/plotting.py | 40 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/contextily/__init__.py b/contextily/__init__.py index 0af5fc21..ac27af5e 100644 --- a/contextily/__init__.py +++ b/contextily/__init__.py @@ -5,6 +5,6 @@ from . import tile_providers as sources from .place import Place, plot_map from .tile import * -from .plotting import add_basemap +from .plotting import add_basemap, add_legend __version__ = '0.99.0.dev' diff --git a/contextily/place.py b/contextily/place.py index 2705c4cd..2d31c540 100644 --- a/contextily/place.py +++ b/contextily/place.py @@ -4,7 +4,7 @@ import matplotlib.pyplot as plt from warnings import warn from .tile import howmany, bounds2raster, bounds2img, _sm2ll, _calculate_zoom -from .plotting import ATTRIBUTION, INTERPOLATION, ZOOM +from .plotting import ATTRIBUTION, INTERPOLATION, ZOOM, add_attribution class Place(object): """Geocode a place by name and get its map. @@ -104,7 +104,7 @@ def _get_map(self): return im, bbox def plot(self, ax=None, zoom=ZOOM, interpolation=INTERPOLATION, - attribution_text = ATTRIBUTION): + attribution = ATTRIBUTION): """ Plot a `Place` object ... @@ -124,8 +124,8 @@ def plot(self, ax=None, zoom=ZOOM, interpolation=INTERPOLATION, [Optional. Default='bilinear'] Interpolation algorithm to be passed to `imshow`. See `matplotlib.pyplot.imshow` for further details. - attribution_text : str - [Optional. Default=''] Text to be added at the + attribution : str + [Optional. Defaults to standard `ATTRIBUTION`] Text to be added at the bottom of the axis. Returns @@ -152,6 +152,8 @@ def plot(self, ax=None, zoom=ZOOM, interpolation=INTERPOLATION, axisoff = True ax.imshow(im, extent=bbox, interpolation=interpolation) ax.set(xlabel="X", ylabel="Y") + if attribution: + add_attribution(ax, attribution) if title is not None: ax.set(title=title) if axisoff: @@ -163,7 +165,8 @@ def __repr__(self): self.place, self.n_tiles, self.zoom, self.im.shape[:2]) return s -def plot_map(place, bbox=None, title=None, ax=None, axis_off=True, latlon=True): +def plot_map(place, bbox=None, title=None, ax=None, axis_off=True, + latlon=True, attribution = ATTRIBUTION): """Plot a map of the given place. Parameters @@ -176,6 +179,9 @@ def plot_map(place, bbox=None, title=None, ax=None, axis_off=True, latlon=True): The axis on which to plot. If None, one will be created. axis_off : bool Whether to turn off the axis border and ticks before plotting. + attribution : str + [Optional. Default to standard `ATTRIBUTION`] Text to be added at the + bottom of the axis. Returns ------- @@ -208,7 +214,8 @@ def plot_map(place, bbox=None, title=None, ax=None, axis_off=True, latlon=True): ax.set(xlabel="X", ylabel="Y") if title is not None: ax.set(title=title) - + if attribution: + add_attribution(ax, attribution) if axis_off is True: ax.set_axis_off() return ax diff --git a/contextily/plotting.py b/contextily/plotting.py index b69ec19d..45ea949e 100644 --- a/contextily/plotting.py +++ b/contextily/plotting.py @@ -3,13 +3,15 @@ import numpy as np from . import tile_providers as sources from .tile import _calculate_zoom, bounds2img, _sm2ll +from matplotlib import patheffects -ATTRIBUTION = '' INTERPOLATION = 'bilinear' ZOOM = 'auto' +ATTRIBUTION = ("Map tiles by Stamen Design, under CC BY 3.0. "\ + "Data by OpenStreetMap, under ODbL.") def add_basemap(ax, zoom=ZOOM, url=sources.ST_TERRAIN, - interpolation=INTERPOLATION, attribution_text = ATTRIBUTION, + interpolation=INTERPOLATION, attribution = ATTRIBUTION, **extra_imshow_args): """ Add a (web/local) basemap to `ax` @@ -33,8 +35,8 @@ def add_basemap(ax, zoom=ZOOM, url=sources.ST_TERRAIN, [Optional. Default='bilinear'] Interpolation algorithm to be passed to `imshow`. See `matplotlib.pyplot.imshow` for further details. - attribution_text : str - [Optional. Default=''] Text to be added at the + attribution : str + [Optional. Defaults to standard `ATTRIBUTION`] Text to be added at the bottom of the axis. **extra_imshow_args : dict Other parameters to be passed to `imshow`. @@ -90,5 +92,35 @@ def add_basemap(ax, zoom=ZOOM, url=sources.ST_TERRAIN, # Plotting ax.imshow(image, extent=extent, interpolation=interpolation, **extra_imshow_args) + if attribution: + add_attribution(ax, attribution) return ax +def add_attribution(ax, att=ATTRIBUTION): + ''' + Utility to add attribution text + ... + + Arguments + --------- + ax : AxesSubplot + Matplotlib axis with `x_lim` and `y_lim` set in Web + Mercator (EPSG=3857) + att : str + [Optional. Defaults to standard `ATTRIBUTION`] Text to be added at the + bottom of the axis. + + Returns + ------- + ax : AxesSubplot + Matplotlib axis with `x_lim` and `y_lim` set in Web + Mercator (EPSG=3857) and attribution text added + ''' + minX, maxX = ax.get_xlim() + minY, maxY = ax.get_ylim() + ax.text(minX + (maxX - minX) * 0.005, + minY + (maxY - minY) * 0.005, + lic, size=8, + path_effects=[patheffects.withStroke(linewidth=2, + foreground="w")]) + return ax From 3af122fbcd2b79cddcf291d5307ba99d5206bc24 Mon Sep 17 00:00:00 2001 From: Dani Arribas-Bel Date: Sun, 5 Aug 2018 22:48:33 +0100 Subject: [PATCH 2/3] Durther minor edits for attribution functionality --- contextily/__init__.py | 2 +- contextily/plotting.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contextily/__init__.py b/contextily/__init__.py index ac27af5e..4bbf6dd0 100644 --- a/contextily/__init__.py +++ b/contextily/__init__.py @@ -5,6 +5,6 @@ from . import tile_providers as sources from .place import Place, plot_map from .tile import * -from .plotting import add_basemap, add_legend +from .plotting import add_basemap, add_attribution __version__ = '0.99.0.dev' diff --git a/contextily/plotting.py b/contextily/plotting.py index 45ea949e..b5e62a50 100644 --- a/contextily/plotting.py +++ b/contextily/plotting.py @@ -120,7 +120,7 @@ def add_attribution(ax, att=ATTRIBUTION): minY, maxY = ax.get_ylim() ax.text(minX + (maxX - minX) * 0.005, minY + (maxY - minY) * 0.005, - lic, size=8, + att, size=8, path_effects=[patheffects.withStroke(linewidth=2, foreground="w")]) return ax From 5e9709f6240f7e7e5c2fcaa681fe1f39c7ea1202 Mon Sep 17 00:00:00 2001 From: Dani Arribas-Bel Date: Sun, 5 Aug 2018 22:48:51 +0100 Subject: [PATCH 3/3] Adding test for attribution --- tests/test_ctx.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_ctx.py b/tests/test_ctx.py index b15034ab..1d4e5630 100644 --- a/tests/test_ctx.py +++ b/tests/test_ctx.py @@ -193,3 +193,7 @@ def test_add_basemap(): assert_array_almost_equal(ax.images[0].get_array().mean(), 184.10237852536648) +def test_attribution(): + f, ax = matplotlib.pyplot.subplots(1) + ax = ctx.add_attribution(ax, 'Test') +