Main Content

导入 NetCDF 文件和 OPeNDAP 数据

您可以使用多种方法从 netCDF 文件中读取数据。您可以通过编程方式使用 MATLAB® 高级 netCDF 函数或低级函数的 netCDF 库命名空间。您可以通过交互方式使用导入数据实时编辑器任务或(在 MATLAB Online™ 中)导入工具

MATLAB NetCDF 功能

网络通用数据表 (NetCDF) 是一组软件库及与机器无关的数据格式,支持创建、访问和共享面向数组的科学数据。NetCDF 广泛用于工程和科学领域,这些领域需要一种标准的数据存储方式,以便共享数据。

MATLAB 高级函数简化了从 NetCDF 文件或 OPeNDAP NetCDF 数据源导入数据的过程。MATLAB 低级函数通过提供对 NetCDF C 库中例程的访问权限来实现对导入过程的更多控制。要有效地使用低级函数,您应该熟悉 NetCDF C 接口。NetCDF 文档可在 Unidata 网站上获取。

注意

有关导入具有单独的、不兼容格式的通用数据格式 (CDF) 文件的信息,请参阅Import CDF Files Using Low-Level Functions

连接到 OPeNDAP 服务器时的安全注意事项

强烈建议您只连接到受信任的 OPeNDAP 服务器。自 R2020b 开始,默认情况下,MATLAB NetCDF 接口仅通过执行服务器证书和主机名验证连接到受信任的数据访问协议 (DAP) 端点。以前,当您访问 OPeNDAP 服务器时,默认情况下服务器证书和主机名验证都处于禁用状态。

如果要禁用服务器证书和主机名验证,请在当前目录的 .dodsrc 文件中添加以下行:

[mylocaltestserver.lab] HTTP.SSL.VALIDATE=0

这样,MATLAB NetCDF 接口会连接到在 URI mylocaltestserver.lab 中指定名称的 OPeNDAP 服务器,而无需对服务器证书或主机名执行任何验证。此更改将在以后的 MATLAB 会话中持续存在。

使用高级函数读取 NetCDF 文件

此示例说明如何使用高级函数显示和读取 NetCDF 文件的内容。

显示示例 NetCDF 文件 example.nc 的内容。

ncdisp('example.nc')
Source:
           \\matlabroot\toolbox\matlab\demos\example.nc
Format:
           netcdf4
Global Attributes:
           creation_date = '29-Mar-2010'
Dimensions:
           x = 50
           y = 50
           z = 5
Variables:
    avagadros_number
           Size:       1x1
           Dimensions: 
           Datatype:   double
           Attributes:
                       description = 'this variable has no dimensions'
    temperature     
           Size:       50x1
           Dimensions: x
           Datatype:   int16
           Attributes:
                       scale_factor = 1.8
                       add_offset   = 32
                       units        = 'degrees_fahrenheit'
    peaks           
           Size:       50x50
           Dimensions: x,y
           Datatype:   int16
           Attributes:
                       description = 'z = peaks(50);'
Groups:
    /grid1/
        Attributes:
                   description = 'This is a group attribute.'
        Dimensions:
                   x    = 360
                   y    = 180
                   time = 0     (UNLIMITED)
        Variables:
            temp
                   Size:       []
                   Dimensions: x,y,time
                   Datatype:   int16
    
    /grid2/
        Attributes:
                   description = 'This is another group attribute.'
        Dimensions:
                   x    = 360
                   y    = 180
                   time = 0     (UNLIMITED)
        Variables:
            temp
                   Size:       []
                   Dimensions: x,y,time
                   Datatype:   int16

ncdisp 显示文件中的所有组、维度和变量定义。无限维度用标签 UNLIMITED 标识。

peaks 变量中读取数据。

peaksData  = ncread('example.nc','peaks');

显示有关 peaksData 输出的信息。

whos peaksData
  Name            Size            Bytes  Class    Attributes

  peaksData      50x50             5000  int16  

读取与变量相关联的 description 属性。

peaksDesc  = ncreadatt('example.nc','peaks','description')
peaksDesc =

z = peaks(50);

创建变量数据的三维曲面图。用 description 属性的值作为图标题。

surf(double(peaksData))
title(peaksDesc);

读取与 /grid1/ 组相关联的 description 属性。将组名指定为 ncreadatt 函数的第二个输入。

g = ncreadatt('example.nc','/grid1/','description')
g =

This is a group attribute.

读取全局属性 creation_date。对于全局属性,将 ncreadatt 的第二个输入参量指定为 '/'

creation_date = ncreadatt('example.nc','/','creation_date')
creation_date =

