我正在尝试从THREDDS提供的三角形网格模型中获取数据的子集。我希望能够指定一个LAT / LON边界框,并从该框中获取数据。数据网址为:
http://www.smast.umassd.edu:8080/thredds/dodsC/FVCOM/NECOFS/Forecasts/NECOFS_MET_FORECAST.nc
使用网格化数据,很容易从THREDDS服务器对数据进行子集化。有谁知道最好的方法是获得由THREDDS服务的三角形网格的子域?
对于网格化数据,我使用Ferret作为我的OPeNDAP客户端,我可以编写下载过程的脚本。虽然我可以使用Matlab,Python或其他工具,但我想在这里做类似的事情。
谢谢,
史蒂夫
答案 0 :(得分:4)
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]
如果我们遍历每个索引,那就慢了:
# loop over indices, extracting time series
time0=time.time()
zi = np.zeros((len(tim),len(jj)))
k=0
for j in jj:
zi[:,k]=ncv['zeta'][:,j]
k +=1
print('elapsed time: %d seconds' % (time.time()-time0))
elapsed time: 56 seconds
但是如果我们在每个时间步都循环范围,它会快得多:
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
当然,结果可能会有所不同,具体取决于非结构化网格的大小,子集中各点的距离,提取的点数等等。但希望这可以让您了解所涉及的问题。
答案 1 :(得分:2)
如果你有严格的性能限制,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网格的问题。
POSTSCRIPT:无论如何,当你获得lat和lon以确定你的子集索引时,你正在抓住整个网格。