+-
我正在尝试将Lambert保形圆锥形卫星图像叠加到Holoviews交互式地图上.我可以很好地映射卫星图像,但是我不知道如何正确地将此地图转换为Holoviews地图.下面是可复制的代码,其中我使用Unidata Siphon库获取数据.
进口包
from datetime import datetime
import matplotlib.pyplot as plt
from netCDF4 import Dataset
from siphon.catalog import TDSCatalog
import holoviews as hv
import geoviews as gv
import geoviews.feature as gf
from cartopy import crs
from cartopy import feature as cf
hv.extension('bokeh')
抓取数据并创建图形
date=datetime.utcnow()
idx=-2
regionstr = 'CONUS'
channelnum = 13
datestr = str(date.year) + "%02d"%date.month + "%02d"%date.day
channelstr = 'Channel' + "%02d"%channelnum
cat = TDSCatalog('http://thredds-test.unidata.ucar.edu/thredds/catalog/satellite/goes16/GOES16/' + regionstr +
'/' + channelstr + '/' + datestr + '/catalog.xml')
ds = cat.datasets[idx].remote_access(service='OPENDAP')
x = ds.variables['x'][:]
y = ds.variables['y'][:]
z = ds.variables['Sectorized_CMI'][:]
proj_var = ds.variables[ds.variables['Sectorized_CMI'].grid_mapping]
# Create a Globe specifying a spherical earth with the correct radius
globe = ccrs.Globe(ellipse='sphere', semimajor_axis=proj_var.semi_major,
semiminor_axis=proj_var.semi_minor)
proj = ccrs.LambertConformal(central_longitude=proj_var.longitude_of_central_meridian,
central_latitude=proj_var.latitude_of_projection_origin,
standard_parallels=[proj_var.standard_parallel],
globe=globe)
fig = plt.figure(figsize=(14, 10))
ax = fig.add_subplot(1, 1, 1, projection=proj)
ax.coastlines(resolution='50m', color='lightblue')
ax.add_feature(cf.STATES, linestyle=':', edgecolor='lightblue')
ax.add_feature(cf.BORDERS, linewidth=1, edgecolor='lightblue')
for im in ax.images:
im.remove()
im = ax.imshow(z, extent=(x.min(), x.max(), y.min(), y.max()), origin='upper', cmap='jet')
plt.colorbar(im)
现在使用Holoviews(使用Bokeh后端)绘制交互式图像
goes = hv.Dataset((x, y, z),['Lat', 'Lon'], 'ABI13')
%opts Image (cmap='jet') [width=1000 height=800 xaxis='bottom' yaxis='left' colorbar=True toolbar='above' projection=proj]
goes.to.image()* gf.coastline().options(projection=crs.LambertConformal(central_longitude=proj_var.longitude_of_central_meridian,central_latitude=proj_var.latitude_of_projection_origin,standard_parallels=[proj_var.standard_parallel],globe=globe))
尽管我发现关于Holoviews的关于Lambert保形圆锥投影的文档很少,但我不能正确翻译它.我愿意使用任何其他交互式地图包.我的主要愿望是能够相对快速地绘图,在图像上正确地获得州/国家/地区的线条,并能够放大.我尝试过叶片,但在那里也遇到了投影问题.
最佳答案
因此,我认为要理解的主要问题(解释为 here:是如何声明投影)的. GeoViews中的元素(例如图像,点等)具有名为crs的参数,该参数声明数据所在的坐标系,而投影图选项则声明将数据投影到要显示的内容.
在您的情况下,我认为您想以与Lambert Conformal中已有的坐标系相同的坐标系显示图像,因此从技术上讲,您根本不必在元素上声明坐标系(crs),而可以使用hv.Image(完全不了解投影).
据我所知,如果您使用的是GeoViews 1.5,则您的代码应该已经可以按预期工作,但是我会这样做:
# Apply mask
masked = np.ma.filled(z, np.NaN)
# Declare image from data
goes = hv.Image((x, y, masked),['Lat', 'Lon'], 'ABI13')
# Declare some options
options = dict(width=1000, height=800, yaxis='left', colorbar=True,
toolbar='above', cmap='jet', projection=proj)
# Display plot
gf.ocean * gf.land * goes.options(**options) * gf.coastline.options(show_bounds=False)
注意我们如何声明图像上的投影,而不声明crs.如果确实要以定义的不同投影显示数据,则必须声明crs并使用gv.Image.在这种情况下,我建议在启用了fast选项的情况下使用project_image(这可能会引入一些工件,但速度要快得多):
# Apply mask
masked = np.ma.filled(z, np.NaN)
# Declare the gv.Image with the crs
goes = gv.Image((x, y, masked), ['Lat', 'Lon'], 'ABI13', crs=proj)
# Now regrid the data and apply the reprojection
projected_goes = gv.operation.project_image(goes, fast=False, projection=ccrs.GOOGLE_MERCATOR)
# Declare some options
options = dict(width=1000, height=800, yaxis='left', colorbar=True,
toolbar='above', cmap='jet')
# Display plot
projected_goes.options(**options) * gv.tile_sources.ESRI.options(show_bounds=False)
另一个最后的技巧是,当使用bokeh进行绘制时,所有要绘制的数据都将发送到浏览器,因此当处理比您已经使用的图像大的图像时,我建议使用holoviews的regrid操作,该操作使用datashader来动态调整大小缩放时的图像.要使用它,只需将操作应用于图像,如下所示:
from holoviews.operation.datashader import regrid
regridded = regrid(goes)
点击查看更多相关文章
转载注明原文:使用Python的交互式卫星地图 - 乐贴网