29-Mar-2010

在 NetCDF 文件中查找所有无限维度

此示例说明如何使用高级函数在 NetCDF 文件中查找一个组的所有无限维度。

使用 ncinfo 函数获取示例文件 example.nc/grid2/ 组的相关信息。

ginfo = ncinfo('example.nc','/grid2/')
ginfo = 

      Filename: '\\matlabroot\toolbox\matlab\demos\example.nc'
          Name: 'grid2'
    Dimensions: [1x3 struct]
     Variables: [1x1 struct]
    Attributes: [1x1 struct]
        Groups: []
        Format: 'netcdf4'

ncinfo 返回一个包含组信息的结构体数组。

获取表示该组的无限维度的布尔值的向量。

unlimDims = [ginfo.Dimensions.Unlimited]
unlimDims =

     0     0     1

unlimDims 向量显示无限维度。

disp(ginfo.Dimensions(unlimDims))
         Name: 'time'
       Length: 0
    Unlimited: 1

使用低级函数读取 NetCDF 文件

此示例显示如何使用 netcdf 命名空间中的 MATLAB 低级函数获取有关 netCDF 文件中的维度、变量和属性的信息。要有效使用这些函数,应该熟悉 netCDF C 接口。

打开 NetCDF 文件

使用 netcdf.open 函数,以只读访问权限打开示例 netCDF 文件 example.nc

ncid = netcdf.open("example.nc","NC_NOWRITE");

netcdf.open 返回文件标识符。

获取有关 netCDF 文件的信息

使用 netcdf.inq 函数获取有关文件内容的信息。此函数对应于 netCDF 库 C API 中的 nc_inq 函数。

[ndims,nvars,natts,unlimdimID] = netcdf.inq(ncid)
ndims = 3
nvars = 3
natts = 1
unlimdimID = -1

netcdf.inq 返回文件中维度、变量和全局属性的数量,并返回文件中无限维度的标识符。无限维度可以增长。

使用 netcdf.inqAttName 函数获取文件中全局属性的名称。此函数对应于 netCDF 库 C API 中的 nc_inq_attname 函数。要获取属性的名称,必须指定该属性所关联变量的 ID 和属性编号。要访问与特定变量不相关联的全局属性,请使用常量 "NC_GLOBAL" 作为变量 ID。

global_att_name = netcdf.inqAttName(ncid,...
    netcdf.getConstant("NC_GLOBAL"),0)
global_att_name = 
'creation_date'

使用 netcdf.inqAtt 函数获取有关属性的数据类型和长度的信息。此函数对应于 netCDF 库 C API 中的 nc_inq_att 函数。再次使用 netcdf.getConstant("NC_GLOBAL") 指定变量 ID。

[xtype,attlen] = netcdf.inqAtt(ncid,...
    netcdf.getConstant("NC_GLOBAL"),global_att_name)
xtype = 2
attlen = 11

使用 netcdf.getAtt 函数获取属性值。

global_att_value = netcdf.getAtt(ncid,...
    netcdf.getConstant("NC_GLOBAL"),global_att_name)
global_att_value = 
'29-Mar-2010'

使用 netcdf.inqDim 函数获取文件中第一个维度的相关信息。此函数对应于 netCDF 库 C API 中的 nc_inq_dim 函数。netcdf.inqDim 的第二个输入是维度 ID,它是一个标识维度的从 0 开始的索引。第一个维度的索引值为 0

[dimname,dimlen] = netcdf.inqDim(ncid,0)
dimname = 
'x'
dimlen = 50

netcdf.inqDim 返回维度的名称和长度。

使用 netcdf.inqVar 函数获取文件中第一个变量的相关信息。此函数对应于 netCDF 库 C API 中的 nc_inq_var 函数。netcdf.inqVar 的第二个输入是变量 ID,它是一个标识变量的从 0 开始的索引。第一个变量的索引值为 0

[varname,vartype,dimids,natts] = netcdf.inqVar(ncid,0)
varname = 
'avagadros_number'
vartype = 6
dimids =

     []
natts = 1

netcdf.inqVar 返回名称、数据类型、维度 ID 以及与变量相关联的属性的数量。vartype 中返回的数据类型信息是 netCDF 数据类型常量的数值,例如,NC_INTNC_BYTE。有关这些常量的信息,请参阅 netCDF 文档。

读取 NetCDF 文件中的数据

使用 netcdf.getVar 函数读取示例文件中与变量 avagadros_number 相关联的数据。netcdf.getVar 的第二个输入是变量 ID,它是一个标识变量的从 0 开始的索引。avagadros_number 变量的索引值为 0

