Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 使用Python中的pyresample重新采样二维空间数据(不同的原点和分辨率)后出现错误的空间信息_Python 3.x_Matplotlib_Geospatial_Resampling_Cartopy - Fatal编程技术网

Python 3.x 使用Python中的pyresample重新采样二维空间数据(不同的原点和分辨率)后出现错误的空间信息

Python 3.x 使用Python中的pyresample重新采样二维空间数据(不同的原点和分辨率)后出现错误的空间信息,python-3.x,matplotlib,geospatial,resampling,cartopy,Python 3.x,Matplotlib,Geospatial,Resampling,Cartopy,我需要定期对网格化(lon-lat)数据进行重采样,以获得分辨率较低、原点不同的新网格。我想我会用的 问题:在重新采样后,我得到的结果的空间位置明显错误。 在下面的示例中,我构造了一个简单的二维数组,其中包含一些空间网格(在sourcegrid中定义,它是一个sample AreaDefinition对象)和一些掩码,以便将其重采样到另一个targetgrid。空间信息在这个过程中丢失了,我不知道在哪里。。。有什么想法吗 import numpy as np from pyresample.ge

我需要定期对网格化(lon-lat)数据进行重采样,以获得分辨率较低、原点不同的新网格。我想我会用的

问题:在重新采样后,我得到的结果的空间位置明显错误。 在下面的示例中,我构造了一个简单的二维数组,其中包含一些空间网格(在
sourcegrid
中定义,它是一个
sample AreaDefinition
对象)和一些掩码,以便将其重采样到另一个
targetgrid
。空间信息在这个过程中丢失了,我不知道在哪里。。。有什么想法吗

import numpy as np
from pyresample.geometry import AreaDefinition
from pyresample.kd_tree import resample_nearest
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw

# Source data
lonmin = -10; lonmax = 10.; latmin=40.; latmax=60.; nlon = 300; nlat = 250
lon = np.linspace(lonmin, lonmax, nlon); lat = np.linspace(latmin, latmax, nlat)
dlon = lon[1] - lon[0]; dlat = lat[1] - lat[0]
lon2d, lat2d = np.meshgrid(lon, lat)
sourcedata = np.cos(np.deg2rad(lat2d)*100) + np.sin(np.deg2rad(lon2d)*100)

# Introduce a polygon as mask
xpol = [frac*(nlon-1) for frac in (0, 0.5, 0.4, 0.6, 0.9, 0., 0)]
ypol = [frac*(nlat-1) for frac in (0, 0.4, 0.6, 0.5, 1., 1., 0)]
polygon = [xy for xy in zip(xpol, ypol)]
img = Image.new('L', (nlon, nlat), 0)
ImageDraw.Draw(img).polygon(polygon, outline=1, fill=1)
mask = np.array(img)
xpol = [lon[int(x)] for x in xpol]; ypol = [lat[int(y)] for y in ypol] # translate in lon-lat for plot
sourcedata = np.ma.masked_where(mask, sourcedata)


# Define source and target areas
sourceextent = [lonmin-dlon/2, latmin-dlat/2, lonmax+dlon/2, latmax+dlat/2] # [xmin, ymin, xmax, ymax]
sourceextentforplot = [sourceextent[i] for i in (0,2,1,3)] # [xmin, xmax, ymin, ymax]
targetextent =  [lonmin-dlon/2 + 0.12*(lonmax-lonmin), latmin-dlat/2 + 0.24*(latmax-latmin),
                 lonmin-dlon/2 + 0.78*(lonmax-lonmin), latmin-dlat/2 + 0.91*(latmax-latmin)]
targetextentforplot = [targetextent[i] for i in (0,2,1,3)] 

sourcegrid = AreaDefinition(area_id='Grd1', description='Source Grid', proj_id='proj_id_blabla',
                            projection='EPSG:4326', width=nlon, height=nlat, area_extent=sourceextent)
# Lower resolution, different origin
targetgrid = AreaDefinition(area_id='Grd2', description='Target Grid', proj_id='proj_id_blabla',
                            projection='EPSG:4326', width=123, height=97, area_extent=targetextent)

# Resample sourcedata to newdata
newdata = resample_nearest(sourcegrid, sourcedata, targetgrid, fill_value=None, radius_of_influence=50000)

# Plot
def doplt(ax, data, extent):
    ax.coastlines(resolution='50m', color='gray', alpha=1., linewidth=2.)
    ax.gridlines(draw_labels=True)
    ax.imshow(data, origin='lower', transform=ccrs.PlateCarree(), extent=extent)
    ax.plot(xpol, ypol, 'k--', transform=ccrs.PlateCarree())
    ax.plot([targetextentforplot[x] for x in (0, 1, 1, 0, 0)], [targetextentforplot[y] for y in (2, 2, 3, 3, 2)],
            'r--', lw=3, transform=ccrs.PlateCarree())
    ax.set_extent([-12, 12, 38, 62])

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(5,10), subplot_kw={'projection': ccrs.PlateCarree()})

doplt(ax1, sourcedata, extent=sourceextentforplot)
ax1.set_title('Source data, target area in red')
doplt(ax2, newdata, extent=targetextentforplot)
ax2.set_title('New data, with wrong spatial ref (or plotting?)')

plt.show()


注意:除了
pyresample
之外,还可以使用其他建议来执行重采样操作,最好使用示例。

因此,问题在于您假设第0行是图像的底部,但如中所示,pyresample使用第0行作为顶部。我修改了您的示例以调整多边形纬度,并使用
origin='upper'
使用
imshow
进行绘图:

