简单、可脚本化的方法对非结构化的THREDDS数据进行子采样?

2024-09-30 20:26:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图从THREDDS提供的三角网格模型中获取数据子集。我希望能够指定一个横向/纵向边界框,并从该框中获取数据。数据URL为:

http://www.smast.umassd.edu:8080/thredds/dodsC/FVCOM/NECOFS/Forecasts/NECOFS_MET_FORECAST.nc

有了网格数据,就可以很容易地将THREDDS服务器上的数据子集化。有没有人知道最好的方法是得到由THREDDS服务的三角形网格的子域?在

对于网格数据,我使用Ferret作为我的OPeNDAP客户端,并且我能够编写下载过程的脚本。虽然我可以使用Matlab、Python或其他工具,但我想在这里做一些类似的事情。在

谢谢

史蒂夫


Tags: 数据模型http网格urlwww子集边界
2条回答

Opendap和NetCDF不允许使用不规则索引进行提取。你只能要求开始,停止和大步前进。在

因为这是一个三角形网格,所以不能保证同一区域内三角形的节点具有相似的索引。因此,如果只想获取边界框中的这些节点,则必须逐个请求它们。这很慢。因此,在很多情况下,更快地确定最小和最大索引,并在一个块中请求整个块,然后根据需要提取索引。在

下面是python中这两种方法的示例比较。在本例中,提取包含所有索引的子集的速度大约是在每个索引上循环提取时间序列的速度的10倍:

import netCDF4
import time
import numpy as np

url='http://www.smast.umassd.edu:8080/thredds/dodsC/FVCOM/NECOFS/Forecasts/NECOFS_GOM3_FORECAST.nc'
nc = netCDF4.Dataset(url)
ncv = nc.variables
lon = ncv['lon'][:]
lat = ncv['lat'][:]
tim = ncv['time'][:]

# find indices inside box
box = [-71.4,41,-70.2,41.5]
ii = (lon>=box[0])&(lon<=box[2])&(lat>=box[1])&(lat<=box[3])
# jj will have just indices from inside the box:
jj = np.where(ii)[0]

如果我们对每个索引进行循环,则速度很慢:

^{pr2}$

但如果我们在每一个时间步循环该范围,它会快得多:

time0=time.time()
zi2 = np.zeros((len(tim),len(jj)))
jmin=jj.min()
jmax=jj.max()

for i in range(len(tim)):
    ztmp = ncv['zeta'][i,jmin:jmax+1]
    zi2[i,:] = ztmp[jj-jmin]
print('elapsed time: %d seconds' % (time.time()-time0))

elapsed time: 6 seconds

当然,结果可能会因非结构化网格的大小、子集中点的接近程度、正在提取的点的数量等而有所不同,但希望这能让您了解所涉及的问题。在

如果您的性能限制非常严格,Rich的回答提供了最好的方法。但是,正如他所说,结果可能因网格和子集区域而异。在

如果您一次只对1个时间步感兴趣(没有双关语),那么只需从dap服务器获取整个空间域就可以获得边际成本和更简单的代码:

time0 = time.time()
zi3 = ncv['zeta'][0, :]
zi3 = zi3[jj]
print('elapsed time: %d seconds' % (time.time() - time0))

elapsed time: 0 seconds

当分析时(即使在预先分配数组时),Rich所做的粗略最小/最大子集的速度大约是这个网格和特定空间子集的2倍。在非结构网格中,NECOFS网格相对较小。例如,您可能会遇到大西洋规模ADCIRC网格的问题。在

附言:当你得到lat和lon来确定你的子集索引时,你就是在抓取整个网格。在

相关问题 更多 >