ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ArcGIS模型构建器:批量将NetCDF逐波段导出为TIFF

ArcGIS模型构建器:批量将NetCDF逐波段导出为TIFF 这些年和气象、海洋、遥感数据打交道最头疼的就是拿到一堆几百兆甚至几个G的.nc文件。上周我一个做气候分析的朋友来找我说手上有几十个CMIP6模式的日平均气温数据每个.nc文件里存了365天的逐日序列他想把每一天单独导成一个tif回头再去做站点对比和空间统计。如果开ArcMap手动操作打开NetCDF栅格图层之后右键导出数据一次只能选一个波段一个文件就要点365次几十个文件下来手都要废掉。我的建议很直接用模型构建器把“读取NetCDF”和“按波段拆分”两个工具串起来一次性把nc文件里的所有波段自动导出成独立栅格。这个过程不写一行Python代码全程图形化操作逻辑清晰跑起来也很快。我这边实测一个几百MB、含365个波段的nc文件从读入到全部导出成tif大概两分钟左右搞定。这篇文章把这套思路和具体步骤完整写出来适合正在被nc文件逐波段导出折磨的GISer、气象水文专业的学生和科研助理也适合想入门模型构建器批处理的朋友。1. 先搞清楚nc文件、变量与波段的关系1.1 一个nc文件里到底装了什么NetCDF全称Network Common Data Form是一种面向科学数据存储的自描述格式气象、海洋、环境领域几乎天天都在用。理解它最直观的方式就是把它想象成一个“多层抽屉柜”整个文件是一个柜子柜子里有若干个大抽屉每个抽屉是一个变量Variable比如温度、降水、风速每个抽屉内部又分了很多小格子每个小格子对应一个时间点或一层高度比如某年某月某日的温度值。这些“小格子”在ArcGIS里加载出来就变成了一个个波段Band。也就是说一个含有365天序列的温度nc文件本质上就是一个具有365个波段的栅格数据。每个波段里的像元值就是那一天对应位置上的温度数值。这里有个容易混淆的点nc文件里的变量和栅格的波段并不是一一对应的。一个变量如果带有时间维度加载后就会展开成多个波段如果变量还带有高度层维度情况会更复杂可能还需要先锁定某个高度层这部分我在后面第5章会专门说。在ArcGIS里想直接看nc文件内部有哪些变量和维度最快的办法是在ArcCatalog或ArcMap的目录面板里选中.nc文件后在“预览”选项卡里切换一下或者直接用文本方式打开nc文件头部不过二进制文件直接看不方便。更稳妥的方法是装一个Panoply或者HDFView这类查看器几秒钟就能看清变量名、维度名、坐标范围和缺失值定义这个习惯建议养成。1.2 ArcGIS处理NetCDF的两个关键工具ArcToolbox里专门有一组NetCDF工具位置在“多维数据”工具集下面。平时最常用的有两个一个是“创建NetCDF栅格图层”一个是“NetCDF转为栅格”。“创建NetCDF栅格图层”负责把nc文件里的某个变量读取为一个临时栅格图层不写盘、不产生磁盘文件运行起来非常轻量。最关键的是它允许指定“波段维度”如果把时间维度设为波段维度那么生成的就是一个多波段栅格图层波段数就等于时间步数。这一步相当于把整个抽屉柜原封不动搬进ArcMap里但还只是一叠叠胶片叠放在一起。“NetCDF转为栅格”则是一次性从nc文件里抽出一个特定时间点或特定高度层的数据把它直接输出成磁盘上的独立栅格文件。它的缺点是每次只能导出一个切片如果要想导出365天就需要循环365次效率低且模型构建器里还不好做这种维度值遍历。所以我的思路很明确先用“创建NetCDF栅格图层”把整个变量读成一个多波段栅格这一步速度很快因为只是建立内存索引再用ArcGIS自带的“分割栅格”工具按照波段维度一次性拆分成多个单波段文件。这样既绕开了逐时间步循环的低效又能稳定生成规范命名的文件序列。2. 模型构建器整体思路先合成多波段再拆分成单波段2.1 为什么推荐模型构建器而不是Python脚本这个问题经常有人问既然ArcPy脚本能实现为什么还用模型构建器我的答案分两个层面。第一模型构建器足够直观。用鼠标把工具拖进画布连线、设参数、勾选中间数据整个处理流程像画流程图一样一眼就能看出谁是谁的上游谁是谁的下游。万一过两个月再打开模型或者交给同事维护看模型窗口比读几百行Python脚本要省力得多。第二模型构建器天然适合“半固定化”流程。nc文件批量处理这个场景变量名、维度名是相对固定的变化的只是文件路径。模型里只要把输入文件设为变量输出目录动态拼接以后每次处理新数据双击模型改一下路径就能跑不需要动逻辑。对不熟悉代码的科研人员来说这个门槛低太多了。当然如果你本身Python功底扎实ArcPy确实更灵活比如动态拼文件名、批量重命名、异常处理都更方便。但就“批量导出nc波段”这个需求而言模型构建器的代码量约等于零逻辑清晰已经足够。2.2 核心流程设计整套流程在模型窗口里其实只有三步输入nc文件 → “创建NetCDF栅格图层”生成临时多波段栅格 → “分割栅格”按波段拆分成多个单波段tif。第1步读入数据第2步拆分数据。没有多余的分支没有需要人工干预的地方设计上非常简洁。这里有一个关键设计点中间的“创建NetCDF栅格图层”输出一定不要保存成磁盘上的永久栅格。因为一个365波段的栅格存成栅格数据集少说也得占几百MB甚至几个G的磁盘空间而且生成后再删除也浪费时间。模型构建器里把这一步的输出勾选为“中间数据”软件跑完流程后会自动清理磁盘负担小很多。另外一个设计要点是输出文件的组织方式。单个nc文件拆分出来的文件默认命名会带上“文件名_波段号”这样的规律但多个nc文件拆出来的结果如果放在同一个目录极容易因为命名相似而互相覆盖。因此模型里我会再加一个“创建文件夹”工具用当前nc文件的文件名作为子文件夹名每个nc文件对应一个独立输出目录彻底避开覆盖问题。2.3 中间数据有什么用很多初学者一看到模型构建器里右键工具输出项有“中间数据”这个勾选项不明白它的意义。简单说勾选之后这个工具的输出不会作为最终成果保留运行完就被释放了。它在模型内部照样能被下一个工具拿来当输入只是不落盘或者说落盘了也会被自动清理。用在这个场景里“创建NetCDF栅格图层”输出的多波段栅格就是一个典型的中间数据。我们只是想借助它完成波段拆分拆分完了这叠胶片就没用了没必要留在磁盘上占空间。不勾选的话ArcGIS可能会在默认工作空间里生成一个临时栅格数据集数据量大时会拖慢整体运行、撑爆磁盘甚至导致后续工具报错“磁盘空间不足”。另外模型构建器里的环境变量也需要顺手设置一下尤其建议把“当前工作空间”和“暂存工作空间”指定到一个剩余空间充足的盘符下避免默认路径跑到C盘系统盘。这个设置双击模型窗口的空白处选择“属性 → 环境设置”就能改非常关键。3. 实操搭建单文件波段批量导出的完整步骤3.1 添加“创建NetCDF栅格图层”工具并设置参数打开ArcMap在ArcToolbox里找到“多维数据工具”把“创建NetCDF栅格图层”拖进模型构建器的画布。双击这个工具图标开始填参数。输入netCDF文件选择你要处理的.nc文件。变量下拉框里选择你要导出的变量比如气温变量名可能是tas、t2m、temp。不用纠结nc文件里有哪些变量下拉框里都能看到。X维度选择经度lon/longitude。Y维度选择纬度lat/latitude。输出栅格图层给这个临时图层起个名字比如“temp_lyr”管它是临时还是最终输出这里必须填。波段维度这里务必选择时间维度也就是time/std_time之类的字段。只有选了这个生成出来的才会是多波段栅格365个时间步就是365个波段。需要注意如果波段维度选“无”工具只会按第一个时间切片生成单波段栅格。这个参数是最容易踩坑的地方很多人导出来发现只有一个tif多半就是漏选了波段维度。模型参数确认无误后点确定。注意这个时候先不要把模型整体的输入参数提交运行我们先把第二个工具接进来。3.2 添加“分割栅格”工具实现按波段拆分“分割栅格”这个工具在ArcToolbox的“数据管理工具 → 栅格 → 栅格处理”下面英文叫Split Raster。把这个工具拖到模型窗口里放在“创建NetCDF栅格图层”的右侧。双击“分割栅格”工具设置参数输入栅格选择刚才“创建NetCDF栅格图层”输出的那个临时图层。输出文件夹选择一个空文件夹或者指定一个已经存在的目录。分割方式这里是最关键的选择必须选“SPLIT_BAND按波段分割”。另外两个选项SIZE_OF_TILE是按指定像元大小分块NUMBER_OF_TILES是按指定数量均分都不是我们要的。格式选TIFF。通用性好后续在其它软件里使用也方便。重采样方式默认最邻近即可我们这属于拆分波段不是重采样这个参数不会真正改变像元值。压缩类型如果数据量偏大可以选LZW压缩无损且能明显减小体积。点确定后用模型构建器的“连接工具”把“创建NetCDF栅格图层”的输出连到“分割栅格”的“输入栅格”参数上。如果工具在画布上已经自动识别到连接线会非常清楚。这里要特别提醒分割栅格的输出文件夹必须是真实存在且可写的目录。ArcGIS不像某些软件会自动创建目录目录不存在会直接报错。如果你在模型里拼了一个新目录路径务必要在流程里加“创建文件夹”工具或者提前手动建好。3.3 运行模型并检查输出文件全部连接好后把“创建NetCDF栅格图层”的输出右键设置为“中间数据”。然后点模型窗口工具栏上的“运行”按钮剩下的事情就交给ArcGIS。运行日志里会显示每一步的开始时间和结束时间。等进度条走完打开输出文件夹你会看到一整排tif文件命名规律通常类似“temp_1.tif、temp_2.tif、temp_3.tif……”数字与波段序号一一对应而波段序号又对应着nc文件时间维度的排列顺序。我建议不要急着直接跑大批量先拿一个波段数少的nc文件试运行验证一下输出的文件数量是否等于时间步数第1个tif的时间值是否对得上nc文件里的第一个时间点空间范围、栅格大小、投影是否正常。拿最后一个时间切片比如第365个波段和原nc文件在ArcMap里对比一下像元值如果完全一致说明整套流程的设置没有问题可以放心放量跑。4. 批量处理多个nc文件外层套一个文件迭代器4.1 添加文件迭代器并关联输入单个文件的模型跑顺后批量就非常简单了。难点在于让模型自动遍历一个文件夹下的所有.nc文件并且每次循环都把文件名正确传给下游工具。在模型构建器菜单栏上点击“插入 → 迭代器 → 文件”画布上会出现一个黄色的迭代器图标。双击它设置工作空间或文件夹选择存放所有nc文件的目录。通配符输入*.nc只处理nc文件。递归子目录按需勾选。如果文件都在同一层目录可以不勾。迭代器有两个输出一个是“文件”代表每个.nc的完整路径另一个是“名称”代表不带扩展名的文件名。前者用来替换“创建NetCDF栅格图层”的输入文件路径后者用来拼输出文件夹名。把迭代器的“文件”输出连接到“创建NetCDF栅格图层”的“输入netCDF文件”参数上。这样每次循环都会自动读入一个新的nc文件并生成同名的临时多波段栅格图层。4.2 输出文件夹自动创建防止文件互相覆盖批量处理最常见的翻车现场就是输出文件全堆在一个目录里。假设第一个文件导出temp_1.tif、temp_2.tif第二个文件也会导出temp_1.tif、temp_2.tif同名文件直接互相覆盖最后只剩最后一个文件的结果前面的全白跑。解决方案是在每个文件夹里建一个子文件夹。在模型窗口里再加一个“创建文件夹”工具位置在“数据管理工具 → 工作空间 → 创建文件夹”。设置参数父文件夹选一个总的输出目录。文件夹名称输入%名称%这里的%名称%就是迭代器输出的当前文件名变量。然后把“创建文件夹”工具的输出连接到“分割栅格”的“输出文件夹”参数上。这样每次循环都会自动生成一个以当前nc文件名命名的子文件夹并把拆分结果放进去。文件名不再冲突后续查找对应关系也方便。这里需要注意的是模型构建器处理多个工具连接的时候有时需要把“创建文件夹”工具的“文件夹”输出连到“分割栅格”的“输出文件夹”而不是直接把父目录路径写死。4.3 批量运行的注意事项与耗时经验全部连接完成后保存模型点运行。整个模型会循环执行读一个nc、生成多波段栅格、建子文件夹、拆分波段然后进入下一个文件全程不需要人工干预。实测经验方面一个包含365个波段、空间范围覆盖中国区域、分辨率0.25度左右的nc文件在我的办公电脑普通i5处理器16G内存机械硬盘上从读取到全部导出约需两三分钟。如果换成固态硬盘速度能明显提升瓶颈主要在磁盘写入上。如果文件特别多建议先处理1到2个文件确认输出无误再批量扔给机器慢慢跑。跑的过程中尽量不要在ArcMap里做其它大操作尤其是内存占用较高的地图渲染、缓存清理容易把模型顶挂。还有一个小技巧为整个模型设置环境时把“并行处理因子”调低一点避免ArcGIS一次性开太多线程导致CPU过载、磁盘I/O排队反而变慢。在数据量不大时这个参数差异不明显但一旦跑几十个文件稳定比极限速度更重要。5. 常见问题与排查经验5.1 分割栅格里没有“按波段分割”选项不少人在ArcMap里找“分割栅格”工具时打开参数下拉框发现分割方式只有按大小分块、按数量分块找不到“SPLIT_BAND”。这种情况通常有三种原因第一输入栅格实际上是单波段图层。比如“创建NetCDF栅格图层”时波段维度没有选时间维度或者选错了变量导致输出只有1个波段。单波段栅格自然无法按波段分割工具会默认屏蔽这个选项。可以用ArcMap的“识别”工具点一下图层或者右键图层属性 → 源查看“波段数”一栏确认。第二版本问题。ArcGIS 10.0之前的分割栅格工具还不支持按波段分割老版本用户需要升级到10.1以上的版本。现在大多数人用的10.8和ArcGIS Pro 3.x都支持没问题。第三使用“NetCDF转为栅格”生成的输出本身就是单波段文件拿它去做按波段分割当然没有意义工具一般也会置灰该选项。出现这种情况说明处理流程选错了应该回到“创建NetCDF栅格图层”这条路上来。5.2 波段编号与nc时间顺序对不上默认情况下“创建NetCDF栅格图层”生成的波段顺序就是nc文件中时间维度的存储顺序。第一个波段对应时间维度的第一个值最后一个波段对应最后一个值。大多数nc文件的时间维度都是按时间先后排列的所以temp_1.tif通常是第一天temp_365.tif是最后一天。但有个例外的坑有些nc文件的时间维度是倒序存储的或者中途混入了缺测时间点。遇到这种情况不要急着批量跑先做一次小样本验证。方法很简单用“创建NetCDF栅格图层”加载文件后打开波段属性或者用像元值对比的方式确认第一个波段对应的日期。也可以在模型里导出第一个和最后一个tif再把这两个tif和原始nc文件在ArcMap中分别叠加对比日期一目了然。如果发现顺序不一致宁可先想办法重新整理nc文件内部的时间维度也不要在导出后靠批量重命名去硬凑那样很容易出错。5.3 nc文件是四维数据带高度层怎么拆气候模式里很常见的情况是变量有4个维度例如时间、气压层、纬度、经度。比如ERA5再分析资料里的温度就是“时间 × 37层 × 纬度 × 经度”四个维度。这时候直接用“创建NetCDF栅格图层”工具会要求你选择一个维度的值比如指定某一层气压如850hPa然后生成这个层对应的时间序列多波段栅格。也就是说四维数据需要先“降维”成三维时间 × 纬度 × 经度再做波段拆分。操作方式有两种一种是在“创建NetCDF栅格图层”工具的“维度”设置里找到高度层维度填上目标值比如850其它参数不变生成的图层就是该层的多波段数据。另一种是先用“NetCDF转为栅格”工具把某个高度层导出一个中间栅格然后再套用分割栅格流程。不过这样会增加一步中间文件的写入和读取效率不如第一种。如果想把所有高度层全部拆出来比如37层 × 365天一次生成一万多个tif我建议外层再套一个高度层维度的循环或者直接用ArcPy脚本处理模型构建器会显得臃肿不少。5.4 数据量大、运行慢怎么办数据量一大运行时间就会明显拉长。如果你跑一个几百MB的nc文件需要半小时以上先别急着抱怨软件慢按下面几步排查。第一确认“创建NetCDF栅格图层”的输出是否勾选了中间数据。如果没有勾选ArcGIS可能正在往磁盘上写一个巨大的栅格数据集既浪费时间又占空间。第二检查“暂存工作空间”是否设置在固态硬盘上。ArcGIS默认的暂存路径在系统临时目录如果系统盘是机械硬盘或者空间不足写入速度会非常拖后腿。在模型属性里重新指定一个SSD上的目录很多时候速度能有明显提升。第三压缩类型选择。导出TIFF时选LZW压缩写出来的文件更小后续读取也更快代价是导出时CPU占用略高。对大多数机器来说LZW压缩是划算的。第四如果nc文件非常大几个G建议先用工具或脚本把研究区域裁剪出来再拆分。有些nc是全球范围的而你只需要中国区域先裁剪可以大幅减少像元数量拆分速度直接翻几倍。这个裁剪可以在创建NetCDF栅格图层之后、分割栅格之前加一个“按掩膜提取”或“裁剪”工具实现原理上和波段拆分不冲突。5.5 输出tif里出现大量NoDatanc文件里经常有填充值FillValue比如某些缺失时间步、海岸线以外的海洋格点都可能是用-9999、-32767这类特殊数值填充的。ArcGIS读取NetCDF时一般能识别填充值并转成NoData但在部分数据里由于属性设置不规范填充值可能被当成正常数值读进来。如果你导出的tif里出现大片异常极值比如气温图上一片-9999说明填充值没有被正确识别。处理办法是在“创建NetCDF栅格图层”生成图层后先不要急着拆分用“栅格计算器”或“条件函数”把填充值重设为NoData比如写成SetNull(ras -9999, ras)再连接“分割栅格”工具。这样拆分出来的每个波段都是干净的。另外提醒一句分割栅格工具本身没有“忽略波段NoData”这种选项它只是原样把像元值复制出去所以预处理很重要。写在最后的个人经验搭这个模型的时候我自己也踩过几次坑最典型的就是第一次忘了选“波段维度”结果导出来只有一个tif当时还以为是软件卡了。后来养成一个习惯任何批量处理任务先手动跑一个小样本验证波段数、文件命名、空间位置、像元值四个要素都没问题再放量去跑。整个模型构建到跑完十几批数据总共也就花了一个下午的时间但省下来的重复劳动却是海量的。如果你后续想把波段号转成真实日期文件名可以在模型跑完后用一小段ArcPy脚本读tif属性里的时间标记或者按文件名序号映射到日期清单但这是另一篇文章的内容了。现阶段把“创建NetCDF栅格图层 分割栅格”这套流程吃透已经能解决绝大多数nc逐波段批量导出的需求。
返回列表