GIUHArcGIS水文提取工具箱Skill giuh-arcgis-extraction

本技能用于在 ArcGIS 10.6(Python 2.7)环境中构建和运行地貌瞬时单位线(GIUH)工具箱,实现 DEM 提取河网与流域(Strahler分级)、交互式出口点选择、Horton 比率计算、GIUH 概率密度(超指数分布)、等效 Nash 单位线及时段单位线(DUH)。涵盖 GIUH 特定代码模式(Python 2.7 安全的 CSV/JSON/matplotlib 写入、无 numpy 的栅格分区统计、子流域栅格掩膜提取)及 3 文件工具箱打包。关键词:ArcGIS 10.6、Python 2.7、GIUH、地貌单位线、DEM 水文提取、Strahler 分级、Horton 比率、Nash 单位线、流域提取、栅格处理、py2.7 兼容、工具箱打包。

数据分析 0 次安装 4 次浏览 更新于 8/24/2026

名称:giuh-arcgis-extraction 描述:> 用于构建、运行、调试或打包 ArcGIS 10.6(Python 2.7)地貌瞬时单位线(GIUH)工具箱:DEM -> 河网 与流域提取(Strahler)-> 交互式出口点选择 -> Horton 比率(R_B/R_L/R_A)-> GIUH 概率密度(超指数分布)-> 等效 Nash 单位线 -> 时段单位线(DUH)。涵盖 GIUH 特定的 代码模式(py2.7 安全的 CSV/JSON/matplotlib 写入、无 numpy 的带状 统计、子流域栅格掩膜提取)以及打包 3 文件工具箱。搭配 技能 arcgis10x-py27-compat 适用于通用 ArcGIS 10.x Python 2.7 陷阱。 agent_created: true

GIUH 提取工具箱(ArcGIS 10.6 / Python 2.7)

本技能记录了在 ArcGIS 10.6 Desktop(Python 2.7,Spatial Analyst)内从 DEM 生成地貌单位线的经过验证的工作流程和来之不易的经验。该工具包位于项目工作区中,是一个3 文件自包含工具箱,可复制到任何 ArcGIS 10.6 机器。

通用 ArcGIS 10.x / Python 2.7 兼容性陷阱(全角字符、 ImageServer 999999、红叉、ZonalStatisticsAsTable MAXIMUM、数据类型关键字) 由技能 arcgis10x-py27-compat 涵盖。本技能仅涵盖 GIUH 领域的工作流程和 GIUH 特定的 py2.7 代码模式。如果您遇到通用的 ArcGIS 错误,请先阅读该技能。

1. 工具箱文件结构(3 文件包)

文件 作用
watershed_uh_toolbox.pyt 工具箱入口。ArcGIS“添加工具箱”指向此处。
arcgis_uh_workflow.py 流程:DEM -> 河网 -> 子流域 -> 统计。
giuh_calculator.py 纯 stdlib GIUH 数学引擎(无需 numpy)。

导入链是路径无关的:每个模块通过 os.path.dirname(os.path.abspath(__file__)) 将自己的目录插入 sys.path,因此三个文件必须放在同一文件夹,但可以位于磁盘上的任何位置。可选文档: README_watershed_uh.md。matplotlib 可选(仅 PNG);缺失时会优雅降级(_HAVE_MPL=False 跳过绘图)。

两个工具:

  • DEMHydrologyExtraction(类 DEMHydrologyExtraction)-> 包装 arcgis_uh_workflow.extract_network
  • InteractiveOutletUnitHydrograph(类 InteractiveOutletUnitHydrograph)-> 包装 arcgis_uh_workflow.run_outlet_and_uh

2. 工作流程

