Matplotlib cartopy中shapefile的匹配投影

Matplotlib cartopy中shapefile的匹配投影,matplotlib,projection,cartopy,Matplotlib,Projection,Cartopy,我正在尝试使用matplotlib和cartopy制作Choropleth贴图,显然我需要先绘制一个shapefile。然而,我没有做到这一点,即使有人问了我一个类似的问题,我也没有做到。我怀疑投影或边界指定错误 我的形状文件有投影 PROJCS["WGS_1984_UTM_Zone_32Nz", GEOGCS["GCS_WGS_1984", DATUM["WGS_1984", SPHEROID["WGS_84",6378137,298.25722

我正在尝试使用matplotlib和cartopy制作Choropleth贴图,显然我需要先绘制一个shapefile。然而,我没有做到这一点,即使有人问了我一个类似的问题,我也没有做到。我怀疑投影或边界指定错误

我的形状文件有投影

PROJCS["WGS_1984_UTM_Zone_32Nz",
    GEOGCS["GCS_WGS_1984",
        DATUM["WGS_1984",
            SPHEROID["WGS_84",6378137,298.257223563]],
        PRIMEM["Greenwich",0],
        UNIT["Degree",0.017453292519943295]],
    PROJECTION["Transverse_Mercator"],
    PARAMETER["False_Easting",32500000],
    PARAMETER["False_Northing",0],
    PARAMETER["Central_Meridian",9],
    PARAMETER["Scale_Factor",0.9996],
    PARAMETER["Latitude_Of_Origin",0],
    UNIT["Meter",1]]
可以在我谈论的
vg250_2010-01-01.utm32w.shape.ebenen/vg250_ebenen-historisch/de1001/vg250_gem.shp的地方下载

我的代码是

#!/usr/local/bin/python
# -*- coding: utf8 -*-

import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
import matplotlib.pyplot as plt

fname = 'path/vg250_gem.shp'
proj = ccrs.TransverseMercator(central_longitude=0.0,central_latitude=0.0,
                           false_easting=32500000.0,false_northing=0.0,
                           scale_factor=0.9996)
municipalities = list(shpreader.Reader(fname).geometries())
ax = plt.axes(projection=proj)
plt.title('Deutschland')
ax.add_geometries(municipalities,proj,edgecolor='black',facecolor='gray',alpha=0.5)
ax.set_extent([32458044.649189778*0.9, 5556418.748046352*1.1, 32465287.307457082*0.9, 5564153.5456742775*1.1],proj)
plt.show()

使用菲奥娜的相应方法求出边界。Python抛出一个错误

Traceback (most recent call last):
  File "***/src/analysis/test.py", line 16, in <module>
ax.set_extent([32458044.649189778, 5556418.748046352, 32465287.307457082, 5564153.5456742775],proj)
  File "/usr/local/lib/python2.7/site-packages/cartopy/mpl/geoaxes.py", line 652, in set_extent
ylim=self.projection.y_limits))
ValueError: Failed to determine the required bounds in projection coordinates. Check that the values provided are within the valid range (x_limits=[-20000000.0, 20000000.0], y_limits=[-10000000.0, 10000000.0]).
[Finished in 53.9s with exit code 1]
回溯(最近一次呼叫最后一次):
文件“***/src/analysis/test.py”,第16行,在
ax.设置范围([32458044.649189778,5556418.748046352,32465287.307457082,5564153.5456742775],项目)
文件“/usr/local/lib/python2.7/site packages/cartopy/mpl/geoaxes.py”,第652行,在set_范围内
ylim=自投影y_极限)
ValueError:无法确定投影坐标中所需的边界。检查提供的值是否在有效范围内(x_限值=[-20000000.0,20000000.0],y_限值=[-10000000.0,10000000.0])。
[完成时间为53.9秒,退出代码为1]

这对我来说毫无意义。另外,使用ccrs.UTM()进行实验会得到一个显示白色区域的图。如果有人能告诉我如何解决这个问题,我将不胜感激。谢谢大家!

我发现了两个问题。一个是调用
set\u extent
时限制的规格不正确,指定的
[x0,x1,y0,y1]
应该是输入,您似乎已经给出了
[x0,y0,x1,y1]
。 另一个问题似乎是cartopy中的一个限制,正如我所能说的那样。看起来超出错误消息中列出的限制的投影总是会失败,并且这些限制是硬编码的。您只需编辑源代码(),将
-2e7
更改为
-4e7
,上限也是如此。在这些修复之后,将生成没有问题的绘图: 新的
set\u区段
行:

ax.set_extent([32458044.649189778*0.975, 32465287.307457082*1.025,5556418.748046352*0.9, 556415,3.5456742775*1.1],proj)
您可能还希望在您的
横切面编辑器中设置
中心经度=9.0
,这似乎是您的shapefile中指定的

我建议与开发人员联系,他们可能有很好的理由设置这些界限,或者他们可能有更好的解决方法,或者他们可能会在以后的版本中扩大界限

更新

您的边界似乎也仅基于
城市中的第一个城市设置:

In [34]: municipalities[0].bounds
Out[34]: (32458044.649189778, 5556418.748046352, 32465287.307457082, 5564153.5456742775)
但是其他元素有不同的界限。您可以根据所有
城市
边界的最小/最大值将限制刷新到实际图形

bnd = np.array([i.bounds for i in municipalities])
x0,x1 = np.min(bnd[:,0]),np.max(bnd[:,2])
y0,y1 = np.min(bnd[:,1]),np.max(bnd[:,3])
ax.set_extent([x0,x1,y0,y1],proj)

我不知道有关cartopy等的任何信息,但阅读错误消息中最后一行的下一行,列出了一些必需的x和y限制,但是调用
set\u extent
(导致错误的调用)中的限制超出了这些必需的限制。这就是我所说的“这对我来说没有意义”因为我使用菲奥娜提取了SeFFEFILE的边界。在上面,我尝试了
set\u extent
方法,包括完全删除这一行,但这也不起作用。不管给出了什么界限,它们都超出了cartopy愿意接受的界限。同样,我不熟悉这些包,但我注意到在构建
proj
时,您提供了一个32.5M的
false\u easting
。这可能会导致x方向的移动。在对
set_extent
的调用中,有两个接近32.5M的值可以通过这种偏移进行校正。查看cartopy的文档,
set\u extent
的输入是(x0,x1,y0,y1),但看起来您可能已经给出了(x0,y0,x1,y1),因此
false\u easting
不会让您回到可接受的范围。谢谢您的努力,@tsj。我不太明白为什么我用菲奥娜得到的SefFeFiele的边界并没有给我一个最小的可能的平方,这个国家是合适的。我上面的代码中是否(仍然)错误指定了投影?菲奥娜或卡托比有错吗?至少有一个不一致的地方?同样,仅仅是一个想法,+/-2e7从卡托比的角度来看应该足够了,因为地球的周长大约是40e6。也许有某种方法可以改变你的输入,使它被引用到-7.5e6而不是32.5e6,这样你就不必去编辑cartopy的源代码了。所以几何体方法实际上返回一个shapley对象,这就是为什么我可以调用
边界
,对吗?因为它返回
(x0,y0,x1,y1)
,而cartopy期望
(x0,x1,y0,y1)
,所以我需要按照您在代码片段中显示的那样重新组织。明白了,谢谢-很有魅力。