创建 NetCDF 文件

您将使用加勒比海的海洋生态单位 (EMU) 要素类在 ArcGIS Pro 中使用 Python 创建 NetCDF 文件。 首先,您将通过工程包设置一个新工程。 然后,您将启动一个新的 Python Notebooks。 接下来,您将使用 EMU 模式创建一个空的 NetCDF 文件。 最后,您要将 EMU 值加载到 NetCDF 文件中。 输出的 EMU NetCDF 文件将具有所需的格式,以便加载并可视化为 ArcGIS Pro 中的体素图层。

设置新工程

您将使用工程包启动一个新的 ArcGIS Pro 工程。 工程包中包含国家/地区和一个 EMU 数据示例。 首先,您将使用 ArcGIS Notebooks 处理此 EMU 数据。

  1. 下载工程包并双击以将其在 ArcGIS Pro 中打开。 如果出现提示,请登录 ArcGIS 帐户。
    注:

    如果您没有 ArcGIS Pro 的访问权限或者 ArcGIS 组织帐户,请参阅软件访问权限选项

    工程包含 Caribbean Ecological Marine Units 局部场景和 EMU_Caribbean_Sea 3D 点要素类。

    EMU 工程包

    注:

    您可以打开 World Ocean Base 图层和WorldElevation3D/TopoBathy3D 图层(并关闭 Countries 图层)以获得更好的地理参考。 地图上的数据越少,其绘制速度就越快。

  2. 在功能区上,单击插入选项卡,然后选择新建笔记本

    “新建笔记本”按钮

    新的笔记本将添加到工程。 可以在目录窗格中编辑 Notebooks 详细信息。

  3. 目录窗格中,展开 Notebooks 文件夹。
  4. 右键单击 New Notebook.ipynb 并选择重命名

    重命名选项

  5. 输入 Create EMU NetCDF file.ipynb 然后按 Enter 键。

    一个包含局部场景和空白 Python 笔记本的 ArcGIS Pro 新工程已经准备就绪。

创建一个空的 NetCDF 文件

首先,您将为加勒比海中的 EMU 创建 NetCDF 文件。 NetCDF 文件将在纬度、经度和深度格网中构建。 该文件还将包括全局属性、维度和变量。 这些是在 3D 模式下绘制(纬度、经度和深度)和显示相关变量(温度、盐度和氧气)所需的基本属性。