工具 1 — extract_network(dem, out_ws, threshold=1000, out_name="hydro", ...) (DEM -> 河网 + 流域):

  1. Fill -> FlowDirection(fill, "NORMAL") -> FlowAccumulation(flow_dir)
  2. StreamOrder(link_ras, flow_dir, "STRAHLER") -> order_ras
  3. 输出最高 Strahler 级河流图层(供用户选择出口点)+ 一个 hydro_meta.json(像元大小、最高级、空间参考、路径)。 所有栅格输出使用 .tif(ESRI GRID 有 13 字符基名限制; hydro_strahler = 14 字符 -> ERROR 010240)。

工具 2 — run_outlet_and_uh(meta_json, pour_features, velocity=None, slope=None, ...) (交互式出口点 -> 子流域 -> 单位线):

  1. 用户提供一个点 shapefile 作为出口点(pour_features)。 (为什么用 shapefile 而不是交互式草图图层:见陷阱 6。)
  2. SnapPourPoint(pour_features, flow_acc, snap_dist)(snap_dist = 5 * cell)。
  3. Watershed(flow_dir, snapped_pour) -> subbasin.shp
  4. 使用 ExtractByMask 将所有栅格(flowacc、dem、flowdir、strahler、link、stream)裁剪到子流域,然后再进行任何统计(见陷阱 2)。
  5. 不使用 numpy 的统计(陷阱 1):用 ZonalStatisticsAsTable 得到 link->order 映射和每个 order 的流量累积均值;用 SearchCursor 统计河流数量/长度;用 GetRasterProperties(flowlen, "MAXIMUM") 得到最长流路 L_Omega
  6. compute_horton_ratios(orders) -> R_B, R_L, R_A;从 L_Omega 和坡度 estimate_velocitybuild_giuh + export_results -> CSV + JSON + PNG。

