我想使用contextily将OSM层添加到我用GeoPandas绘制的地图中。但是,在自动模式(默认)中使用zoom时,我遇到了某种随机错误。
MCVE
这是一个MCVE:
df = pd.DataFrame({"key": ["A"], "lon": [3.6], "lat": [43.4]})
point = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.lon, df.lat), crs=4326).to_crs(crs="ESRI:102014")
circle = point.geometry.buffer(3000)
axe = point.plot(color="red")
circle.plot(alpha=0.35, color="red", ax=axe)
ctx.add_basemap(axe, zoom="auto", crs=point.crs)不幸的是,由于瓷砖的URL不存在,所以失败了:
---------------------------------------------------------------------------
HTTPError Traceback (most recent call last)
File ~/.local/lib/python3.10/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 /usr/local/lib/python3.10/dist-packages/requests/models.py:1021, in Response.raise_for_status(self)
1020 if http_error_msg:
-> 1021 raise HTTPError(http_error_msg, response=self)
HTTPError: 404 Client Error: Not Found for url: https://stamen-tiles-a.a.ssl.fastly.net/terrain/14/8353/5993.png
During handling of the above exception, another exception occurred:
HTTPError Traceback (most recent call last)
Cell In [9], line 3
1 axe = point.plot(color="red")
2 circle.plot(alpha=0.35, color="red", ax=axe)
----> 3 ctx.add_basemap(axe, zoom="auto", crs=point.crs)
File ~/.local/lib/python3.10/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 ~/.local/lib/python3.10/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 /usr/local/lib/python3.10/dist-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 /usr/local/lib/python3.10/dist-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 /usr/local/lib/python3.10/dist-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 ~/.local/lib/python3.10/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 ~/.local/lib/python3.10/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/14/8353/5993.png有趣的是,它似乎与瓷砖的细节水平有关。因为如果我选择了一个具有更复杂几何学的点,它就会起作用:
df = pd.DataFrame({"key": ["A"], "lon": [3.7], "lat": [43.8]})或者,如果我将缩放缩小一个单位与原来的点:
ctx.add_basemap(axe, zoom=13, crs=point.crs)它也能工作(zoom=14是使它崩溃的值)。
分析
它似乎有一些问题,一些瓷砖没有呈现或映射到一个预期的contextily生成,因此404。
问题似乎与瓷砖本身的详细程度有关,因为:
选择一个包含很多细节的瓷砖使work;
问题
我没有足够的洞察力来区分它是否是contextily错误,或者它是否与瓷砖提供者有关。如何在防止404错误的同时仍然使用自动缩放模式?我能用提供程序的定义做些什么吗?为什么上下文不能在自动缩放模式下获取一些瓷砖?
发布于 2022-09-30 10:47:03
这不是contextily的问题。雄蕊地形(默认的瓷砖)没有一个均匀的覆盖,所以有些地方有很多缩放级别,而其他地方较少。你的观察也证明了这一点。因此,上下文自动计算预期的瓷砖,但不能知道这个地方没有提供它,因为其他一些地方有相同的缩放,所以tiles元数据表示允许级别14。如果使用不同的瓷砖,则相同的代码可以工作。
ctx.add_basemap(axe, zoom="auto", crs=point.crs, source=ctx.providers.OpenStreetMap.Mapnik)https://stackoverflow.com/questions/73906822
复制相似问题