A_number = netcdf.getVar(ncid,0)
A_number = 6.0221e+23

查看 A_number 的数据类型。

whos A_number
  Name          Size            Bytes  Class     Attributes

  A_number      1x1                 8  double              

netcdf 命名空间中的函数自动选择与 NetCDF 数据类型最匹配的 MATLAB 类,但您也可以使用 netcdf.getVar 的可选参量指定返回数据的类。

读取与 avagadros_number 相关联的数据,并以 single 类返回数据。

A_number = netcdf.getVar(ncid,0,"single")
A_number = single
    6.0221e+23
whos A_number
  Name          Size            Bytes  Class     Attributes

  A_number      1x1                 4  single              

关闭 NetCDF 文件

关闭 netCDF 文件 example.nc

netcdf.close(ncid)

以交互方式读取 NetCDF 文件中的数据

此示例说明如何使用导入数据任务来浏览 netCDF 文件的结构,从文件中导入数据,然后分析和可视化数据。

下载数据集

美国国家海洋和大气管理局物理科学实验室 (NOAA PSL) 托管由美国国家冰雪数据中心 (NSIDC) 编制的北半球积雪数据的插值数据集。将此数据集下载到您的当前文件夹。

filename = "snowcover.mon.mean.nc";
url = "https://downloads.psl.noaa.gov/Datasets/snowcover/snowcover.mon.mean.nc";
fullLocalPath = websave(filename,url);

浏览和导入数据

通过选择实时编辑器选项卡上的任务 > 导入数据,在实时编辑器中打开导入数据任务。在文件字段中输入 netCDF 数据集的文件名 snowcover.mon.mean.nc。使用任务浏览数据结构,包括变量及其属性:

  • 全局属性给出文件中包含的数据的一般含义,包括引用。

  • 该数据集包含三个维度:两个空间维度(latlon)与一个时间维度 (time)。

  • lat 变量的大小为 90,具有一个名为 units 的属性,其属性值为 'degrees_north'。此变量表示测量点在赤道以北的纬度,以度为单位。

  • lon 变量的大小为 360,具有一个名为 units 的属性,其属性值为 'degrees_east'。此变量表示测量点在本初子午线以东的经度,以度为单位。

  • time 变量的大小为 297,具有一个无限维度和一个名为 units 的属性,其属性值为 'hours since 1800-01-01 00:00:0.0'。此变量表示进行测量的时间。

  • snowcover 变量的大小为 360×90×297,第三个维度为无限维度,具有一个名为 units 的属性(其属性值为 '%')和一个名为 long_name 的属性(其属性值为 'Monthly Means Snowcover Extent')。snowcover 变量是 latlontime 这三个变量的联合。它表示北半球特定月份特定点的月平均积雪量,以积雪覆盖地面的百分比来衡量。

latlontimesnowcover 变量中选择并导入数据。

Import Data Live Editor task with the snowcover.mon.mean.nc file imported, showing all variables selected for import

要查看此任务生成的代码,请点击任务参数区域底部的显示代码展开任务显示。

% Create a structure to store imported netCDF data
snowcover_mon_mean = struct();

filename = "snowcover.mon.mean.nc";
snowcover_mon_mean.Variables(1).Name = "lat";
snowcover_mon_mean.Variables(2).Name = "lon";
snowcover_mon_mean.Variables(3).Name = "time";
snowcover_mon_mean.Variables(4).Name = "snowcover";

snowcover_mon_mean.Variables(1).Value = ncread(filename, "/lat");

snowcover_mon_mean.Variables(2).Value = ncread(filename, "/lon");

snowcover_mon_mean.Variables(3).Value = ncread(filename, "/time");

snowcover_mon_mean.Variables(4).Value = ncread(filename, "/snowcover");

clear filename

组织和准备数据

为数据集中的每个变量创建局部变量。

lats = snowcover_mon_mean.Variables(1).Value;
lons = snowcover_mon_mean.Variables(2).Value;
times = snowcover_mon_mean.Variables(3).Value;
snows = snowcover_mon_mean.Variables(4).Value;

创建 latslons 的显示版本,为绘制数据做准备。选择适合在每个轴上显示十个标签的显示比例。

numLabels = 10;

latDisps = strings(length(lats),1);
latsLabelInterval = length(lats)/numLabels;
latLabelInds = latsLabelInterval:latsLabelInterval:length(lats);
latDisps(latLabelInds) = lats(latLabelInds);

lonDisps = strings(length(lons),1);
lonsLabelInterval = length(lons)/numLabels;
lonLabelInds = lonsLabelInterval:lonsLabelInterval:length(lons);
lonDisps(lonLabelInds) = lons(lonLabelInds);