3. GIUH 数学 API(giuh_calculator.py

输入 orders = 字典列表:{"order": int, "n": float(河流数), "length": float(km), "area": float(km^2)}

  • compute_horton_ratios(orders) -> (R_B, R_L, R_A, diag)(几何均值)。
  • estimate_velocity(length_km, slope) -> v(m/s)基于 sqrt(g*L*S) 风格。
  • giuh_pdf(orders, velocity, t, length_unit="km") -> 超指数 PDF。 返回密度单位为 s⁻¹。 组装时间序列时必须乘以 sec_per(小时为 3600),否则坐标值会偏差该因子 (仅修复后 ∫h dt ≈ 0.9995)。
  • giuh_moments(orders, velocity, length_unit="km") -> (mean, var)
  • equivalent_nash(mean, var) -> (n, k) 水库(n = mean²/var, k = var/mean)。
  • nash_iuh(t, a, k) / nash_duh(t, a, k, D) -> Nash IUH 和时段-UH(DUH 通过归一化下不完全伽马函数;无需 scipy)。
  • build_giuh(orders, velocity, length_unit="km", time_unit="h", ...) -> 网格字典 (t, h, u, cum_h, cum_u, nash_n, nash_k_out)。
  • export_results(orders, velocity, length_unit="km", time_unit="h", out_dir, D=None, make_plot=True, basename="unit_hydrograph") -> {"csv", "json", "png"}。 CSV 表头为中文(时间(h)GIUH瞬时单位线(1/h)、…);JSON summary 有中文 note 字段(py2.7 安全)。

可复用的 py2.7 安全 I/O 助手(照抄即可):

  • _write_text(path, text) — py3 io.open(encoding="utf-8");py2 open(path,"wb").write
  • _to_unicode(obj) — 递归将 py2 str(bytes) 解码为 unicode;py3 无操作。
  • _open_csv_writer(path) — py3 io.open(path,"w",newline="",encoding="utf-8-sig") (BOM 用于 Excel);py2 io.open(path,"wb")(二进制)。返回 (f, w)
  • _csv_row(writer, cells) — py2:在 writer.writerow 之前将每个单元格编码为 utf-8 字节;py3:直接写入。

4. GIUH 特定的 ArcGIS 10.6 / Python 2.7 陷阱(不在 arcgis10x-py27-compat 中)

  1. ArcGIS 10.6 Python 2.7 默认没有 numpy。 切勿使用 RasterToNumPyArray 进行 Horton 统计——它会静默产生全零 面积并导致 compute_horton_ratios 崩溃(几何均值需要正值)。 全部使用纯 ArcGIS 做统计:ZonalStatisticsAsTableGetRasterPropertiesSearchCursor

  2. 掩膜一致性。 当组合多个栅格(例如 strahler vs flowacc vs 子流域)时,首先用 ExtractByMask 将它们都 裁剪到同一子流域范围。范围不匹配会产生静默的全零面积——正是引起 R_A 几何均值崩溃的 bug。

  3. py2.7 下的 CSV 写入。 使用 §3 中的 _open_csv_writer/_csv_row。 模式:f, w = _open_csv_writer(p); try: _csv_row(w, row) finally: f.close()不要写 with _open_csv_writer(p) as (f, w):——返回的元组不是 上下文管理器 -> AttributeError: __exit__py_compile 不会捕获此错误; 运行导出路径验证。

  4. py2.7 下的 JSON 写入。 调用 json.dumps(_to_unicode(summary), ensure_ascii=False, indent=2)。任何不是 u"..." 的中文字符串字面量在 py2.7 中是 UTF-8 字节 str,会使 json.dumps(ensure_ascii=False) 抛出 UnicodeDecodeError。切勿裸用 json.dumps(obj)

  5. matplotlib 中文标签。 导入 matplotlib 后设置 matplotlib.rcParams["font.sans-serif"] = ["SimHei","Microsoft YaHei","SimSun", "FangSong","KaiTi",...]matplotlib.rcParams["axes.unicode_minus"]=False。 传递给 pyplot 的每个 label/title/xlabel/ylabel 必须是 u"..."(unicode), 否则 set_label 内部的 '%s' % s 会对字节字符串进行 ascii 解码并抛出 UnicodeDecodeError。缺少 CJK 字体会显示方框(不会崩溃)。后端已经是 Agg(仅文件,无 GUI)。

  6. 交互式出口点草图图层在 10.6 上已损坏。 GPFeatureRecordSetLayer 悬停光标一直是手形(永远不会变成十字准线),即使设置了 schema.featureType="Simple"/hasZ=False/hasM=False。修复:将出口点 参数设为 GPFeatureLayer 并过滤为 Point;用户创建一个 1 点 shapefile(与 DEM 相同的坐标系!)并选择它。将点放在最高级河流图层上或旁边(捕捉距离 ≈ 5 个像元)。

  7. GRID 13 字符限制 -> 始终输出 .tif 栅格(见 §2 工具 1)。

  8. 模块编辑后需完全重启 ArcMap。 arcgis_uh_workflow.pygiuh_calculator.py.pyt 懒加载并缓存在 sys.modules 中。编辑它们后,仅刷新工具箱是不够的—— 必须完全关闭并重新打开 ArcMap。(同时禁用后台地理处理以避免 旧模块 / ImageServer 999999 问题;见 arcgis10x-py27-compat 陷阱 7。)

5. 部署打包

将 3 个核心文件(watershed_uh_toolbox.pytarcgis_uh_workflow.pygiuh_calculator.py)+ README_watershed_uh.md 复制到一个文件夹中,压缩,部署 到目标机器,然后“添加工具箱” .pyt。保持它们在一起。不需要 外部 Python 包(matplotlib 可选)。已构建的 分发包位于工作区的 GIUH_Toolbox_Dist/

6. 快速诊断

如果工具 2 中途失败,回溯前的最后几行 arcpy.AddMessage 会告诉您哪个阶段出错(SnapPourPoint / Watershed / 统计 / GIUH 导出)。 大多数剩余失败来自上述 py2.7 编码陷阱(CSV/JSON/matplotlib) 或 numpy/ZonalStatistics 替换(陷阱 1)。应用相应修复并完全重启 ArcMap 后重新运行。