多维数据是跨空间和时间、深度或高度收集的。

  1. 在笔记本的空单元格中,输入以下命令以加载所需的 Python 模块:
    import os
    import arcpy
    import netCDF4
    import numpy as np
    import datetime as dt

    这些模块是包含脚本中所使用函数的库。 例如,arcpy 模块包含 ArcGIS 地理处理、数据管理和映射函数。 我们可以通过 netCDF4 模块读写 NetCDF 文件。

  2. Notebooks 功能区上,单击运行

    “运行”按钮

    第一个单元格运行后,大括号将显示数字 1。 新单元格随即添加到第一个单元格下方。

    注:

    通过单击插入选项卡并选择在下方插入单元格,您可以从笔记本功能区添加新单元格。

  3. 在新单元格中,粘贴与输出 NetCDF 文件和规则 3D 格网相关的以下命令,然后单击运行
    # Output file
    output_nc = "EMU_Caribbean_Voxel.nc"
    
    # Grid
    lowerleft_x = -88.625
    lowerleft_y = 8.375
    cellsize = 0.25
    
    # Number of cells
    no_rows = 58
    no_cols = 117
    no_depths = 101
    
    # Values
    lat_vals = np.arange(lowerleft_y, lowerleft_y + cellsize*no_rows, cellsize)
    lon_vals = np.arange(lowerleft_x, lowerleft_x + cellsize*no_cols, cellsize)
    z_vals = np.arange(0, -505, -5)
    
    # Print vectors
    print('Latitude')
    print(lat_vals)
    print('Longitude')
    print(lon_vals)
    print('Depth')
    print(z_vals)

    每个变量定义都通过相关注释 (#) 进行分隔。 Output_nc 指定输出 NetCDF 文件的名称。 Lowerleft_xlowerleft_y 指定 NetCDF 文件的坐标。 像元大小代表 1/4 度的分辨率。 No_rows 指定与纬度相关的行数;在本例中,0.25 像元大小的 58 行表示纬度为 14.5 度。 No_cols 指定与经度相关的列数;在本例中,0.25 像元大小的 117 行表示经度为 29.25 度。 这表示输出的宽度(经度)将略大于其长度(纬度)的两倍。 No_depths 指定将包含在 NetCDF 文件中的深度值的数量。 这在 3D 模式下表示我们的水体的列空间。 在下一个变量定义()中,您可以指定如何将这些变量一起使用,以生成间距固定的水平格网和间距不固定的垂直(深度)格网。

    latitudelongitudedepth 矢量将显示在屏幕上。

    运行代码块后的输出

    接下来,您将使用 netCDF4 Python 模块的数据集函数创建空白的 NetCDF 文件。 您还将提供全局属性以将文档添加至文件。

  4. 在空白单元格中,粘贴以下代码,然后单击运行
    # Create File
    nc_file = netCDF4.Dataset(output_nc, 'w', format="NETCDF4", set_auto_mask=False)
    
    # Global Attributes
    nc_file.title = 'Ecological Marine Units'
    nc_file.summary = 'Ecological Marine Units (EMUs) for the Caribbean Sea.'
    nc_file.keywords = 'Global, EMU, USGS, NOAA, Esri, 3D, Ocean, Marine, Ecology'
    nc_file.license = ('This work is licensed under a Creative Commons Attribution 4.0 '
                       'International License.')
    nc_file.references = ('Please see references Cited in this publication: ' 
                        'http://www.aag.org/galleries/default-file/AAG_Marine_Ecosyst_bklt72.pdf')
    nc_file.source = 'Esri, USGS,  NatureServe, GEO, NOAA, NASA, NIWA'
    nc_file.Conventions = 'CF-1.6'
    nc_file.institution = 'Esri'
    nc_file.history = ('{0} Creation of EMU Caribbean '
                       'netcdf file.').format(dt.datetime.now().strftime("%Y-%m-%d"))

    注:

    为 NetCDF 文件添加文档非常重要,这样,其他人就可以更好地理解文件。 您可以遵循气候和预测 (CF) 元数据公约中关于标准属性和变量名称的指导。

  5. 在新单元格中,粘贴以下代码以创建经度纬度深度维度。
    # Create Dimensions
    lat_dim = nc_file.createDimension('latitude', no_rows)
    lon_dim = nc_file.createDimension('longitude', no_cols)
    top_dim = nc_file.createDimension('depth', no_depths)

    接下来,您将添加用于对变量进行制图和格网化的代码:crslatitudelongitudedepth,然后将 lat_valslon_valsz_vals 矢量加载到其对应的变量(换言之,lat_varlon_vardepth_var)中。

  6. 在同一单元格的末尾,添加以下代码并单击运行
    # Create the map and grid variables
    crs_var = nc_file.createVariable('crs', 'l', (), fill_value=-9999, zlib=True)
    crs_var.standard_name = 'crs'
    crs_var.grid_mapping_name = 'latitude_longitude'
    crs_var.crs_wkt = arcpy.SpatialReference(4326).exportToString()
    
    lat_var = nc_file.createVariable('latitude', 'f4', ('latitude'), fill_value=-9999)
    lat_var.units = 'degrees_north'
    lat_var.standard_name = 'latitude'
    lat_var.axis = 'Y'
    
    lon_var = nc_file.createVariable('longitude', 'f4', ('longitude'), fill_value=-9999)
    lon_var.units = 'degrees_east'
    lon_var.standard_name = 'longitude'
    lon_var.axis = 'X'
    
    depth_var = nc_file.createVariable('depth', 'l', ('depth'), fill_value=-9999)
    depth_var.short_name = 'depth'
    depth_var.standard_name = 'depth'
    depth_var.positive = 'up'
    depth_var.units = 'meters'
    depth_var.axis = 'Z'
    
    # Load data
    lat_var[:] = lat_vals
    lon_var[:] = lon_vals
    depth_var[:] = z_vals

    crs 变量没有任何维度或变量;它提供了制图空间参考信息。

    用于创建输出文件并加载数据的代码块

  7. 在新单元格中,为 EMU 数据粘贴三个变量:海水温度盐度溶氧量cluster37,然后单击运行
    # Create EMU Variables
    temp_var = nc_file.createVariable('temp', 'f4',
                                      ('depth', 'latitude', 'longitude'), fill_value=-9999)
    temp_var.short_name = 'temp'
    temp_var.standard_name = 'sea_water_temperature'
    temp_var.units = 'degree_Celsius'
    temp_var.grid_mapping = 'crs'
    
    sali_var = nc_file.createVariable('salinity', 'f4',
                                      ('depth', 'latitude', 'longitude'), fill_value=-9999)
    sali_var.short_name = 'salinity'
    sali_var.long_name = 'sea_water_salinity'
    sali_var.units = ''
    sali_var.grid_mapping = 'crs'
    
    dissO2_var = nc_file.createVariable('dissO2', 'f4',
                                      ('depth', 'latitude', 'longitude'), fill_value=-9999)
    dissO2_var.short_name = 'dissO2'
    dissO2_var.long_name = 'mole_concentration_of_dissolved_molecular_oxygen_in_sea_water'
    dissO2_var.units = 'microliters/liter'
    dissO2_var.grid_mapping = 'crs'
    
    cluster37_var = nc_file.createVariable('cluster37', 'l',
                                           ('depth', 'latitude', 'longitude'), fill_value=-9999)
    cluster37_var.short_name = 'cluster37'
    cluster37_var.long_name = 'cluster37_id'
    cluster37_var.units = ''
    cluster37_var.grid_mapping = 'crs'

    海水温度、盐度和溶氧量是描绘海洋及其环境条件的关键变量。 聚类变量保存 EMU 数据集中格网像元的分类。 请注意,前三个变量的数据类型为浮点型(即“f4”)而 cluster37 变量的数据类型为整型(即“l”)。

    注:

    在本教程中,使用了深度为 500 米的一部分加勒比海数据。 访问 ArcGIS Living Atlas of the World 中的 Ecological Marine Units (EMU) Web 应用程序以了解有关 EMU 数据集的详细信息。 整个 EMU 数据集包含比本练习中列出的三个变量更多的变量。 您可以从 ArcGIS Online 下载完整的 EMU NetCDF 文件

将数据加载到 NetCDF 文件

接下来,您将把 EMU 点要素类的值加载到 NetCDF 文件中。

  1. 内容窗格中,右键单击 EMU_Caribbean_Sea 要素类,然后选择属性表

    “属性表”选项

    属性表随即出现。

    每个 3D 点(坐标 XYZ)的 tempsalinitydissO2Cluster37 字段包含将加载到 NetCDF 文件变量的信息。

    海洋生态单位属性

  2. 关闭属性表。
  3. 在笔记本末尾的新单元格中,将 EMU_Caribbean_Sea 要素类分配到 fc 变量中。 创建包含 fc 变量以及 tempsalinitydissO2Cluster37Shape@ 字段的搜索游标。 现在不要运行单元格。
    # Load EMU data
    fc = os.path.abspath(r'.\EMU.gdb\EMU_Caribbean_Sea')
    cursor = arcpy.da.SearchCursor(fc, ['temp', 'salinity', 'dissO2', 'Cluster37', 'Shape@'])
  4. 内容窗格中,双击 EMU_Caribbean_Sea 图层。 在图层属性窗口中,单击选项卡。

    “源”选项卡

  5. 数据库行复制源路径并将其粘贴到笔记本中作为 fc 路径变量。 确保在末尾包含文件名 EMU_Caribbean_Sea

    完整的 fc 路径变量

  6. 在同一单元格中,使用 for 循环迭代游标中的。 获取 EMU 变量值,用 -9999 替换值,获取 3D 点的数组索引,并将变量值存储在 NetCDF 数组中。
    
    # For each record in the table
    for row in cursor:
        # Get values
        temp, salinity, dissO2, cluster37 = row[:4]
        coords = row[4].getPart()
        # Replace null values with -9999
        temp = float(temp) if temp else -9999
        salinity = float(salinity) if salinity else -9999
        dissO2 = float(dissO2) if dissO2 else -9999
        cluster37 = float(cluster37) if cluster37 else -9999
        # Get indices in array of current 3D point
        idx = (np.abs(lon_vals - coords.X)).argmin()
        idy = (np.abs(lat_vals - coords.Y)).argmin()
        idz = np.where(z_vals==int(coords.Z))[0]
        # Store variables values
        if idz.size > 0:
            temp_var[idz, idy, idx] = temp
            sali_var[idz, idy, idx] = salinity
            dissO2_var[idz, idy, idx] = dissO2
            cluster37_var[idz, idy, idx] = cluster37
    del(cursor)

    将迭代游标中的行的 for 循环

  7. 运行单元格。

    单元格可能需要运行一段时间。 在运行单元格时,单元格旁会显示一个星号 (*)。 该星号会在完成后变为数字。

    单元格旁的型号表示该单元格正在运行

  8. 在新单元格中,复制粘贴以下代码关闭 NetCDF 文件,然后单击运行
    # Close NetCDF file
    nc_file.close()

    提示:

    您可以从 ArcGIS Online 下载最终的 Python 笔记本。

  9. 在功能区的笔记本选项卡上,单击保存

    Notebook 选项卡中的“在 Notebook 中保存”组

您已创建一个空的 NetCDF 文件。 您还在 ArcGIS Pro 中使用 Python Notebooks 将值从点要素类加载到了 NetCDF 文件。 接下来,您将在本地场景中将此 NetCDF 文件加载为多维体素图层。


将 NetCDF 文件添加为体素图层

之前,您在 ArcGIS Pro 中使用 Python 笔记本和 EMU 点要素类创建了一个 NetCDF 文件。 接下来,您需要在局部场景中将 EMU NetCDF 文件加载为多维体素图层。 体素图层可用于以 3D 形式可视化 EMU 变量,例如海水温度、盐度或溶氧量。

添加多维体素图层

首先,您要将 EMU NetCDF 文件添加为体素图层。

  1. 单击 Caribbean Ecological Marine Units 选项卡以打开该局部场景。
  2. 在功能区上的地图选项卡中,单击添加数据下拉箭头,然后选择多维体素图层

    多维体素图层选项

    添加体素图层窗口随即显示。

  3. 添加体素图层窗口中,对于输入源数据,单击浏览,然后选择 EMU_Caribbean_Voxel.nc 文件。

    选择该文件后,可用属性字段将填充选择变量部分。

    在 NetCDF 文件中定义的每个变量都将在添加体素图层窗口中列出。 通过打开或关闭变量,可以确定要包含在体素图层中的变量。 可以选择要设置为默认变量的变量。 将体素图层添加至场景后,这将是显示的变量。

    变量具有的已定义数据类型用于确定符号化变量的方式。 例如,连续数据类型可以为数值,例如海水温度盐度溶氧量。 可以使用拉伸值来可视化连续变量。 如果数据类型为离散型,例如 cluster37,则可以使用唯一值对变量进行符号化。

  4. 对于选择变量,在默认变量列中,将 dissO2 设置为默认值。

    “添加体素图层”窗口

  5. 单击确定

    ArcGIS Pro 中,EMU NetCDF 文件将显示为体素图层

    体素已添加至工程

    目前,将使用默认颜色和高程值对其进行绘制。 要更加精确地可视化此数据,您需要更改高程和样式。

    该图层目前正在海洋顶部绘制。 要正确地将其放置在某深度处,您需要设置垂直夸大。

  6. 内容窗格中,单击 EMU_Caribbean_Voxel 图层以将其选中。
  7. 在功能区上,单击体素图层选项卡。
  8. 高程组中,对于垂直夸大,删除负号,以将其设置为 3223.86

    “高程”参数

    场景中随即更新体素图层。

    体素已放置在实际深度

    接下来,出于可视化目的,您将应用专为显示海洋数据而开发的样式。 海洋样式包含多种配色方案,用于可视化海洋中的特征,例如氧含量。 颜色范围和标注需要相匹配,以便于受众解释体素图层中的值。

  9. 下载 cmocean.stylx 样式包。
  10. 单击功能区上的插入选项卡。 在样式组中,单击添加并选择添加样式

    “添加样式”选项

  11. 添加样式文件窗口中,选择 cmocean.stylx 文件并单击确定
    注:

    如果显示升级样式窗口,单击继续操作。

    现在,即可将样式应用于该图层。

  12. 在功能区上,单击体素图层选项卡。 在绘制组中,单击符号系统

    随即显示符号系统窗格。

  13. 符号系统窗格中,对于配色方案,展开菜单并选中显示名称显示所有

    配色方案菜单

    已下载的海洋样式将显示在列表顶部。

  14. 查找并选择 oxy 配色方案。

    Oxy 配色方案

    地图将重新绘制以显示新的配色方案。 低溶氧浓度将显示为红色和栗色,而高溶氧浓度将显示为黄色。

    Dissolved O2 体素图层

    中间值将显示为灰色。 要强调高值和低值,您需要使用透明度来隐藏这些中间值。

  15. 符号系统窗格中,对于标签颜色范围,将最小值设置为 3.00,将最大值设置为 4.00

    设置标注和颜色范围值。

  16. 选中透明度功能复选框。

    通过添加控制点来定义透明度范围。

  17. 单击两次添加控制点按钮。

    “添加控制点”按钮

    随即将另外两个点添加至符号范围。

  18. 单击第一个控制点,然后将设置为 100%,并将位置设置为 3%。

    第一个控制点

  19. 对于第二个控制点,将设置为 100%,并将位置设置为 80%。

    体素图层显示了加勒比海中高(黄色)和低(红色)溶氧量的区域。

    完成的符号系统

  20. 快速访问工具栏上,单击保存以保存工程。

    快速访问工具栏上的“保存”按钮

您已将 EMU NetCDF 文件添加为 ArcGIS Pro 中局部场景中的多维体素图层。 接下来,您将通过定义表面并对体素图层外观进行基本更改(例如选择变量并更改拉伸参数)来直观地分析体素图层。


在 3D 模式下直观分析 EMU

之前,您在 ArcGIS Pro 中将 EMU NetCDF 文件加载为体素图层。 接下来,您将创建面(例如等值面和截面),以直观分析变量。

创建等值面

首先,您将以特定值定义一个等值面,以直观地分析溶氧的分布情况。 等值面描述了体素图层中沿指定值的表面。 例如,以 2.85 微升/升表示的溶氧等值面显示了加勒比海中具有该值的所有位置,这些位置可能位于不同深度。

  1. 内容窗格中的 EMU_Caribbean_Voxel 下,单击 mole_concentration_of_dissolved_molecular_oxygen_in_sea_water 两次。

    字段变为可编辑状态。

  2. 将变量命名为 Concentration of Dissolved Oxygen

    重命名溶氧表面变量。

  3. 展开并选择表面

    已在“内容”窗格中选择并展开“表面”

    由于尚未创建表面,因此将从地图上移除体素。

  4. 表面下,右键单击等值面,然后选择创建等值面

    创建一个等值面。

    随即将在体素图层内创建一个新等值面,并显示体素探索窗格。

  5. 体素探索窗格中,对于名称,输入 Concentration of Dissolved Oxygen 2.85。 对于,输入 2.85

    “体素探索”窗格

    在地图上绘制了溶氧为 2.85 微升/升的等值面。

    体素仅显示 2.85 微升/升的溶氧量。

    接下来,您将更新体素的垂直夸大地面高程表面

    注:

    有关将体素数据配置为相对于海洋测深正确定位,请参阅更改体素图层的外观

  6. 内容窗格中,打开 World Ocean BaseWorldElevation3D/TopoBathy3D 图层。
  7. 内容窗格中,单击地面

    “内容”窗格中的“地面”

  8. 在功能区高程表面图层选项卡的绘制组中,对于垂直夸大,键入 40,然后按 Enter 键。
  9. 内容窗格中,单击 EMU_Caribbean_Voxel 图层。 在功能区体素图层选项卡的高程组中,将垂直夸大设置为 40
  10. 右键单击 EMU_Carribbean_Voxel 图层,然后单击属性
  11. 图层属性窗口中,单击高程选项卡,对于夸大模式,选择 Z 坐标,然后单击确定

    值为 5 微升/升的溶氧浓度

创建截面

接下来,您将通过定义跨越体素图层的截面来直观地探索变量。 您将定义一个截面,然后动态更改其位置、倾斜度和方向。 新截面将被锁定为与其他变量一起显示。

  1. 在功能区体素图层选项卡的变量组中,选择 sea_water_temperature

    海水温度变量。

  2. 绘制组中,单击符号系统。 在符号系统窗格中,对于配色方案,选中显示名称并选择热波段

    选择热波段符号系统

  3. 内容窗格中,取消选中 Countries 图层。
  4. 单击功能区上的数据选项卡。 在浏览组中,选择剖切片和截面

    剖切片和截面工具栏随即显示在场景底部。

  5. 剖切片和截面工具栏中,选择垂直截面

    “剖切片和截面”工具栏中的“垂直剖切片”工具

  6. 在地图中,在尼加拉瓜西北海岸上单击一个点,作为剖切片起点,然后在尤卡坦半岛沿海单击第二个点。

    已在尼加拉瓜和尤卡坦半岛之间创建垂直剖切片

    新的垂直截面已添加至场景。

    侧面倾斜剖面图

  7. 内容窗格中,右键单击截面 1,然后选择锁定截面

    锁定截面以供以后进行可视化。

    锁定截面移动到体素图层的锁定截面组中。 现在,截面为定义位置的快照,即使选择其他变量,仍可以查看此截面。 这允许您同时浏览多个变量。

  8. 在功能区体素图层选项卡的变量组中,选择 mole_concentration_of_dissolved_molecular_oxygen_in_sea_water 变量。

    2.85 溶氧浓度等值面和海水温度截面随即在场景中显示。

    截面和等值面的视觉效果

    示例图像显示了从尼加拉瓜到尤卡坦半岛的海水温度横截面。 它还显示了值为 2.85 微升/升的溶氧等值面。

在本课程中,您使用 ArcGIS Pro 中的 Python 笔记本创建了 NetCDF 文件。 您下载了 EMU 点要素类,并将其值加载到新的 EMU NetCDF 文件中。 您将 NetCDF 文件作为局部场景中的多维体素图层进行了加载并在 3D 模式下对其进行了直观分析。

您可以在教程库中找到更多教程。