Files

1487 lines
56 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#! /usr/bin/env python
import os
import sys
import numpy as np
import argparse
import subprocess
import glob
from skimage import io
# 尝试导入 NASADEM 库
try:
from NASADEM import NASADEM
from rasters import RasterGrid
HAS_NASADEM = True
except ImportError:
HAS_NASADEM = False
print("Warning: NASADEM library not installed. NASADEM download will not be available.")
print("Install with: pip install nasadem rasters")
# 尝试导入 srtm 库
try:
import srtm
HAS_SRTM = True
except ImportError:
HAS_SRTM = False
print("Warning: srtm library not installed. SRTM download will not be available.")
print("Install with: pip install srtm (requires Python >= 3.12)")
print(f"Current Python version: {sys.version_info.major}.{sys.version_info.minor}")
resolutions = 30 # 90
def write_demrsc_file(FILE, Corner_LON, Corner_LAT, X_STEP, Y_STEP, WIDTH, LENGTH):
"""Write ROI_PAC DEM resource file (.dem.rsc)
Args:
FILE (str): Output resource file path
Corner_LON (str): Corner longitude
Corner_LAT (str): Corner latitude
X_STEP (str): Longitude step size
Y_STEP (str): Latitude step size
WIDTH (str): Number of columns
LENGTH (str): Number of lines
"""
f = open(FILE, 'w')
f.write('DATE12 111111-222222\n')
f.write('FILE_LENGTH ' + str(int(LENGTH)) + '\n')
f.write('FILE_TYPE .dem\n')
f.write('PROCESSOR roipac\n')
f.write('PROJECTION LATLON\n')
f.write('RLOOKS 1\n')
f.write('WIDTH ' + str(int(WIDTH)) + '\n')
f.write('XMAX ' + str(int(int(WIDTH)-1)) + '\n')
f.write('XMIN 0\n')
f.write('X_FIRST ' + str(float(Corner_LON)) + '\n')
f.write('X_STEP ' + str(float(X_STEP)) + '\n')
f.write('X_UNIT degrees\n')
f.write('YMAX ' + str(int(int(LENGTH)-1)) + '\n')
f.write('YMIN 0\n')
f.write('Y_FIRST ' + str(float(Corner_LAT)) + '\n')
f.write('Y_STEP ' + str(float(Y_STEP)) + '\n')
f.write('Y_UNIT degrees\n')
f.write('Z_OFFSET 0\n')
f.write('Z_SCALE 1\n')
f.close()
def write_dempar_file(FILE, Corner_LON, Corner_LAT, X_STEP, Y_STEP, WIDTH, LENGTH, DATA_FORMAT):
"""Write Gamma DEM parameter file (.dem.par)
Args:
FILE (str): Output parameter file path
Corner_LON (str): Corner longitude
Corner_LAT (str): Corner latitude
X_STEP (str): Longitude step size
Y_STEP (str): Latitude step size
WIDTH (str): Number of columns
LENGTH (str): Number of lines
DATA_FORMAT (str): Data format (INTEGER*2 or REAL*4)
"""
DEM_TYPE = 'Copernicus30'
Proj = 'EQA'
f = open(FILE, 'w')
f.write("Gamma DIFF&GEO DEM/MAP parameter file\n")
f.write("title:\tIMPORTED DEM FROM %s\n" % DEM_TYPE)
f.write("DEM_projection: %s\n" % Proj)
f.write("data_format: %s\n" % DATA_FORMAT)
f.write("DEM_hgt_offset: 0.00000\n")
f.write("DEM_scale: 1.00000\n")
f.write("width: %s\n" % WIDTH)
f.write("nlines: %s\n" % LENGTH)
f.write("corner_lat: %s decimal degrees\n" % Corner_LAT)
f.write("corner_lon: %s decimal degrees\n" % Corner_LON)
f.write("post_lat: %s decimal degrees\n" % Y_STEP)
f.write("post_lon: %s decimal degrees\n" % X_STEP)
f.write("\n")
f.write("ellipsoid_name: WGS 84\n")
f.write("ellipsoid_ra: 6378137.000 m\n")
f.write("ellipsoid_reciprocal_flattening: 298.2572236\n")
f.write("\n")
f.write("datum_name: WGS 1984\n")
f.write("datum_shift_dx: 0.000 m\n")
f.write("datum_shift_dy: 0.000 m\n")
f.write("datum_shift_dz: 0.000 m\n")
f.write("datum_scale_m: 0.00000e+00\n")
f.write("datum_rotation_alpha: 0.00000e+00 arc-sec\n")
f.write("datum_rotation_beta: 0.00000e+00 arc-sec\n")
f.write("datum_rotation_gamma: 0.00000e+00 arc-sec\n")
f.write("datum_country_list Global Definition, WGS84, World\n")
f.write("\n")
f.close()
def convert_to_gamma(input_file, output_name, byteorder='big', processor='gamma'):
"""Convert TIF file to Gamma or ROI_PAC format (.dem and .dem.par/.dem.rsc)
Args:
input_file (str): Input TIF file path
output_name (str): Output name (without extension)
byteorder (str): Byte order ('big' or 'little')
processor (str): Processor type ('gamma' or 'roi_pac')
"""
processor_name = 'Gamma' if processor == 'gamma' else 'ROI_PAC'
print(f"\n开始转换到 {processor_name} 格式: {input_file}")
# 读取 DEM 数据 - 优先使用 GDAL(更稳定),然后是 rasterio
dem_data = None
# 方法1: 使用 GDAL(最稳定)
try:
from osgeo import gdal
print(" 尝试使用 GDAL 读取数据...")
ds = gdal.Open(input_file)
if ds is not None:
band = ds.GetRasterBand(1)
dem_data = band.ReadAsArray()
print(f" ✓ 使用 GDAL 读取成功")
ds = None # 关闭文件
except Exception as e:
print(f" ✗ GDAL 读取失败: {e}")
# 方法2: 如果GDAL失败,尝试rasterio
if dem_data is None:
try:
import rasterio
print(" 尝试使用 rasterio 读取数据...")
with rasterio.open(input_file) as src:
dem_data = src.read(1)
print(f" ✓ 使用 rasterio 读取成功")
except Exception as e:
print(f" ✗ rasterio 读取失败: {e}")
# 方法3: 最后尝试skimage
if dem_data is None:
try:
print(" 尝试使用 skimage 读取数据...")
dem_data = io.imread(input_file)
print(f" ✓ 使用 skimage 读取成功")
except Exception as e:
print(f" ✗ skimage 读取失败: {e}")
# 如果所有方法都失败
if dem_data is None:
raise ValueError(f"无法读取DEM文件: {input_file},所有读取方法都失败了")
# 确定数据格式
if dem_data.dtype == 'float32':
DATA_FORMAT = 'REAL*4'
else:
DATA_FORMAT = 'INTEGER*2'
# 字节序转换
if not sys.byteorder == byteorder:
dem_data.byteswap(True)
# 输出文件路径
dem_file = output_name + '.dem'
if processor == 'gamma':
dem_par_file = output_name + '.dem.par'
else:
dem_par_file = output_name + '.dem.rsc'
# 写入二进制 DEM 数据
dem_data.tofile(dem_file)
# 使用 gdalinfo 获取地理信息
info_file = 'temp_gdalinfo.txt'
cmd = f"gdalinfo {input_file} > {info_file}"
os.system(cmd)
# 解析地理信息
Corner_LON = None
Corner_LAT = None
Post_LON = None
Post_LAT = None
WIDTH = None
FILE_LENGTH = None
with open(info_file, 'r') as f:
for line in f:
if 'Origin =' in line:
parts = line.split('Origin =')[1].strip().split('(')[1].split(')')[0].split(',')
Corner_LON = parts[0]
Corner_LAT = parts[1]
elif 'Pixel Size ' in line:
parts = line.split('Pixel Size =')[1].strip().split('(')[1].split(')')[0].split(',')
Post_LON = parts[0]
Post_LAT = parts[1]
elif 'Size is' in line:
parts = line.split('Size is')[1].strip().split(',')
WIDTH = parts[0]
FILE_LENGTH = parts[1]
# 删除临时文件
if os.path.exists(info_file):
os.remove(info_file)
# 写入参数文件
if processor == 'gamma':
write_dempar_file(dem_par_file, Corner_LON, Corner_LAT, Post_LON, Post_LAT, WIDTH, FILE_LENGTH, DATA_FORMAT)
else:
write_demrsc_file(dem_par_file, Corner_LON, Corner_LAT, Post_LON, Post_LAT, WIDTH, FILE_LENGTH)
print(f"{byteorder} endian {dem_file} and {dem_par_file} are generated.")
print(f"{processor_name} 格式转换完成!")
def get_sufix(STR):
"""Get file extension"""
n = len(STR.split('.'))
SUFIX = STR.split('.')[n-1]
return SUFIX
def read_region(STR):
"""Parse region string 'west/east/south/north'"""
WEST = STR.split('/')[0]
EAST = STR.split('/')[1].split('/')[0]
SOUTH = STR.split(EAST+'/')[1].split('/')[0]
NORTH = STR.split(EAST+'/')[1].split('/')[1]
WEST = float(WEST)
SOUTH = float(SOUTH)
EAST = float(EAST)
NORTH = float(NORTH)
return WEST, SOUTH, EAST, NORTH
def cmd_init(lon, lat, save_path):
s_lon = str(abs(lon))
s_lat = str(abs(lat))
if abs(lon) < 10:
s_lon = "00" + str(abs(lon))
elif abs(lon) < 100:
s_lon = "0" + str(abs(lon))
if abs(lat) < 10:
s_lat = "0" + str(abs(lat))
if lon < 0:
c_lon = "W" + str(s_lon)
else:
c_lon = "E" + str(s_lon)
if lat < 0:
c_lat = "S" + str(s_lat)
else:
c_lat = "N" + str(s_lat)
cmd = "aws s3 cp --no-sign-request" + " s3://copernicus-dem-{0}m/Copernicus_DSM_COG_{1}_{2}_00_{3}_00_DEM/ {4} --recursive".format(
str(resolutions), str(int(resolutions / 3)), str(c_lat), str(c_lon), save_path)
return cmd
def get_remote_file(lon, lat, save_path, max_retries=3):
"""Get Copernicus Dem by lon and lat with retry mechanism
Args:
lon (number): lontitude
lat (number): latitude
save_path (str): directory to save data
max_retries (int): maximum retry attempts
"""
lon = int(lon)
lat = int(lat)
cmd = cmd_init(lon, lat, save_path)
for attempt in range(max_retries):
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=300)
if result.returncode == 0:
print(f"✓ Successfully downloaded: lon={lon}, lat={lat}")
return True
else:
if attempt < max_retries - 1:
print(f"✗ Failed (attempt {attempt+1}/{max_retries}): lon={lon}, lat={lat}, retrying...")
import time
time.sleep(2)
else:
print(f"✗ Failed after {max_retries} attempts: lon={lon}, lat={lat}")
return False
except subprocess.TimeoutExpired:
if attempt < max_retries - 1:
print(f"⏱ Timeout (attempt {attempt+1}/{max_retries}): lon={lon}, lat={lat}, retrying...")
import time
time.sleep(2)
else:
print(f"✗ Timeout after {max_retries} attempts: lon={lon}, lat={lat}")
return False
except Exception as e:
print(f"✗ Exception occurred for lon={lon}, lat={lat}: {e}")
return False
return False
def get_remote_file_batch(west, east, south, north, save_path, num_workers=4):
"""Get Copernicus Dems by WESN extent with parallel download
Args:
west (number): western longitude boundary
east (number): eastern longitude boundary
south (number): southern latitude boundary
north (number): northern latitude boundary
save_path (str): directory to save data
num_workers (int): number of parallel download workers (default: 4)
"""
from concurrent.futures import ThreadPoolExecutor, as_completed
from tqdm import tqdm
west = int(west)
east = int(east)
south = int(south)
north = int(north)
# 生成所有需要下载的坐标对
coords = [(lon, lat) for lon in range(west, east + 1) for lat in range(south, north + 1)]
total_tiles = len(coords)
print(f"\n{'='*80}")
print(f"并行下载 Copernicus DEM 数据")
print(f"{'='*80}")
print(f"区域范围: {west}°E - {east}°E, {south}°N - {north}°N")
print(f"总瓦片数: {total_tiles}")
print(f"并行线程: {num_workers}")
print(f"{'='*80}\n")
success_count = 0
failed_count = 0
# 使用线程池并行下载
with ThreadPoolExecutor(max_workers=num_workers) as executor:
# 提交所有下载任务
future_to_coord = {executor.submit(get_remote_file, lon, lat, save_path): (lon, lat)
for lon, lat in coords}
# 使用 tqdm 显示进度条
with tqdm(total=total_tiles, desc="下载进度", unit="瓦片") as pbar:
for future in as_completed(future_to_coord):
coord = future_to_coord[future]
try:
result = future.result()
if result:
success_count += 1
else:
failed_count += 1
except Exception as e:
print(f"\n✗ 下载失败 {coord}: {e}")
failed_count += 1
pbar.update(1)
# 打印统计信息
print(f"\n{'='*80}")
print(f"下载完成统计")
print(f"{'='*80}")
print(f"成功: {success_count}/{total_tiles} 瓦片")
print(f"失败: {failed_count}/{total_tiles} 瓦片")
if failed_count > 0:
print(f"\n⚠️ 有 {failed_count} 个瓦片下载失败,可能会影响 DEM 完整性")
print(f"{'='*80}\n")
def download_nasadem(west, south, east, north, save_path, cell_size_deg=0.000277778):
"""Download NASADEM data using NASADEM library
Args:
west (float): western longitude boundary
south (float): southern latitude boundary
east (float): eastern longitude boundary
north (float): northern latitude boundary
save_path (str): directory to save data
cell_size_deg (float): cell size in degrees (default: 0.000277778 ≈ 30m at equator)
Returns:
str: path to the downloaded DEM file, or None if failed
"""
if not HAS_NASADEM:
print("✗ NASADEM library not available. Cannot download NASADEM.")
print(" Install with: pip install nasadem rasters")
return None
print(f"\n{'='*80}")
print(f"下载 NASADEM 数据")
print(f"{'='*80}")
print(f"区域范围: {west}°E - {east}°E, {south}°N - {north}°N")
print(f"分辨率: {cell_size_deg}° (约 {cell_size_deg * 111000:.0f} 米)")
print(f"{'='*80}\n")
try:
from NASADEM.NASADEM import NASADEMConnection
from rasters import RasterGrid
import time
start_time = time.time()
# 定义目标区域
geometry = RasterGrid.from_bbox(
xmin=west, ymin=south, xmax=east, ymax=north,
cell_size=cell_size_deg,
crs="EPSG:4326"
)
print(f"RasterGrid 维度: {geometry.shape}")
print(f"正在从NASA服务器下载高程数据...")
print(f"提示: 首次下载需要从NASA服务器获取数据,可能需要几分钟时间...")
# 创建NASA DEM连接并获取高程数据
conn = NASADEMConnection()
elevation = conn.elevation_m(geometry)
elapsed_time = time.time() - start_time
print(f"\n✓ 下载完成!")
print(f" 高程范围: {float(elevation.min()):.1f}{float(elevation.max()):.1f} 米")
print(f" 数据维度: {elevation.shape}")
print(f" 用时: {elapsed_time:.1f} 秒")
# 保存为 GeoTIFF
output_file = os.path.join(save_path, f"NASADEM_{west}_{east}_{south}_{north}.tif")
print(f"\n保存到: {output_file}")
# 检查elevation对象是否有save方法
if hasattr(elevation, 'save'):
elevation.save(output_file)
print(f"✓ 文件保存成功: {output_file}")
if os.path.exists(output_file):
file_size = os.path.getsize(output_file) / (1024 * 1024)
print(f" 文件大小: {file_size:.2f} MB")
return output_file
# 否则使用 rasterio 保存
try:
import rasterio
from rasterio.crs import CRS
from rasterio.transform import from_bounds
# 获取数据数组
if hasattr(elevation, 'read'):
elev_array = elevation.read()
else:
elev_array = np.array(elevation)
# 计算变换矩阵
height, width = elev_array.shape
transform = from_bounds(west, south, east, north, width, height)
# 写入文件
with rasterio.open(
output_file,
'w',
driver='GTiff',
height=height,
width=width,
count=1,
dtype=elev_array.dtype,
crs=CRS.from_epsg(4326),
transform=transform,
nodata=-32767,
compress='LZW'
) as dst:
dst.write(elev_array, 1)
print(f"✓ 文件保存成功: {output_file}")
if os.path.exists(output_file):
file_size = os.path.getsize(output_file) / (1024 * 1024)
print(f" 文件大小: {file_size:.2f} MB")
return output_file
except ImportError:
print("⚠️ rasterio 未安装,尝试使用 GDAL...")
# 使用 GDAL 创建 GeoTIFF
width, height = geometry.width, geometry.height
gdal_cmd = f"gdal_create -outsize {width} {height} -of GTiff -co COMPRESS=LZW -a_srs EPSG:4326 -a_ullr {west} {north} {east} {south} {output_file}"
result = os.system(gdal_cmd)
if result == 0 and os.path.exists(output_file):
print(f"✓ 文件创建成功: {output_file}")
return output_file
else:
print(f"✗ 文件创建失败")
return None
except Exception as e:
print(f"\n✗ 下载失败: {e}")
import traceback
traceback.print_exc()
return None
def download_srtm(west, south, east, north, save_path, srtm_data_dir=None, cell_size=0.000277778):
"""Download SRTM data using srtm library (requires pre-downloaded .hgt files)
Args:
west (float): western longitude boundary
south (float): southern latitude boundary
east (float): eastern longitude boundary
north (float): northern latitude boundary
save_path (str): directory to save output DEM
srtm_data_dir (str): directory containing SRTM .hgt files (required)
cell_size (float): cell size in degrees (default: 0.000277778 ≈ 30m)
Returns:
str: path to the generated DEM file, or None if failed
Note:
This function requires SRTM .hgt files to be pre-downloaded.
You can download SRTM data from:
- https://srtm.csi.cgiar.org/
- https://earthexplorer.usgs.gov/
Python version requirement:
- srtm library requires Python >= 3.12
- For Python < 3.12, use process_srtm_hgt_files() instead
"""
if not HAS_SRTM:
print("✗ srtm library not available. Cannot use SRTM.")
print(" Install with: pip install srtm (requires Python >= 3.12)")
print(f" Current Python version: {sys.version_info.major}.{sys.version_info.minor}")
print(" Alternative: Use process_srtm_hgt_files() to manually process .hgt files")
return None
if srtm_data_dir is None or not os.path.isdir(srtm_data_dir):
print("✗ SRTM data directory not provided or does not exist.")
print(" Please download SRTM .hgt files and specify the directory.")
print(" Download sources:")
print(" - https://srtm.csi.cgiar.org/")
print(" - https://earthexplorer.usgs.gov/")
return None
print(f"\n{'='*80}")
print(f"使用 SRTM 数据生成 DEM")
print(f"{'='*80}")
print(f"区域范围: {west}°E - {east}°E, {south}°N - {north}°N")
print(f"SRTM数据目录: {srtm_data_dir}")
print(f"分辨率: {cell_size}° (约 {cell_size * 111000:.0f} 米)")
print(f"{'='*80}\n")
try:
import time
from tqdm import tqdm
start_time = time.time()
# 创建 SrtmService
service = srtm.SrtmService(srtm_data_dir, cache_size=100)
print(f"✓ SrtmService 创建成功")
# 生成坐标网格
lats = np.arange(south, north + cell_size, cell_size)
lons = np.arange(west, east + cell_size, cell_size)
print(f"生成网格: {len(lats)} × {len(lons)} = {len(lats) * len(lons)} 个点")
# 批量查询高程
coords = [(lat, lon) for lat in lats for lon in lons]
print(f"正在查询高程数据...")
elevations = service.get_elevations_batch(coords, default=0)
# 重塑为数组
elevation_array = np.array(elevations, dtype=np.float32).reshape(len(lats), len(lons))
# 替换0值为NaN(可能是缺失数据)
elevation_array[elevation_array == 0] = np.nan
elapsed_time = time.time() - start_time
print(f"\n✓ 查询完成!")
print(f" 有效数据: {np.sum(~np.isnan(elevation_array))} / {elevation_array.size} 点")
if np.sum(~np.isnan(elevation_array)) > 0:
print(f" 高程范围: {np.nanmin(elevation_array):.1f}{np.nanmax(elevation_array):.1f} 米")
print(f" 用时: {elapsed_time:.1f} 秒")
# 保存为 GeoTIFF
output_file = os.path.join(save_path, f"SRTM_{west}_{east}_{south}_{north}.tif")
print(f"\n保存到: {output_file}")
try:
import rasterio
from rasterio.crs import CRS
from rasterio.transform import from_bounds
height, width = elevation_array.shape
transform = from_bounds(west, south, east, north, width, height)
# 替换NaN为nodata值
elevation_array[np.isnan(elevation_array)] = -32767
with rasterio.open(
output_file,
'w',
driver='GTiff',
height=height,
width=width,
count=1,
dtype=np.float32,
crs=CRS.from_epsg(4326),
transform=transform,
nodata=-32767,
compress='LZW'
) as dst:
dst.write(elevation_array.astype(np.float32), 1)
print(f"✓ 文件保存成功: {output_file}")
if os.path.exists(output_file):
file_size = os.path.getsize(output_file) / (1024 * 1024)
print(f" 文件大小: {file_size:.2f} MB")
return output_file
except ImportError:
print("⚠️ rasterio 未安装,无法保存文件")
return None
except Exception as e:
print(f"\n✗ 生成失败: {e}")
import traceback
traceback.print_exc()
return None
def split_large_region(west, south, east, north, tile_size=1.0):
"""将大区域分割成小块
Args:
west, south, east, north: 区域边界
tile_size: 分块大小(度),默认1°×1°
Returns:
list: 分块列表 [(west, south, east, north), ...]
"""
tiles = []
w = west
while w < east:
e = min(w + tile_size, east)
s = south
while s < north:
n = min(s + tile_size, north)
tiles.append((w, s, e, n))
s += tile_size
w += tile_size
return tiles
def download_srtm_cgiar(west, south, east, north, save_path, api_key=None, num_workers=4, dem_type='SRTMGL1', auto_tile=True):
"""Download DEM data from OpenTopography automatically
Args:
west (float): western longitude boundary
south (float): southern latitude boundary
east (float): eastern longitude boundary
north (float): northern latitude boundary
save_path (str): directory to save output DEM
api_key (str): OpenTopography API key (optional, will prompt if not provided)
num_workers (int): number of parallel downloads (not used for API, kept for compatibility)
dem_type (str): DEM type (default: 'SRTMGL1')
- SRTMGL1: SRTM GL1 30m (recommended for SRTM)
- SRTMGL3: SRTM GL3 90m
- NASADEM: NASADEM 30m
- COP30: Copernicus 30m
- COP90: Copernicus 90m
auto_tile (bool): 自动分块下载大区域
Returns:
str: path to the generated DEM file, or None if failed
Note:
OpenTopography API provides:
- SRTMGL1: SRTM GL1 30m (recommended)
- SRTMGL3: SRTM GL3 90m
- NASADEM: NASADEM Global DEM 30m
- COP30: Copernicus 30m
- COP90: Copernicus 90m
API Documentation: https://portal.opentopography.org/apidocs/
Get API key: https://opentopography.org/myOpenTopo
"""
# DEM类型信息
dem_info = {
'SRTMGL1': {'resolution': '30m', 'name': 'SRTM GL1'},
'SRTMGL3': {'resolution': '90m', 'name': 'SRTM GL3'},
'NASADEM': {'resolution': '30m', 'name': 'NASADEM'},
'COP30': {'resolution': '30m', 'name': 'Copernicus 30m'},
'COP90': {'resolution': '90m', 'name': 'Copernicus 90m'}
}
info = dem_info.get(dem_type, {'resolution': 'unknown', 'name': dem_type})
print(f"\n{'='*80}")
print(f"从 OpenTopography 自动下载 DEM 数据")
print(f"{'='*80}")
print(f"区域范围: {west}°E - {east}°E, {south}°N - {north}°N")
print(f"数据源: {info['name']} ({info['resolution']} resolution)")
print(f"{'='*80}\n")
# 计算区域面积
region_area = (east - west) * (north - south)
# 如果区域较大,自动分块
if auto_tile and region_area > 4:
print(f"⚠️ 区域较大 ({region_area:.1f} 平方度),将自动分块下载以提高稳定性")
# 计算分块
tiles = split_large_region(west, south, east, north, tile_size=1.0)
print(f" 将分成 {len(tiles)} 个 1°×1° 的区块下载\n")
# 创建临时目录存放分块文件
temp_dir = os.path.join(save_path, f"temp_tiles_{dem_type}_{west}_{east}_{south}_{north}")
if not os.path.exists(temp_dir):
os.makedirs(temp_dir)
# 下载每个分块
downloaded_files = []
failed_tiles = []
for i, (w, s, e, n) in enumerate(tiles, 1):
print(f"\n{'='*80}")
print(f"下载分块 {i}/{len(tiles)}: {w}°E-{e}°E, {s}°N-{n}°N")
print(f"{'='*80}")
tile_file = download_single_tile(w, s, e, n, temp_dir, api_key, dem_type, info)
if tile_file:
downloaded_files.append(tile_file)
print(f"✓ 分块 {i}/{len(tiles)} 下载成功")
else:
failed_tiles.append((w, s, e, n))
print(f"✗ 分块 {i}/{len(tiles)} 下载失败")
# 如果有失败的分块
if failed_tiles:
print(f"\n⚠️ 有 {len(failed_tiles)} 个分块下载失败")
print("失败的分块:")
for w, s, e, n in failed_tiles:
print(f" {w}°E-{e}°E, {s}°N-{n}°N")
# 合并所有分块
if downloaded_files:
print(f"\n{'='*80}")
print(f"合并 {len(downloaded_files)} 个分块...")
print(f"{'='*80}\n")
merged_file = merge_dem_tiles(downloaded_files, save_path, dem_type, west, east, south, north)
# 清理临时文件
import shutil
try:
shutil.rmtree(temp_dir)
print("✓ 临时文件已清理")
except:
pass
if merged_file:
print(f"\n✓ 最终输出文件: {merged_file}")
return merged_file
else:
print("✗ 合并失败")
return None
else:
print("✗ 所有分块下载失败")
return None
# 小区域直接下载
else:
return download_single_tile(west, south, east, north, save_path, api_key, dem_type, info)
def download_single_tile(west, south, east, north, save_path, api_key, dem_type, dem_info):
"""下载单个DEM块
Args:
west, south, east, north: 区域边界
save_path: 保存路径
api_key: OpenTopography API key
dem_type: DEM类型
dem_info: DEM信息字典
Returns:
str: 下载的文件路径,失败返回None
"""
try:
import time
import urllib.request
import urllib.parse
start_time = time.time()
# OpenTopography API endpoint
base_url = "https://portal.opentopography.org/API/globaldem"
# 如果没有提供API key,提示用户获取
if api_key is None:
print("⚠️ 需要OpenTopography API key才能下载SRTM数据")
print("\n获取免费API key的步骤:")
print(" 1. 访问: https://opentopography.org/myOpenTopo")
print(" 2. 注册免费账户")
print(" 3. 在 'My Account' 页面请求API key")
print(" 4. 使用 --opentopo-api-key 参数提供API key")
print("\n或者使用其他DEM数据源:")
print(" - Copernicus (推荐): --dem-source copernicus")
print(" - NASADEM: --dem-source nasadem")
return None
# 构建请求参数
params = {
'demtype': dem_type,
'south': south,
'north': north,
'west': west,
'east': east,
'outputFormat': 'GTiff',
'API_Key': api_key
}
# 构建完整URL
url = base_url + '?' + urllib.parse.urlencode(params)
# 输出文件名
output_file = os.path.join(save_path, f"{dem_type}_{west}_{east}_{south}_{north}.tif")
# 下载文件 - 使用curl以获得更好的稳定性
max_retries = 3
retry_count = 0
download_success = False
while retry_count < max_retries and not download_success:
try:
retry_count += 1
print(f"正在从OpenTopography下载数据... (尝试 {retry_count}/{max_retries})")
# 尝试使用 curl 下载(更稳定)
try:
import subprocess
curl_cmd = ['curl', '-L', '-o', output_file, '-s', '--show-error', url]
result = subprocess.run(curl_cmd, capture_output=True, text=True, timeout=1800) # 30分钟超时
if result.returncode != 0:
raise Exception(f"curl下载失败: {result.stderr}")
print(" ✓ curl下载完成")
download_success = True
except (subprocess.TimeoutExpired, FileNotFoundError):
# 如果curl不可用或超时,使用urllib
print(" 使用urllib下载...")
urllib.request.urlretrieve(url, output_file)
download_success = True
except urllib.error.HTTPError as e:
print(f"\n✗ HTTP错误: {e.code} {e.reason}")
if e.code == 401:
print(" API key无效或已过期")
print(" 请获取新的API key: https://opentopography.org/myOpenTopo")
elif e.code == 403:
print(" 访问被拒绝,可能是:")
print(" - 请求区域过大")
print(" - API key配额已用完")
print(" - 需要注册获取免费API key")
if retry_count < max_retries:
print(f" 将在3秒后重试...")
time.sleep(3)
continue
return None
except Exception as e:
print(f"\n✗ 下载失败: {e}")
if retry_count < max_retries:
print(f" 将在3秒后重试...")
time.sleep(3)
continue
return None
# 检查文件是否有效
if os.path.exists(output_file):
file_size = os.path.getsize(output_file)
# 如果文件很小,可能是错误消息
if file_size < 1000:
with open(output_file, 'r') as f:
error_msg = f.read()
print(f"\n✗ 下载失败: {error_msg}")
os.remove(output_file)
return None
elapsed_time = time.time() - start_time
print(f"\n✓ 下载完成!")
print(f" 输出文件: {output_file}")
print(f" 文件大小: {file_size / (1024 * 1024):.2f} MB")
print(f" 用时: {elapsed_time:.1f} 秒")
# 验证文件完整性
print("\n验证文件完整性...")
try:
import rasterio
with rasterio.open(output_file) as src:
# 尝试读取多个位置的数据验证
print(f" 文件大小: {src.width} x {src.height} 像素")
# 读取多个测试点
test_points = [
(0, 0, min(100, src.height), min(100, src.width)), # 左上角
(max(0, src.height-100), max(0, src.width-100), src.height, src.width), # 右下角
(src.height//2-50, src.width//2-50, src.height//2+50, src.width//2+50), # 中间
]
for i, (row_start, col_start, row_end, col_end) in enumerate(test_points):
try:
window = ((row_start, row_end), (col_start, col_end))
test_data = src.read(1, window=window)
print(f" ✓ 测试点 {i+1}/3 验证成功")
except Exception as e:
print(f" ✗ 测试点 {i+1}/3 验证失败: {e}")
raise
print(f" ✓ 所有验证点通过,文件完整")
return output_file
except Exception as e:
print(f" ✗ 文件验证失败: {e}")
print(f" 文件可能已损坏,正在删除...")
try:
os.remove(output_file)
except:
pass
return None
else:
print("✗ 文件下载失败")
return None
except Exception as e:
print(f"\n✗ 下载失败: {e}")
import traceback
traceback.print_exc()
return None
def merge_dem_tiles(tile_files, save_path, dem_type, west, east, south, north):
"""合并多个DEM分块文件
Args:
tile_files: 分块文件列表
save_path: 保存路径
dem_type: DEM类型
west, east, south, north: 最终区域边界
Returns:
str: 合并后的文件路径,失败返回None
"""
if not tile_files:
print("✗ 没有文件需要合并")
return None
try:
import rasterio
from rasterio.merge import merge
import time
print(f"开始合并 {len(tile_files)} 个分块文件...")
# 读取所有分块
src_files_to_mosaic = []
for tile_file in tile_files:
src = rasterio.open(tile_file)
src_files_to_mosaic.append(src)
# 合并
start_time = time.time()
mosaic, out_trans = merge(src_files_to_mosaic)
# 获取输出元数据
out_meta = src_files_to_mosaic[0].meta.copy()
out_meta.update({
"driver": "GTiff",
"height": mosaic.shape[1],
"width": mosaic.shape[2],
"transform": out_trans,
"compress": "lzw"
})
# 输出文件名
output_file = os.path.join(save_path, f"{dem_type}_{west}_{east}_{south}_{north}.tif")
# 写入合并后的文件
with rasterio.open(output_file, "w", **out_meta) as dest:
dest.write(mosaic)
# 关闭所有源文件
for src in src_files_to_mosaic:
src.close()
elapsed_time = time.time() - start_time
file_size = os.path.getsize(output_file) / (1024 * 1024)
print(f"✓ 合并完成!")
print(f" 输出文件: {output_file}")
print(f" 文件大小: {file_size:.2f} MB")
print(f" 用时: {elapsed_time:.1f} 秒")
return output_file
except ImportError:
print("✗ rasterio 未安装,无法合并文件")
print(" 安装方法: pip install rasterio")
return None
except Exception as e:
print(f"✗ 合并失败: {e}")
import traceback
traceback.print_exc()
return None
def download_srtm_cgiar_old(west, south, east, north, save_path, num_workers=4):
"""Download SRTM data from CSI-CGIAR (DEPRECATED - tiles not accessible)
This function is kept as backup but CSI-CGIAR tile downloads are not reliable.
Use download_srtm_cgiar() with OpenTopography API instead.
"""
print("警告: CSI-CGIAR瓦片下载不可靠,建议使用OpenTopography API")
return None
def process_srtm_hgt_files(west, south, east, north, srtm_data_dir, save_path, output_name=None):
"""Process SRTM .hgt files manually (alternative for Python < 3.12)
Args:
west (float): western longitude boundary
south (float): southern latitude boundary
east (float): eastern longitude boundary
north (float): northern latitude boundary
srtm_data_dir (str): directory containing SRTM .hgt files
save_path (str): directory to save output DEM
output_name (str): output filename (without extension)
Returns:
str: path to the generated DEM file, or None if failed
Note:
SRTM .hgt files are 1°×1° tiles with 1201×1201 pixels (3 arc-second) or
3601×3601 pixels (1 arc-second). This function reads and merges them.
"""
print(f"\n{'='*80}")
print(f"手动处理 SRTM .hgt 文件")
print(f"{'='*80}")
print(f"区域范围: {west}°E - {east}°E, {south}°N - {north}°N")
print(f"SRTM数据目录: {srtm_data_dir}")
print(f"{'='*80}\n")
try:
import rasterio
from rasterio.merge import merge
from rasterio.crs import CRS
import time
start_time = time.time()
# 查找需要的SRTM文件
hgt_files = []
for lat in range(int(south), int(north) + 1):
for lon in range(int(west), int(east) + 1):
# 构造文件名
lat_prefix = 'N' if lat >= 0 else 'S'
lon_prefix = 'E' if lon >= 0 else 'W'
# SRTM文件名格式: N39E116.hgt
filename = f"{lat_prefix}{abs(lat):02d}{lon_prefix}{abs(lon):03d}.hgt"
filepath = os.path.join(srtm_data_dir, filename)
if os.path.exists(filepath):
hgt_files.append(filepath)
print(f" ✓ 找到文件: {filename}")
else:
print(f" ⚠ 文件缺失: {filename}")
if not hgt_files:
print("\n✗ 没有找到任何SRTM文件!")
return None
print(f"\n找到 {len(hgt_files)} 个SRTM文件")
# 使用GDAL合并.hgt文件
merged_file = os.path.join(save_path, f"SRTM_merged_{west}_{east}_{south}_{north}.tif")
# 构建gdal_merge命令
gdal_merge_cmd = ['gdal_merge.py', '-o', merged_file, '-of', 'GTiff', '-co', 'COMPRESS=LZW']
gdal_merge_cmd.extend(hgt_files)
print(f"\n使用GDAL合并文件...")
result = subprocess.run(gdal_merge_cmd, capture_output=True, text=True)
if result.returncode != 0 or not os.path.exists(merged_file):
print(f"✗ GDAL合并失败: {result.stderr}")
return None
print(f"✓ 合并完成: {merged_file}")
# 裁剪到目标范围
if output_name is None:
output_name = os.path.join(save_path, f"SRTM_{west}_{east}_{south}_{north}")
output_file = output_name + '.tif'
gdal_warp_cmd = [
'gdalwarp',
'-te', str(west), str(south), str(east), str(north),
'-of', 'GTiff',
'-co', 'COMPRESS=LZW',
merged_file,
output_file
]
print(f"\n裁剪到目标范围...")
result = subprocess.run(gdal_warp_cmd, capture_output=True, text=True)
if result.returncode != 0 or not os.path.exists(output_file):
print(f"✗ GDAL裁剪失败: {result.stderr}")
return None
elapsed_time = time.time() - start_time
print(f"\n✓ SRTM DEM 生成完成!")
print(f" 输出文件: {output_file}")
if os.path.exists(output_file):
file_size = os.path.getsize(output_file) / (1024 * 1024)
print(f" 文件大小: {file_size:.2f} MB")
print(f" 用时: {elapsed_time:.1f} 秒")
# 清理临时文件
if os.path.exists(merged_file) and merged_file != output_file:
os.remove(merged_file)
print(f" 清理临时文件: {merged_file}")
return output_file
except ImportError:
print("✗ rasterio 未安装,无法处理文件")
return None
except Exception as e:
print(f"\n✗ 处理失败: {e}")
import traceback
traceback.print_exc()
return None
def merge_tif_files(input_pattern, output_file):
"""合并多个 TIF 文件为一个文件
Args:
input_pattern (str): 输入 TIF 文件的匹配模式
output_file (str): 输出合并后的 TIF 文件路径
"""
# 查找所有匹配的 TIF 文件
tif_files = sorted(glob.glob(input_pattern))
if not tif_files:
print(f"未找到匹配的 TIF 文件: {input_pattern}")
return False
print(f"\n{'='*80}")
print(f"合并 DEM 瓦片")
print(f"{'='*80}")
print(f"找到 {len(tif_files)} 个 TIF 文件待合并")
print(f"输出文件: {output_file}")
print(f"{'='*80}\n")
# 使用 gdal_merge.py 合并文件
try:
start_time = __import__('time').time()
cmd = ["gdal_merge.py", "-o", output_file, "-co", "COMPRESS=LZW", "-co", "BIGTIFF=YES"] + tif_files
print(f"执行合并命令...")
# 使用 tqdm 显示进度
result = subprocess.run(cmd, capture_output=True, text=True)
elapsed_time = __import__('time').time() - start_time
if result.returncode == 0:
# 检查输出文件大小
if os.path.exists(output_file):
file_size = os.path.getsize(output_file) / (1024 * 1024) # MB
print(f"\n✓ 成功合并文件!")
print(f" 输出文件: {output_file}")
print(f" 文件大小: {file_size:.2f} MB")
print(f" 用时: {elapsed_time:.1f} 秒")
print(f"{'='*80}\n")
return True
else:
print(f"\n✗ 合并失败: {result.stderr}")
print(f"{'='*80}\n")
return False
except Exception as e:
print(f"\n✗ 合并过程中发生错误: {e}")
print(f"{'='*80}\n")
return False
def convert_format(input_file, output_file, format_type="GTiff", options=None):
"""转换 TIF 文件格式
Args:
input_file (str): 输入文件路径
output_file (str): 输出文件路径
format_type (str): 输出格式类型 (默认: GTiff)
options (list): gdal_translate 的额外选项
"""
if options is None:
options = []
try:
cmd = ["gdal_translate", "-of", format_type] + options + [input_file, output_file]
print(f"执行转换命令: {' '.join(cmd)}")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
print(f"成功转换文件到: {output_file}")
return True
else:
print(f"转换失败: {result.stderr}")
return False
except Exception as e:
print(f"转换过程中发生错误: {e}")
return False
def process_dem_files(save_path, west, east, south, north, merge=True, convert=True,
output_format="GTiff", convert_options=None, gamma=False, gamma_byteorder='big',
processor='gamma', output_name=None, num_workers=4,
srtm_data_dir=None, opentopo_api_key=None, opentopo_dem_type='SRTMGL1',
fabdem_dir=None):
"""处理下载的 DEM 文件:下载、合并和转换
Args:
save_path (str): 数据保存目录
west (float): 西经边界
east (float): 东经边界
south (float): 南纬边界
north (float): 北纬边界
merge (bool): 是否合并文件
convert (bool): 是否转换格式
output_format (str): 输出格式
convert_options (list): 转换选项
gamma (bool): 是否转换为 Gamma/ROI_PAC 格式
gamma_byteorder (str): 字节序 ('big' 或 'little')
processor (str): 处理器类型 ('gamma' 或 'roi_pac')
output_name (str): 输出文件名(不含扩展名)
num_workers (int): 并行下载线程数 (default: 4)
dem_source (str): DEM数据源 ('copernicus', 'nasadem' 或 'srtm', default: 'copernicus')
srtm_data_dir (str): SRTM数据目录 (仅srtm源需要)
"""
if convert_options is None:
convert_options = ["-co", "COMPRESS=LZW", "-co", "TILED=YES"]
# ============ 优先尝试本地 FABDEM 瓦片库 ============
if fabdem_dir and os.path.isdir(fabdem_dir):
print(f"\n{'='*80}")
print(f"优先使用本地 FABDEM 瓦片库: {fabdem_dir}")
print(f"{'='*80}")
try:
from make_local_dem import (find_needed_tiles, extract_tiles_from_zips,
tiles_to_gamma_dem)
import tempfile, shutil
tiles = find_needed_tiles(west, south, east, north)
print(f"需要 {len(tiles)} 个 1°×1° FABDEM 瓦片")
temp_dir = tempfile.mkdtemp(prefix='fabdem_tiles_')
try:
tif_files = extract_tiles_from_zips(tiles, fabdem_dir, temp_dir)
if tif_files:
# 一步完成: VRT → ENVI 二进制 → .dem(仅一次大文件写入)
out_name = output_name if output_name else os.path.join(save_path, 'out')
dem_file, dem_par_file = tiles_to_gamma_dem(
tif_files, out_name, west, south, east, north, gamma_byteorder)
if dem_file and dem_par_file:
print(f"\n✓ 本地 FABDEM 生成 GAMMA DEM 成功!")
print(f" DEM: {dem_file}")
print(f" PAR: {dem_par_file}")
shutil.rmtree(temp_dir, ignore_errors=True)
return
else:
print("⚠ 本地 FABDEM 转换失败,回退到网络下载")
else:
print("⚠ 未从本地 FABDEM 提取到瓦片,回退到网络下载")
finally:
shutil.rmtree(temp_dir, ignore_errors=True)
except ImportError as e:
print(f"⚠ 无法导入 make_local_dem 模块 ({e}),回退到网络下载")
except Exception as e:
print(f"⚠ 本地 FABDEM 处理异常 ({e}),回退到网络下载")
# ============ 回退: 网络下载 ============
# 检查是否使用预下载的SRTM数据
if srtm_data_dir and os.path.isdir(srtm_data_dir):
print(f"\n{'='*80}")
print(f"使用预下载的 SRTM 数据")
print(f"{'='*80}")
if HAS_SRTM:
# Python >= 3.12, 使用srtm库
dem_file = download_srtm(west, south, east, north, save_path, srtm_data_dir)
else:
# Python < 3.12, 使用手动处理方法
print("注意: srtm库需要Python >= 3.12,使用手动处理方法")
dem_file = process_srtm_hgt_files(west, south, east, north, srtm_data_dir,
save_path, output_name)
else:
# 自动从OpenTopography下载
print(f"\n{'='*80}")
print(f"开始下载 DEM 数据...")
print(f"{'='*80}")
print("自动从OpenTopography下载DEM数据")
dem_file = download_srtm_cgiar(west, south, east, north, save_path,
api_key=opentopo_api_key, num_workers=num_workers,
dem_type=opentopo_dem_type)
if dem_file is None:
print("✗ DEM 生成失败,退出")
return
current_file = dem_file
# 生成输出文件名
if output_name is None:
output_name = os.path.join(save_path, f"DEM_W{int(west)}_E{int(east)}_S{int(south)}_N{int(north)}")
# 转换到 Gamma/ROI_PAC 格式
if gamma:
print("\n开始转换到 {} 格式...".format(processor.upper()))
convert_to_gamma(current_file, output_name, gamma_byteorder, processor)
# 转换到其他格式(非 Gamma/ROI_PAC
if not gamma and convert:
print("\n开始转换文件格式...")
converted_file = os.path.join(save_path, f"final_DEM_W{int(west)}_E{int(east)}_S{int(south)}_N{int(north)}.tif")
convert_format(current_file, converted_file, output_format, convert_options)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='Download DEM data from OpenTopography and convert to Gamma/ROI_PAC format.',
formatter_class=argparse.RawTextHelpFormatter
)
# 与 makedem.py 相同的参数
parser.add_argument('-r', dest='region', help='Research region, west/east/south/north (e.g., 106/110/36/40)')
parser.add_argument('-d', dest='dem', help='Raw dem file that used for further processing')
parser.add_argument('-s', dest='par', help='SLC parameter file of SAR image used for determining research region')
parser.add_argument('-p', dest='processor', help='Interferometry processor. [ gamma or roi_pac ] [default: gamma]')
parser.add_argument('-o', dest='out', help='Output name of the generated DEM')
parser.add_argument('--byteorder', dest='byteorder', choices=['big', 'little'],
help='Byteorder of the generated DEM: big or little. [default: big for gamma and little for roi_pac]')
parser.add_argument('--dir', dest='PATH', help='Processing directory for generating DEM. [default: Current directory]')
parser.add_argument('--num-workers', dest='num_workers', type=int, default=4,
help='Number of parallel download workers (used for batch processing). [default: 4]')
parser.add_argument('--srtm-data-dir', dest='srtm_data_dir', default=None,
help='Directory containing SRTM .hgt files (optional).\n'
'If not provided, DEM data will be automatically downloaded from OpenTopography.\n'
'Download SRTM data from: https://srtm.csi.cgiar.org/')
parser.add_argument('--opentopo-api-key', dest='opentopo_api_key',
default='09ad77d34545607fdf5cb182b64ac64e',
help='OpenTopography API key for downloading DEM data.\n'
'Get a free API key at: https://opentopography.org/myOpenTopo\n'
'Default key is provided, but you can use your own key.')
parser.add_argument('--opentopo-dem-type', dest='opentopo_dem_type',
choices=['SRTMGL1', 'SRTMGL3', 'NASADEM', 'COP30', 'COP90'],
default='SRTMGL1',
help='DEM type for OpenTopography download. [default: SRTMGL1]\n'
' - SRTMGL1: SRTM GL1 30m (recommended)\n'
' - SRTMGL3: SRTM GL3 90m\n'
' - NASADEM: NASADEM 30m\n'
' - COP30: Copernicus 30m\n'
' - COP90: Copernicus 90m')
parser.add_argument('--fabdem-dir', dest='fabdem_dir', default=None,
help='Directory containing local FABDEM ZIP tiles (e.g., /mnt/ZYD/全球FABDEM).\n'
'If provided, local FABDEM tiles will be used FIRST before network download.\n'
'Falls back to OpenTopography download if local tiles are unavailable.')
args = parser.parse_args()
# 确定工作目录
if args.PATH:
workdir = args.PATH
else:
workdir = os.getcwd()
os.chdir(workdir)
# 确定处理器类型
if args.processor:
processor = args.processor
else:
processor = 'gamma'
# 确定字节序
if args.byteorder:
Byteorder = args.byteorder
else:
if processor == 'gamma':
Byteorder = 'big'
else:
Byteorder = 'little'
# 确定输出名称
if args.out:
Name = args.out
else:
Name = "out"
# 处理已有 DEM 文件的情况
if args.dem:
dem = args.dem
print('Raw dem file is provided: %s.' % dem)
# 转换为 TIF 格式(如果不是 TIF)
SUFIX = get_sufix(dem)
if SUFIX != 'tif':
DTIF = dem.replace('.' + SUFIX, '.tif')
call_str = f'gdal_translate {dem} -of GTiff {DTIF}'
os.system(call_str)
DEM = DTIF
else:
DEM = dem
# 转换到 Gamma/ROI_PAC 格式
convert_to_gamma(DEM, Name, Byteorder, processor)
BB = Byteorder + ' endian'
print('')
print('%s %s and %s are generated.' % (BB, Name + '.dem', Name + ('.dem.par' if processor == 'gamma' else '.dem.rsc')))
print('Congratulations! Done!')
sys.exit(0)
# 处理从 SLC 参数文件确定区域的情况
if args.par:
Par = args.par
print("SLC_par file is provided: %s" % Par)
print("DEM over research region will be downloaded automatically based on %s" % Par)
print("DEM data will be downloaded from OpenTopography")
call_str = "SLC_corners " + Par + " > corners.txt"
os.system(call_str)
File = open("corners.txt", "r")
InfoLine = File.readlines()[8:10]
File.close()
MinLat = float(InfoLine[0].split(':')[1].split(' max. ')[0])
MaxLat = float(InfoLine[0].split(':')[2])
MinLon = float(InfoLine[1].split(':')[1].split(' max. ')[0])
MaxLon = float(InfoLine[1].split(':')[2])
north = int(MaxLat) + 2
south = int(MinLat)
east = int(MaxLon) + 2
west = int(MinLon)
elif args.region:
region = args.region
west, south, east, north = read_region(region)
else:
parser.print_usage()
sys.exit(os.path.basename(sys.argv[0]) + ': error: research region, raw_demfile and SLC parameter file, at least one is needed.')
print('Research region: %s(west) %s(south) %s(east) %s(north)' % (west, south, east, north))
print('>>> Ready to download DEM over research region.')
# 处理数据(下载、合并和转换到 Gamma/ROI_PAC 格式)
process_dem_files(
save_path=workdir,
west=west,
east=east,
south=south,
north=north,
merge=True,
convert=False,
gamma=True,
gamma_byteorder=Byteorder,
processor=processor,
output_name=os.path.join(workdir, Name),
num_workers=args.num_workers,
srtm_data_dir=args.srtm_data_dir,
opentopo_api_key=args.opentopo_api_key,
opentopo_dem_type=args.opentopo_dem_type,
fabdem_dir=args.fabdem_dir
)