time 变量的 units 属性表示 time 是从 1800 年开始以小时为单位测量的。此外,snowcover 变量的 long_name 属性指示这些值是月均值。使用这些信息将 times 向量转换为对应的 datetime 值,并创建 times 的显示版本,该版本包含月份和年份,但不显示日期。

sampTimes = datetime("1800-01-01 00:00:00") + hours(times);
sampTimes.Format = "MMM-yyyy";
sampTimeDisps = string(sampTimes);

snows 的第一个维度表示纬度,第二个维度表示经度。要创建此数据的热图,第一个维度应对应于一列(经度),第二个维度应对应于一行(纬度)。置换 snows 的这两个维度。

snows = permute(snows,[2 1 3]);

对数据绘图

为第一个月的数据创建热图。

h = heatmap(lons,lats,snows(:,:,1));
h.XLabel = "Longitude (°E)";
h.YLabel = "Latitude (°N)";
h.XDisplayLabels = lonDisps;
h.YDisplayLabels = latDisps;
h.Colormap = winter;
h.GridVisible = "off";

通过遍历所有可用时间的数据为热图添加动画效果。

for i = 1:numel(sampTimeDisps)
    h.ColorData = snows(:,:,i);
    h.Title = "Percent Snow Cover vs. Location (" + sampTimeDisps(i) + ")";
    pause(0.1)
end

Figure contains an object of type heatmap. The chart of type heatmap has title Percent Snow Cover vs. Location (Sep-1995).

找到积雪量最大的时间

计算并绘制总积雪量与时间的函数关系图。

cumSnowsbyTime = squeeze(sum(snows,[1 2])) / (length(lats)*length(lons));

plot(sampTimes,cumSnowsbyTime)
xlabel("Date")
ylabel("Total Snow Cover (%)")
title("Total Snow Cover vs. Date")

Figure contains an axes object. The axes object with title Total Snow Cover vs. Date, xlabel Date, ylabel Total Snow Cover (%) contains an object of type line.

找出并绘制积雪量最大的时间。

[maxSnowsbyTime,maxSnowsbyTimeInd] = max(cumSnowsbyTime);

h = heatmap(lons,lats,snows(:,:,maxSnowsbyTimeInd));
h.XLabel = "Longitude (°E)";
h.YLabel = "Latitude (°N)";
h.Title = "Percent Snow Cover vs. Location (" + sampTimeDisps(maxSnowsbyTimeInd) + ")";
h.XDisplayLabels = lonDisps;
h.YDisplayLabels = latDisps;
h.Colormap = winter;
h.GridVisible = "off";

Figure contains an object of type heatmap. The chart of type heatmap has title Percent Snow Cover vs. Location (Feb-1978).

积雪量最大的月份是 1978 年 2 月。

找到积雪量最大的位置

计算并绘制平均积雪量与位置的函数关系图。

cumSnowsbyLoc = sum(snows,3) / length(times);

h = heatmap(lons,lats,cumSnowsbyLoc);
h.XLabel = "Longitude (°E)";
h.YLabel = "Latitude (°N)";
h.Title = "Average Percent Snow Cover vs. Location";
h.XDisplayLabels = lonDisps;
h.YDisplayLabels = latDisps;
h.Colormap = winter;
h.GridVisible = "off";

Figure contains an object of type heatmap. The chart of type heatmap has title Average Percent Snow Cover vs. Location.

找到并绘制积雪量最大的位置。

maxSnowsbyLocVal = max(cumSnowsbyLoc,[],"all");
maxSnowsbyLoc = maxSnowsbyLocVal*(cumSnowsbyLoc == maxSnowsbyLocVal);

h = heatmap(lons,lats,maxSnowsbyLoc);
h.XLabel = "Longitude (°E)";
h.YLabel = "Latitude (°N)";
h.Title = "Locations of Maximum Snow Cover";
h.XDisplayLabels = lonDisps;
h.YDisplayLabels = latDisps;
h.Colormap = winter;
h.GridVisible = "off";

Figure contains an object of type heatmap. The chart of type heatmap has title Locations of Maximum Snow Cover.

积雪量最大的地方包括格陵兰岛的大部分、斯瓦尔巴特群岛和弗朗茨约瑟夫地的部分地区。

感谢

NH Ease-Grid 积雪数据由美国科罗拉多州博尔德市的 NOAA PSL 在其网站 https://psl.noaa.gov 上提供。

另请参阅

函数

实时编辑器任务

相关主题

外部网站