第一篇 NC数据深度优先检索(Python)

第一篇 NC数据深度优先检索

NetCDF是UCAR开发的一种通用数据格式,可能做环境或者地学的人会比较熟悉。这种数据格式非常方便使用者读取和编辑,很多语言都可以对这种格式进行读写。这种格式会保留原有数据的长度、维度等信息,就像Python的.npy,matlab的.m和IDL的.sav文件一样。NetCDF以.nc格式对数据进行存储,所存储的数据结构可以用一个数表示[1]:

Stephen R Clark,https://www.researchgate.net/figure/The-hierarchical-group-structure-for-an-example-output-file-in-NetCDF-format-The-groups_fig4_308964752
树的根节点表示我们访问的nc文件,每一个子节点表示一个group,一个nc文件可能会包含很多group,而每一个group下面也可能包含很多新的group。这一个棵树的叶子就代表了该文件所储存的数据集,根节点和子节点都可以链接到很多数据集。所以,nc文件下存储的数据结构可能会很复杂,当我们知道所需数据的key(通常就是数据名称)的时候,便可以通过深度优先检索的方式对数据进行查找。

代码实现

Anaconda目前并没有自带netCDF4的库,所以首先我们需要自行安装这个库。和其他大部分库的安装一样,打开命令行窗口,键入:

pip install netCDF4

pip就会自动帮助你安装好netCDF4。

我一般会使用Spyder或者vim对脚本进行编辑,我们需要先导入所需要的库:

import netCDF4 as nc
from numpy import *

然后我们定义一个类,简单地来说这个类的核心就是一个栈,用来暂存我们在检索过程中遇到的节点,包括根节点和子节点。当我们对某一个节点检索,没有发现我们所要找的数据时,就从这个栈的栈尾取出一个节点继续检索。这个地方不明白的话可以先了解一下深度优先检索

class deep_search_nc:
    def __init__(self,nc_ob): #初始化,把根节点放入栈内
        self.ob_list_i = [nc_ob]
        self.ob_list = [nc_ob]
        
    def seek_for(self,varname):#单个数据集检索
        if self.ob_list == []:#检查是否空栈
            print('Cant find',varname)
            self.ob_list=self.ob_list_i.copy()
            return 1
        ob_temp = self.ob_list.pop()#从栈尾取出一个节点(并从栈尾删除)
        if ob_temp.get_variables_by_attributes(name = varname) != []:
        #判断节点内是否有目标数据集,有的话返回数据集
            self.ob_list=self.ob_list_i.copy()
            temp = ob_temp.variables[varname][:]
            if type(temp) == ma.core.MaskedArray:
                return temp.data.squeeze()
            elif type(temp) == ndarray:
                return temp.squeeze()
            else:
                print('unrecognized type',type(temp))
                return temp
        else:
        #没有找到目标数据集,递归调用继续检索
            for key in list(ob_temp.groups.keys()):
                self.ob_list.append(ob_temp.groups[key])
            return self.seek_for(varname)
        
    def seek_lot_for(self,varnames):#多个数据集检索
        if type(varnames) == str:
            varnames = [varnames]
        elif type(varnames) != list:
            print('wrong type of varnames!',varnames)
            return []
        return [self.seek_for(var) for var in varnames]

这个地方对函数进行了递归调用,这种方式可以使得代码的编写更加简洁。
下面举个例子,怎么使用这个检索工具。首先我们用nc.Dataset函数需要打开一个.nc文件,然后用它对我们的deep_search_nc类对象进行初始化,然后调用其中的seek_lot_for检索函数:

NC_file_ob = deep_search_nc(nc.Dataset(NC_file,'r'))#NC_file是目标文件路径,是一个字符串
nc_list= ['cloud_fraction_crb','cloud_pressure_crb','surface_pressure','surface_albedo','surface_albedo_nitrogendioxide_window','latitude_bounds','longitude_bounds','cloud_radiance_fraction_nitrogendioxide_window']
NC_file_ob.seek_lot_for(nc_list)#nc_list内包含了所有我们所想查找的数据集的key,通常来说就是变量名

参考资料

[1] https://www.researchgate.net/figure/The-hierarchical-group-structure-for-an-example-output-file-in-NetCDF-format-The-groups_fig4_308964752

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章