【问题标题】:Weather data over maps地图上的天气数据
【发布时间】:2018-08-31 13:31:10
【问题描述】:

我正在尝试在 Python 上使用 Basemap(我也愿意尝试 cartopy)在地图上绘制一些天气数据。现在,我的天气数据看起来像this。我的数据源基本上是一个数组,每个位置对应于网格的一个正方形,每个值表示该正方形应该是的颜色。用于生成此图像的代码如下所示,其中网格的每个正方形等于 1000 m:

grid_0 = np.asarray(dec.split())
grid_1=np.reshape(grid_0,(n_cols,n_rows))
grid_2 = grid_1.astype(float)

# Make plot
plt.figure(figsize=(30,30))
fig, ax = plt.subplots()

plt.axis('off')
cax = ax.imshow(grid_2, interpolation='nearest', cmap=cmap)

我有关于地理上网格下角所在位置的信息。我相信在地图上绘制它的最佳方法是以某种方式使用 contourf() 函数,但我对 Basemap 很陌生,无法找到将其转换为 contourf() 可以理解的方法的方法。绘制我正在使用 Basemap 的地图,其中 lon_air 和 lat_air 是某个机场的坐标:

fig=figure(1, figsize=(19, 15))

m = Basemap(projection='cyl', llcrnrlon=lon_air-25, llcrnrlat=lat_air-15,
            urcrnrlon=lon_air+25, urcrnrlat=lat_air+15, resolution='h', area_thresh=10000)

m.drawstates(linewidth=0.5, color='black', zorder=4)
m.drawcountries(linewidth=2.0, color='white', zorder=3)
m.drawmapboundary(fill_color='#e5f5ff')
m.fillcontinents(color='#DFDFDF', zorder=1)
m.scatter(lon_air, lat_air,marker='o',color='k', zorder=10)

x0, y0 = lon_air-((360*920)/(4*np.pi*6371)),lat_air-((360*920)/(4*np.pi*6371)) 
x1, y1 = lon_air+((360*920)/(4*np.pi*6371)), lat_air+((360*920)/(4*np.pi*6371)) 

im = plt.imshow(plt.imread('./pngs/9905.png'), extent=(x0, x1, y0, y1), zorder=2)
plt.show()

如果有人认为需要更多详细信息,我将编辑该帖子。在此先感谢大家!

【问题讨论】:

  • 分别生成天气数据和地图需要什么代码?如果我们能看到我们可能能够更好地帮助您合并两者
  • 正如 Aaron 所说,在问题中包含代码可以帮助您找到答案。看起来好像您正试图从提供的照片中绘制一些雷达数据。我会调查一下metpy (link to docs),看看里面是否有任何适用于你的东西。
  • 感谢你们的 cmets 伙计们,我编辑了我的问题,现在我会检查 MetPy :)

标签: python dictionary matplotlib-basemap weather contourf


【解决方案1】:

生成Basemap.contourf 图是一个非常标准的过程。您的plt.imread 命令应该返回一个二维numpy 数组(假设它是灰度),所以请执行以下操作来获取实际数据及其尺寸:

data = plt.imread('./pngs/9905.png')
lx, ly = data.shape

接下来,您需要为数据的每个点提供坐标。对于contourf,这是通过提供两个额外的 2D 字段完成的,一个带有 x 坐标,一个带有 y 坐标。您可以通过np.linspacenp.meshgrid 获得正确的表格:

lon0, lat0 = lon_air-((360*920)/(4*np.pi*6371)),lat_air-((360*920)/(4*np.pi*6371))
lon1, lat1 = lon_air+((360*920)/(4*np.pi*6371)), lat_air+((360*920)/(4*np.pi*6371))
lons = np.linspace(lon0, lon1, lx)  #1D
lats = np.linspace(lat0, lat1, ly)  #1D
lon, lat = np.meshgrid(lons,lats)   #1D --> 2D

现在您仍然需要将地图坐标转换为投影坐标,然后绘制整个坐标:

x,y = m(lon, lat)
m.contourf(x,y,data)
plt.show()

数据的排列可能仍然存在一些问题(有时有点令人困惑),因此您可能必须转置它(data.T)或反转维度(通过索引[::-1])。如果您遇到此类问题,请询问(或提供示例图像),然后我可以相应地调整答案。哦,记得加一个

import numpy as np

脚本开头的某处。

【讨论】:

  • 感谢 Thomas,这是我最接近所需产品的产品。图像不是黑白的,所以我得到了一个 3D 数组,我认为 lz=4 是导致我出现问题的原因。我设法打印了相同的 grid_3,但我得到了一个不应该存在的白色背景。当使用 fig = plt.figure() m = [...] x,y = m(lon, lat) m.contourf(x,y,data, zorder=10, cmap=cmap) img=plt.show( ) fig.savefig('./9905/each'.png') 我得到: ValueError: 操作数不能与形状一起广播 (993,1032,4) (1032,993) 和 data.t: 输入 z 必须是一个二维数组。
  • @GuillermoMorenoCastaño 如果您从plt.imread() 返回的数据的 z 维度为 4,这意味着您的图像是 rgba 图像,例如三个颜色通道和一个 Alpha 通道。在这种情况下,您首先需要考虑这些颜色和 alpha 在数据表示方面的含义。我的猜测是您的图像 已经 表示伪彩色图像(无论是等高线图还是其他),这意味着您可能只想将图像覆盖在地图上而不使用 @987654335 @ 完全...
  • ...here 讨论了Basemap.imshow() 的使用,但显然这只适用于圆柱地图。有什么方法可以将天气数据作为真实数据,而不是图像?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-11
  • 2011-06-25
  • 1970-01-01
  • 2013-06-14
  • 2019-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多