2026-06-03 srtm数据 管道处理

使用数据组git中的kfqself分支来处理,或者clcd分支(需要自己添加srtm3的支持)

一键脚本(推荐):把 3.1 → 3.6 串起来跑,断点续跑,失败可直接重跑:

bash scripts/hangzhou/run_full_hangzhou.sh

自定义 workers:

WORKERS=4 bash scripts/hangzhou/run_full_hangzhou.sh

Windows 几何由 repo 根目录的 hangzhou_olmoearth_windows.json 固定;如需自定义可
WINDOWS_JSON=/path/to/other.json override。

如果想了解每一步具体在做什么,或想分步排查,继续看下面 3.1-3.6 手动版本。

3.1 转换原始 hgt + 写 file_list.json

python scripts/hangzhou/01_convert_hgt_to_geotiff.py \
  --hgt_dir    data/srtm_hangzhou \
  --mirror_dir data/srtm_hangzhou/hf_mirror

预期:data/srtm_hangzhou/hf_mirror/ 下出现 N29/N30/ 共 6 个 SRTM1*V2.tif,加一个 file_list.json

3.2 生成杭州 res_10 windows

python scripts/hangzhou/02_create_windows.py \
  --ds_path data/rslearn_hangzhou_srtm

Windows 来自 repo 根目录的 hangzhou_olmoearth_windows.json(无需手动指定)。

预期:输出末尾 Created 6272 windows under data/rslearn_hangzhou_srtm/windows/res_10/

3.3 准备 rslearn dataset 配置

sed "s|LOCAL_ROOT_PLACEHOLDER|$(pwd)/data/srtm_hangzhou/hf_mirror|" \
  data/rslearn_hangzhou_srtm/config.template.json \
  > data/rslearn_hangzhou_srtm/config.json

3.4 rslearn 三连(用 8 workers 适配 16 GB)

export DS=./data/rslearn_hangzhou_srtm
export WORKERS=8

rslearn dataset prepare    --root $DS --group res_10 --workers $WORKERS
rslearn dataset ingest     --root $DS --group res_10 --workers $WORKERS --no-use-initial-job
rslearn dataset materialize --root $DS --group res_10 --workers $WORKERS --no-use-initial-job

中途内存压力大可 Ctrl-C,降 WORKERS=4 重跑。三连均可断点续跑(已完成的 window 自动跳过)。

与 JSON 清单对账

确认 materialize 后的 rslearn dataset 与 hangzhou_olmoearth_windows.json 完全一致(名字 + projection + bounds + 每个 window 都有非空 .tif):

uv run --extra all-no-flash python scripts/hangzhou/verify_windows_against_json.py \
  --ds_path data/rslearn_hangzhou_srtm \
  --require-materialized

预期:OK: 6272 windows match JSON exactly (names + projection + bounds), all materialized。该脚本三模态共用(SRTM / Landsat / CLCD 都跑同一份 JSON)。

3.5 跑 srtm.py 转 OlmoEarth 单文件格式

python -m olmoearth_pretrain.dataset_creation.rslearn_to_olmoearth.srtm \
  --ds_path        $DS \
  --olmoearth_path ./data/olmoearth_hangzhou_srtm \
  --workers        $WORKERS

3.6 聚合模态级 metadata

python -m olmoearth_pretrain.dataset_creation.make_meta_summary \
  --olmoearth_path ./data/olmoearth_hangzhou_srtm \
  --modality       srtm \
  --time_span      static

预期产物:data/olmoearth_hangzhou_srtm/10_srtm.csv,行数 = window 数 + 1(header)。


服务器端运行(Linux 生产环境)

如果本地 Mac 跑完 sample / 烟囱测试通过,要把全杭州流程挪到 Linux 服务器上跑(更多核 / 更多 RAM / 不用占本地机器),按下面流程。整体流水线和"第 3 步"完全一样,差异只在环境配置 + 后台运行 + 数据进出。

