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

Python 对非结构化THREDD数据进行子采样的简单、可编写脚本的方法?,python,matlab,thredds,opendap,Python,Matlab,Thredds,Opendap,我试图从THREDDS提供的三角网格模型中获取数据子集。我希望能够指定一个LAT/LON边界框,并从该框中获取数据。数据URL为: 有了网格化数据,就可以很容易地从THREDD服务器对数据进行子集划分。有没有人知道最好的方法是得到THREDD服务的三角形网格的子域 对于网格化数据,我使用Ferret作为OPeNDAP客户端,并且能够编写下载过程的脚本。我想在这里做一些类似的事情,尽管我可以使用Matlab、Python或其他工具 谢谢 SteveOpendap和NetCDF不允许使用不规则索引

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

有了网格化数据,就可以很容易地从THREDD服务器对数据进行子集划分。有没有人知道最好的方法是得到THREDD服务的三角形网格的子域

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

谢谢


Steve

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]
但如果我们在每一个时间步长上循环范围,速度会快得多:

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个timestep感兴趣(没有双关语),那么只需从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网格在非结构化网格中相对较小。例如,使用Atlantic scale ADCIRC网格可能会遇到问题


附言:当你得到lat和lon来确定你的子集指数时,你就抓住了整个网格。

谢谢。这很有帮助。我会试着根据这一点想出一些办法。目标是拥有一个带有子集的NetCDF文件。在雪貂中,创建一个只包含我感兴趣区域的温度和盐度的小文件非常简单:
save/file=myfile.nc/i=55:94/j=204:253 TEMP,sality
。我将使用您提供的内容,并尝试添加代码以保存到NetCDF。
time0 = time.time()
zi3 = ncv['zeta'][0, :]
zi3 = zi3[jj]
print('elapsed time: %d seconds' % (time.time() - time0))

elapsed time: 0 seconds