import numpy as np
from pyresample.geometry import AreaDefinition
from pyresample.kd_tree import resample_nearest
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw

# Source data
lonmin = -10; lonmax = 10.; latmin=40.; latmax=60.; nlon = 300; nlat = 250
lon = np.linspace(lonmin, lonmax, nlon); lat = np.linspace(latmin, latmax, nlat)
dlon = lon[1] - lon[0]; dlat = lat[1] - lat[0]
lon2d, lat2d = np.meshgrid(lon, lat)
sourcedata = np.hypot(lon2d, lat2d - 50) * (np.cos(np.deg2rad(lat2d)*100) + np.sin(np.deg2rad(lon2d)*100))

# Introduce a polygon as mask
xpol = [frac*(nlon-1) for frac in (0, 0.5, 0.4, 0.6, 0.9, 0., 0)]
ypol = [frac*(nlat-1) for frac in (0, 0.4, 0.6, 0.5, 1., 1., 0)]
polygon = [xy for xy in zip(xpol, ypol)]
img = Image.new('L', (nlon, nlat), 0)
ImageDraw.Draw(img).polygon(polygon, outline=1, fill=1)
mask = np.array(img)
xpol = [lon[int(x)] for x in xpol]; ypol = [lat[nlat - 1 - int(y)] for y in ypol] # translate in lon-lat for plot
sourcedata = np.ma.masked_where(mask, sourcedata)


# Define source and target areas
sourceextent = [lonmin-dlon/2, latmin-dlat/2, lonmax+dlon/2, latmax+dlat/2] # [xmin, ymin, xmax, ymax]
sourceextentforplot = [sourceextent[i] for i in (0,2,1,3)] # [xmin, xmax, ymin, ymax]
targetextent =  [lonmin-dlon/2 + 0.12*(lonmax-lonmin), latmin-dlat/2 + 0.24*(latmax-latmin),
                 lonmin-dlon/2 + 0.78*(lonmax-lonmin), latmin-dlat/2 + 0.91*(latmax-latmin)]
targetextentforplot = [targetextent[i] for i in (0,2,1,3)] 

sourcegrid = AreaDefinition(area_id='Grd1', description='Source Grid', proj_id='proj_id_blabla',
                            projection='EPSG:4326', width=nlon, height=nlat, area_extent=sourceextent)
# Lower resolution, different origin
targetgrid = AreaDefinition(area_id='Grd2', description='Target Grid', proj_id='proj_id_blabla',
                            projection='EPSG:4326', width=123, height=97, area_extent=targetextent)

# Resample sourcedata to newdata
newdata = resample_nearest(sourcegrid, sourcedata, targetgrid, fill_value=None, radius_of_influence=50000)

# Plot
def doplt(ax, data, extent):
    ax.coastlines(resolution='50m', color='gray', alpha=1., linewidth=2.)
    ax.gridlines(draw_labels=True)
    ax.imshow(data, transform=ccrs.PlateCarree(), extent=extent, norm=plt.Normalize(0, 20), origin='upper')
    ax.plot(xpol, ypol, 'k--', transform=ccrs.PlateCarree())
    ax.plot([targetextentforplot[x] for x in (0, 1, 1, 0, 0)], [targetextentforplot[y] for y in (2, 2, 3, 3, 2)],
            'r--', lw=3, transform=ccrs.PlateCarree())
    ax.set_extent([-12, 12, 38, 62])

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(5,10), subplot_kw={'projection': ccrs.PlateCarree()})

doplt(ax1, sourcedata, extent=sourceextentforplot)
ax1.set_title('Source data, target area in red')
doplt(ax2, newdata, extent=targetextentforplot)
ax2.set_title('New data, with wrong spatial ref (or plotting?)');
这就产生了:


我发现使用变化较大的图像有助于更好地与源数据对齐。

我发现使用
SwathDefinition
而不是
AreaDefinition
(请参阅)解决了这个问题

在原始代码中按如下方式定义
sourcegrid
targetgrid
,可获得良好的结果:

sourcegrid = SwathDefinition(lons=lon2d, lats=lat2d)
lon2dtarget, lat2dtarget = np.meshgrid(np.linspace(targetextent[0], targetextent[2], 123),
                                       np.linspace(targetextent[1], targetextent[3], 97))
targetgrid = SwathDefinition(lons=lon2dtarget, lats=lat2dtarget)

谢谢!我查一下。但是假设示例数据是空间数据,这里的结果将是错误的(空间信息仍然丢失)。那么,在这种情况下,我们是否应该在
pyresample
中执行任何操作之前,将它们在Lat维度上移动,然后再次转换它们?!你能否修改你的答案,使其与问题中的空间信息完全匹配(就好像它是一张地图,这里的国家是错误的)?我不确定你所说的“空间信息仍然丢失”是什么意思。我所做的唯一更改是,第0行是高纬度。这种排列方式与原始示例中的排列方式完全相同:它也是为
ImageDraw
指定的:实际上,这里的问题是如何从多边形坐标(以图像的分数表示)计算纬度,0的分数需要映射到
latmax
,不
latmin
。谢谢-对不起,我说得不清楚。我的意思是,如果我的原始数组是实际的空间数据,那么您的操作意味着“垂直翻转”(即,继续像您的解决方案那样覆盖大部分法国,而不是北海),但这只是一个翻转操作,至少
重采样
操作有效,您发现了问题-谢谢![同时,我发现使用
SwathDefinition
立即解决了问题…]