服 0. 服务器侧前置

  • Linux x86_64(Ubuntu 22.04+ / Debian 12+ / RHEL 9+ 都可以)
  • Python 3.12 + uv(预装,或现装 curl -LsSf https://astral.sh/uv/install.sh | sh)
  • 磁盘 ≥ 10 GB 空闲(原始 .hgt ~150 MB + rslearn 中间产物 ~3 GB + OlmoEarth 输出 ~600 MB + 缓冲)
  • RAM ≥ 16 GB(8 workers);RAM 紧时降到 4 workers + 8 GB 也能跑
  • 不需要 AWS / 网络(SRTM 是纯本地数据源)

服 2. 在服务器上跑一键脚本(后台 + 日志)

cd /path/to/olmoearth_pretrain
mkdir -p logs

# 用 nohup 后台跑,日志落到 logs/srtm_run.log
nohup bash scripts/hangzhou/run_full_hangzhou.sh > logs/srtm_run.log 2>&1 &
echo $! > logs/srtm_run.pid

# 看进度(日志末尾)
tail -f logs/srtm_run.log

或者用 tmux(可断开 SSH 重连):

tmux new -s srtm
bash scripts/hangzhou/run_full_hangzhou.sh 2>&1 | tee logs/srtm_run.log
# Ctrl-B D 断开;ssh 上来后 tmux attach -t srtm 重连

可调环境变量:

WORKERS=16 bash scripts/hangzhou/run_full_hangzhou.sh

服 3. 监控 + 中断恢复

跑到一半想看进度:

# 看当前进度
tail -50 logs/srtm_run.log

# 看已完成的 windows 数(主要瓶颈在 ingest + materialize)
find data/rslearn_hangzhou_srtm/windows/res_10 -name 'completed_*' | wc -l

# 看产出 .tif 数(srtm.py 转换阶段)
find data/olmoearth_hangzhou_srtm/10_srtm -name '*.tif' | wc -l

中断(Ctrl-Ckill $(cat logs/srtm_run.pid))后重跑同一脚本,所有子命令自动跳过已完成 window,安全续跑

服 4. 拿回产物

如果训练也在服务器上,不用拿回——data/olmoearth_hangzhou_srtm/ 留在原地等下游消费。

如果要拷回本地:

# 本地
rsync -avP --exclude='10_srtm_meta' \
  user@server:/path/to/olmoearth_pretrain/data/olmoearth_hangzhou_srtm/ \
  ./data/olmoearth_hangzhou_srtm/
  • 10_srtm/:核心交付物(每 window 一个 GeoTIFF,~600 MB)
  • 10_srtm.csv:聚合 metadata(几十 KB,必拷)
  • 10_srtm_meta/:per-window 临时 CSV,不拷(已被聚合进 .csv)

服 5. 服务器侧验证

uv run --extra all-no-flash python scripts/hangzhou/verify_hangzhou.py \
  --srtm_dir data/olmoearth_hangzhou_srtm/10_srtm

跟本地"## 验证产物"完全一致(下面那段)。

资源预算(典型 Linux 服务器)

配置 WORKERS 全杭州耗时 RAM 峰值
8 vCPU / 16 GB(够用) 8 30-50 分钟 ~12 GB
16 vCPU / 32 GB(舒服) 16 15-25 分钟 ~20 GB
32 vCPU / 64 GB(过剩) 24 10-15 分钟 ~30 GB

主要时间在 rslearn dataset materialize(~70%)+ srtm.py 转换(~25%)。

跟 Landsat / CLCD 服务器流程的关系

模态 是否需要 AWS 是否需要外网 跑全杭州时间 输出体积
SRTM(本指南) ❌(纯本地) ~30 分钟 ~600 MB
Landsat ✅ Requester Pays ✅(s3.us-west-2) ~4-8 小时 ~50 GB
CLCD ❌(纯本地,从 Zenodo 下) ~5-10 分钟 ~50 MB

SRTM 是三个里最简单的服务器侧场景(无 AWS、无网络、无代理需求)。如果 SRTM 跑通,Landsat 和 CLCD 的服务器流程见各自的运行指南。


验证产物

一键深度验证(推荐)

uv run --extra all-no-flash python scripts/hangzhou/verify_hangzhou.py \
  --srtm_dir data/olmoearth_hangzhou_srtm/10_srtm

会做 4 项交叉检查:

  1. CRS / 尺寸 / 分辨率:每个 tile 必须是 256×256 @ 10 m,在 EPSG:32650 或 32651
  2. 反投影到 WGS84:每个 tile 中心反算成经纬度,必须落在杭州 bbox 内,平均中心应在 (120.20, 30.25) 附近
  3. 地标交叉验证:找离西湖、杭州湾、临安西部山地、千岛湖、萧山主城最近的 tile,验证高程值在合理范围(西湖 ~5–30m、杭州湾 ~0–5m、临安山地 200–1500m 等)
  4. 全局高程分布:全局 min 应 ≈ 0(海面),max 应 ≥ 500m(临安/淳安山地)

跑完应该看到大量 ✅。出现 ⚠️ 时阅读上下文判断是真错(数据不对)还是合理(比如 bbox 缩小了某个地标没覆盖)。

主城区范围的烟囱测试不会覆盖到临安山地,所以"临安"那项和"全局 max ≥ 500"在烟囱阶段会显示 ⚠️,这是正常的;全杭州 run 完之后这两项必须变 ✅

手动快速检查

# 1. 检查 SRTM 切片数量
find data/olmoearth_hangzhou_srtm/10_srtm -name '*.tif' | wc -l
# 应该接近 window 数

# 2. 抽样一张 SRTM tif 看元数据
SAMPLE=$(find data/olmoearth_hangzhou_srtm/10_srtm -name '*.tif' | head -1)
uv run --extra all-no-flash python -c "
import rasterio, sys
with rasterio.open(sys.argv[1]) as src:
    print('CRS:', src.crs)        # 应是 EPSG:32650 或 32651
    print('Size:', src.width, 'x', src.height)  # 应是 256 x 256
    print('Resolution:', src.res)  # 应是 (10, 10)
    arr = src.read(1)
    print('Elevation range:', arr.min(), '-', arr.max(), 'meters')
" "$SAMPLE"

# 3. 检查聚合 CSV
head -3 data/olmoearth_hangzhou_srtm/10_srtm.csv
wc -l data/olmoearth_hangzhou_srtm/10_srtm.csv

可视化(肉眼看地形)

GeoTIFF 在 Finder/Preview 里显示成黑色是正常的(int16 高程值远超 8-bit 范围),看图必须做拉伸:

# 抽 4 张拼出彩色地形图
uv run --extra all-no-flash python -c "
import rasterio, matplotlib.pyplot as plt, glob
files = sorted(glob.glob('data/olmoearth_hangzhou_srtm/10_srtm/*.tif'))
fig, axes = plt.subplots(2, 2, figsize=(10, 10))
for ax, f in zip(axes.flat, files[:4]):
    with rasterio.open(f) as src:
        arr = src.read(1)
    im = ax.imshow(arr, cmap='terrain', vmin=0, vmax=max(arr.max(), 100))
    ax.set_title(f.split('/')[-1] + f' max={arr.max()}m')
    plt.colorbar(im, ax=ax)
plt.tight_layout()
plt.savefig('/tmp/hangzhou_srtm.png', dpi=120)
print('Saved /tmp/hangzhou_srtm.png')
" && open /tmp/hangzhou_srtm.png

或者直接把 data/olmoearth_hangzhou_srtm/10_srtm/*.tif 拖进 QGIS —— QGIS 会自动拉伸,能直接看到地形(主城区平原 + 西部山地)。


故障排查

现象 可能原因 处置
gdal_translate: command not found 没装 GDAL,且我们的代码意外调用了它 我们用 rasterio,不该需要;若仍需要 brew install gdal
Failed to build flash-attn Mac 用 --all-extras 触发了 flash-attn 编译 改用 uv sync --locked --extra all-no-flash --python 3.12
encode_raster() got an unexpected keyword argument 'raster' rslearn 0.0.29 把 kwarg 从 raster 改成了 array,仓库里很多 rslearn_to_olmoearth/*.py 还用旧名 raster=image 改成 array=image(srtm.py 已修;若合作方跑其它模态时遇到,同样改)
ModuleNotFoundError: rslearn 没装 dataset-creation extra uv sync --locked --extra all-no-flash
requests.exceptions.InvalidSchema: file:// LocalSRTM override 没生效 检查 config.jsonclass_patholmoearth_pretrain.dataset_creation.local_data_sources.local_srtm.LocalSRTM
Step 3.4 卡住 / 内存满 workers 太多 降到 4 重跑(已完成 window 会跳过)
is_layer_completed=False 跳过所有 window materialize 没跑完或失败 检查 windows/res_10/<name>/layers/srtm/ 下有无 completed 文件,重跑 materialize
Step 3.6 报 "no temp metadata found" Step 3.5 没真正写出文件 抽查任意 window 的 OlmoEarth 目录确认有 tif + temp CSV
Window count 远低于预期 bbox 错了 / hf_mirror 路径配错 检查 config.jsonlocal_root 是绝对路径,且指向真实存在的 mirror

清理 / 回滚

整条流水线产物都在 data/ 下三个新目录,可整体删除重来,不影响仓库其它部分:

rm -rf data/srtm_hangzhou/hf_mirror
rm -rf data/rslearn_hangzhou_srtm
rm -rf data/olmoearth_hangzhou_srtm
rm -rf data/_smoke_hangzhou

新增源代码(olmoearth_pretrain/dataset_creation/{hangzhou,local_data_sources}/scripts/hangzhou/tests/unit/dataset_creation/)未修改任何已有文件,删除即回到当前状态。


想做更多?

  • 改 windows 几何:生产管线 windows 全部来自 hangzhou_olmoearth_windows.json(repo 根目录,6,272 个 256×256 @ 10 m tile)。要做嘉兴 / 宁波 / 整个长三角,先重新生成一份 windows JSON,再 --windows-json <path>WINDOWS_JSON=<path> 传给脚本——同时要保证原始 .hgt 数据覆盖到目标区域。本地子区域开发可以用 scripts/hangzhou/_filter_windows_json.py --bbox ... --output <subset>.json 从主 JSON 切一个子集。
  • 走完训练链路:补一个时变模态(ERA5_10 是最简单,纯本地不依赖外部凭证),重跑 Step 3.4-3.6 给该模态,然后跑 python -m olmoearth_pretrain.internal.run_h5_conversion(参见 plan 文件 Step 9 章节)。
  • 真正训练模型:需要至少 Sentinel-2 + SRTM 这种多模态组合,且涉及大量 GPU 资源,远超本指南范围。

本任务的边界 — 你做到哪步就停

结论:第 3.6 步跑完(10_srtm.csv 写出),你的全部数据准备工作就完成了。

后续 H5 打包(convert_to_h5py)和模型训练不属于本任务,留给合作方:

  • 不要单独打包 SRTM-only H5:OlmoEarth dataloader 的过滤器(convert_to_h5py.py:617-633)要求每样本至少一个时变模态 ≥12 时间步,SRTM 是静态的,SRTM-only H5 全部样本都会被丢弃,毫无意义。
  • 正确路径:把 SRTM 切片交付给合作方;他们补完 Sentinel-2/Sentinel-1/ERA5/OSM 等模态后,统一跑一次 H5 打包,所有模态的 sample 才能配齐。

完整 OlmoEarth 预训练数据集地图(供参考,看你卡在哪)

模态 类型 时间属性 数据源 凭证要求 谁负责
SRTM 高程 static 已本地 30m 本任务
Sentinel-2 L2A 12 波段光学 two_week Microsoft PC 合作方
Sentinel-1 GRD VV+VH 2 波段雷达 two_week Microsoft PC 合作方
Landsat 8/9 11 波段光学 two_week AWS AWS 凭证 合作方(可选)
ERA5 月度气象 two_week Copernicus CDS CDS API key 合作方
OpenStreetMap 矢量栅格化 static OSM PBF 合作方
WorldCover 土地覆盖 static ESA/HF 合作方
WorldCereal 作物图 static ESA 合作方
WRI Canopy Height 树冠高度 static Meta/HF 合作方
USDA CDL 美国农田 annual USDA 跳过(美国境外无数据)
H5 打包(终点) 训练样本 convert_to_h5py 合作方汇总后统一跑

交付清单(给合作方)

把下面 4 项打包给合作方,他们就能继续跑其它模态并最终做 H5 打包:

# 路径 说明
1 data/rslearn_hangzhou_srtm/windows/res_10/(打 tar,~50 MB,纯 metadata JSON) 杭州 windows 集合,~6000 个。合作方处理其它模态时必须复用这同一份 windows,不能各自重新生成
2 data/olmoearth_hangzhou_srtm/10_srtm/(每 window 一个 GeoTIFF,~600 MB) OlmoEarth 标准格式的 SRTM 切片
3 data/olmoearth_hangzhou_srtm/10_srtm.csv 模态级聚合 metadata,行数 = window 数 + 1(header)
4 本指南 docs/杭州SRTM-运行指南.md + 设计文档 ~/.claude/plans/a-async-valiant.md(可选) 让合作方了解你做了什么、约定如何形成

协议要点(必须告知合作方)

约定值
杭州空间范围 bbox (118.2889081, 29.1563713, 120.7598261, 30.5935326) WGS84(与 CLAUDE.md "杭州 (Hangzhou) 区域常量" 一致)
windows 来源 data/rslearn_hangzhou_srtm/windows/res_10/,~6000 个,禁止重新生成
CRS 集合 EPSG:32650(UTM 50N)+ EPSG:32651(UTM 51N)。杭州跨两个 UTM 区,合作方 ingest 必须保留 windows 原有 CRS
每 window 尺寸 256×256 像素 @ 10 m,即 2.56 km × 2.56 km
占位时间戳 SRTM 用 2020-01-01 UTC 作占位。合作方处理时变模态时会用真实采集时间替换,这没问题
OlmoEarth 输出根目录 data/olmoearth_hangzhou_srtm/。合作方的其它模态目录必须落在同一个根下,H5 打包阶段才能找齐所有模态
H5 打包触发条件 等所有约定模态(至少 S2 L2A 必须有,因为它是 H5 的 required_modality)都跑完 + 各自 make_meta_summary 完毕,统一跑一次 python -m olmoearth_pretrain.internal.run_h5_conversion --tile_path ./data/olmoearth_hangzhou_srtm --supported_modality_names '[srtm,sentinel2_l2a,...]' --required_modality_names '[sentinel2_l2a]' --compression zstd --tile_size 128

给合作方的一句话提示

杭州 windows 用我这份(data/rslearn_hangzhou_srtm/windows/res_10/),你们处理 S2/S1/ERA5/OSM 等模态时,把各自 rslearn dataset 的 windows/res_10/ 替换成我这份再跑 ingest+materialize;olmoearth_path 都指向 data/olmoearth_hangzhou_srtm/。所有模态都灌完之后再统一跑 convert_to_h5py,产物 h5py_data_w_missing_timesteps/sample_*.h5 即是 dataloader 直接读的训练数据集。

合作方接手后还需做哪些(供你了解,不要做)

  1. 复用杭州 windows + 每个时变 / 静态模态分别跑 6 步流程(prepare → ingest → materialize → 转 OlmoEarth → make_meta_summary)
  2. Sentinel-2 / Sentinel-1 数据量大(~30-100 GB),需准备 ~300 GB 磁盘 + 数小时下载
  3. ERA5 需注册 Copernicus CDS 账号(免费)拿 API key
  4. OpenStreetMap 处理最折腾(需 OSM PBF + Go 处理 + 类别配置),建议放最后
  5. 所有模态齐了之后,跑一次 H5 打包,产物即"可直接训练的数据集"
  6. 训练(GPU + 多模态多日训练)是再下一阶段的事,与数据准备无关
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容