BUG: HTTPError for points close together
raybellwaves opened this issue · 0 comments
raybellwaves commented
Default source (cx.providers.Stamen.Terrain) gives HTTPError for points close together.
Another source works (e.g. cx.providers.Esri.NatGeoWorldMap) but a small zoom has to be specified (e.g. zoom=1).
Not sure if "auto" can handle this case.
import contextily as cx
import geopandas as gpd
import pandas as pd
df = pd.DataFrame(
data={
"lon": [24.061341666666667, 24.061378333333334],
"lat": [37.69585333333333, 37.69589],
}
)
gdf = gpd.GeoDataFrame(
df,
geometry=gpd.points_from_xy(df["lon"], df["lat"]),
crs="epsg:4326",
)
cx.add_basemap(gdf.plot(color="red", figsize=(16, 16)), crs=gdf.crs)
gives
/Users/ray/miniconda3/envs/test_env/lib/python3.9/site-packages/contextily/tile.py:581: UserWarning: The inferred zoom level of 25 is not valid for the current tile provider (valid zooms: 0 - 18).
warnings.warn(msg)
HTTPError Traceback (most recent call last)
File ~/miniconda3/envs/test_env/lib/python3.9/site-packages/contextily/tile.py:396, in _retryer(tile_url, wait, max_retries)
395 request = requests.get(tile_url, headers={"user-agent": USER_AGENT})
--> 396 request.raise_for_status()
397 except requests.HTTPError:
File ~/miniconda3/envs/test_env/lib/python3.9/site-packages/requests/models.py:960, in Response.raise_for_status(self)
959 if http_error_msg:
--> 960 raise HTTPError(http_error_msg, response=self)
HTTPError: 404 Client Error: Not Found for url: https://stamen-tiles-a.a.ssl.fastly.net/terrain/18/148592/101396.png
During handling of the above exception, another exception occurred:
HTTPError Traceback (most recent call last)
Input In [17], in <cell line: 1>()
----> 1 cx.add_basemap(gdf.plot(color="red", figsize=(16, 16)), crs=gdf.crs)
File ~/miniconda3/envs/test_env/lib/python3.9/site-packages/contextily/plotting.py:121, in add_basemap(ax, zoom, source, interpolation, attribution, attribution_size, reset_extent, crs, resampling, **extra_imshow_args)
117 left, right, bottom, top = _reproj_bb(
118 left, right, bottom, top, crs, {"init": "epsg:3857"}
119 )
120 # Download image
--> 121 image, extent = bounds2img(
122 left, bottom, right, top, zoom=zoom, source=source, ll=False
123 )
124 # Warping
125 if crs is not None:
File ~/miniconda3/envs/test_env/lib/python3.9/site-packages/contextily/tile.py:222, in bounds2img(w, s, e, n, zoom, source, ll, wait, max_retries)
220 x, y, z = t.x, t.y, t.z
221 tile_url = provider.build_url(x=x, y=y, z=z)
--> 222 image = _fetch_tile(tile_url, wait, max_retries)
223 tiles.append(t)
224 arrays.append(image)
File ~/miniconda3/envs/test_env/lib/python3.9/site-packages/joblib/memory.py:594, in MemorizedFunc.__call__(self, *args, **kwargs)
593 def __call__(self, *args, **kwargs):
--> 594 return self._cached_call(args, kwargs)[0]
File ~/miniconda3/envs/test_env/lib/python3.9/site-packages/joblib/memory.py:537, in MemorizedFunc._cached_call(self, args, kwargs, shelving)
534 must_call = True
536 if must_call:
--> 537 out, metadata = self.call(*args, **kwargs)
538 if self.mmap_mode is not None:
539 # Memmap the output at the first call to be consistent with
540 # later calls
541 if self._verbose:
File ~/miniconda3/envs/test_env/lib/python3.9/site-packages/joblib/memory.py:779, in MemorizedFunc.call(self, *args, **kwargs)
777 if self._verbose > 0:
778 print(format_call(self.func, args, kwargs))
--> 779 output = self.func(*args, **kwargs)
780 self.store_backend.dump_item(
781 [func_id, args_id], output, verbose=self._verbose)
783 duration = time.time() - start_time
File ~/miniconda3/envs/test_env/lib/python3.9/site-packages/contextily/tile.py:252, in _fetch_tile(tile_url, wait, max_retries)
250 @memory.cache
251 def _fetch_tile(tile_url, wait, max_retries):
--> 252 request = _retryer(tile_url, wait, max_retries)
253 with io.BytesIO(request.content) as image_stream:
254 image = Image.open(image_stream).convert("RGBA")
File ~/miniconda3/envs/test_env/lib/python3.9/site-packages/contextily/tile.py:399, in _retryer(tile_url, wait, max_retries)
397 except requests.HTTPError:
398 if request.status_code == 404:
--> 399 raise requests.HTTPError(
400 "Tile URL resulted in a 404 error. "
401 "Double-check your tile url:\n{}".format(tile_url)
402 )
403 elif request.status_code == 104:
404 if max_retries > 0:
HTTPError: Tile URL resulted in a 404 error. Double-check your tile url:
https://stamen-tiles-a.a.ssl.fastly.net/terrain/18/148592/101396.png
This works
cx.add_basemap(gdf.plot(color="red", figsize=(16, 16)), crs=gdf.crs, source=cx.providers.Esri.NatGeoWorldMap, zoom=1)