ASF HyP3 Python接口使用教程

  • 1. HyP3简介
  • 2. 安装HyP3 SDK
  • 3. 使用HyP3 SDK
  • 3.1. 导入hyp3_sdk 包
  • 3.2. 登录授权
  • 3.3. 提交Jobs
  • (1) 提交Sentinel-1 RTC jobs
  • (2)提交Sentinel-1 InSAR jobs
  • (3)提交autoRIFT jobs
  • 3.4 监控 jobs处理进度
  • 3.4 下载文件


1. HyP3简介

ASF(Alaska Satellite Facility) HyP3(音同 hype [haɪp], Hybrid Pluggable Processing Pipeline)是一项用于处理合成孔径雷达(SAR)影像的服务,可解决SAR数据用户的许多常见问题:

  • 大多数SAR数据集需要一些处理来消除畸变,然后才能进行分析
  • SAR处理是计算密集型的
  • SAR处理软件使用起来十分复杂,或过于昂贵
  • 处理SAR数据有一个陡峭的学习曲线,存在入门障碍

HyP3通过提供一项免费服务来解决这些问题,人们可以根据需要请求SAR处理。HyP3不要求用户在入门前具备大量的SAR处理知识;用户只需提交输入数据,并根据需要设置一些可选参数。

HyP3服务目前仅适用于Sentinel-1数据集,有三种请求HyP3处理产品的方法。

Web访问

ASF的数据搜索Vertex门户提供了一个丰富的界面,来探索Sentinel-1采集并查找图像以提交需求进行处理。它还提供了为InSAR分析选择对和叠加的工具。

  • Vertex:https://hyp3-docs.asf.alaska.edu/using/vertex/

程序访问

请求和下载产品也可以通过编程来完成:

  • HyP3 SDK for Python:https://hyp3-docs.asf.alaska.edu/using/sdk/ ,Python接口
  • HyP3 REST API: https://hyp3-docs.asf.alaska.edu/using/api/ , 通过此API,任意编程语言都可以进行操作。

本教程只展示使用 Python 操作 HyP3。

2. 安装HyP3 SDK

HyP3 SDK可以通过conda进行安装:

conda install -c conda-forge hyp3_sdk -y

或者通过pip进行安装

python -m pip install hyp3_sdk

3. 使用HyP3 SDK

HyP3 SDK 有3个主要的 python 类(class):

  • HyP3: 执行HyP3操作(查找作业、刷新作业信息、提交新作业)
  • Job: 对单个作业执行操作(下载产品、检查状态)
  • Batch: 一次对多个作业执行操作(下载产品、检查状态)

3.1. 导入hyp3_sdk 包

import hyp3_sdk as sdk

3.2. 登录授权

hyp3_sdk 提供了三种授权方式:

  • 读取.netrc文件的登录信息
  • 直接传递登录信息到class参数
  • 运行时终端输入登录信息

下面将分别详细介绍这三种授权方式。

(1)通过.netrc授权

如果代码中未指定登录信息,程序会自动读取~/.netrc文件获取登录凭证。

hyp3 = sdk.HyP3()

如果不太懂如何操作.netrc ,可以使用data_downloader 包来管理.netrc

安装 data-downloader

pip install data_downloader

使用 data_downloader 管理 .netrc

from data_downloader import downloader

netrc = downloader.Netrc()
# 添加登录信息到netrc文件中。MyUsername,MyPassword分别为自己的 NASA 账号的用户名与密码
netrc.add('urs.earthdata.nasa.gov', 'MyUsername', 'MyPassword')

# 查看.netrc中的信息
print(netrc)

(2) 直接传递登录信息到参数

直接将用户名与密码写到HyP3 类中。

# MyUsername,MyPassword分别为自己的 NASA 账号的用户名与密码
hyp3 = HyP3(username='MyUsername', password='MyPassword')

(3)手动输入凭证授权

通过终端,自己手动输入用户名与密码。

hyp3 = sdk.HyP3(prompt=True) #运行时,会分别询问用户名和密码

3.3. 提交Jobs

HyP3 SDK 有3种job类型:

  • RTC: SAR数据集固有地包含几何和辐射失真。辐射地形校正(RTC)消除了这些失真,并生成了适用于GIS应用的分析的数据。RTC处理是许多基于振幅的SAR应用所需的第一步。
  • InSAR: 干涉合成孔径雷达( Interferometric SAR,InSAR )利用同一区域内重复经过的相位差来识别传感器与地球表面距离发生变化的区域。
  • autoRIFT: AutoRIFT利用NASA MEaSUREs ITS _ LIVE项目中开发的特征跟踪算法从观测运动中生成速度图。

注意:

ASF决定从 2022 年 2 月开始, 处理配额将设置为每个用户每月 1000 个jobs。
2024年4月1日起,将更换结算方式:每个月拥有10000 credits,可提交的jobs如下表:

fastapi连接pymysql_insar

(1) 提交Sentinel-1 RTC jobs

Sentinel-1辐射地形校正(RTC)作业是使用 ESA granule IDs 提交的。下面的 示例 granule 可以在ASF搜索中查看。

granules = [
    'S1A_IW_SLC__1SDV_20210214T154835_20210214T154901_036588_044C54_8494',
    'S1B_IW_SLC__1SDV_20210210T153131_20210210T153159_025546_030B48_B568',
    'S1A_IW_SLC__1SDV_20210210T025526_20210210T025553_036522_0449E2_7769',
    'S1A_IW_SLC__1SDV_20210210T025501_20210210T025528_036522_0449E2_3917',
    'S1B_IW_SLC__1SDV_20210209T030255_20210209T030323_025524_030A8D_7E88',
    'S1B_IW_SLC__1SDV_20210209T030227_20210209T030257_025524_030A8D_5BAF',
    'S1A_IW_SLC__1SDV_20210202T154835_20210202T154902_036413_044634_01A1',
]


rtc_jobs = sdk.Batch()
for g in granules:
    rtc_jobs += hyp3.submit_rtc_job(g, name='rtc-example')
print(rtc_jobs)

这里我们将每个作业命名为rtc-example,稍后我们可以使用它来搜索这些作业。

HyP3.submit_rtc_job 还接受 关键字参数 来为您的应用程序定制生成的RTC产品。

(2)提交Sentinel-1 InSAR jobs

SDK还可以提交Sentinel-1干涉合成孔径雷达(InSAR)作业,处理reference-secondary干涉对。

from tqdm.auto import tqdm  # 用于生成进度条,第三方包,可以使用 pip install tqdm 进行安装

insar_jobs = sdk.Batch()

pairs = [('S1B_IW_SLC__1SSV_20170111T232556_20170111T232624_003807_0068BB_61D1',
  'S1B_IW_SLC__1SSV_20170204T232555_20170204T232623_004157_00731B_FBFA'),
 ('S1B_IW_SLC__1SSV_20170111T232556_20170111T232624_003807_0068BB_61D1',
  'S1A_IW_SLC__1SDV_20170222T232637_20170222T232705_015403_019477_F04A'),
 ('S1B_IW_SLC__1SSV_20170111T232556_20170111T232624_003807_0068BB_61D1',
  'S1A_IW_SLC__1SDV_20170318T232638_20170318T232705_015753_019EF5_7A50'),
 ('S1B_IW_SLC__1SSV_20170204T232555_20170204T232623_004157_00731B_FBFA',
  'S1A_IW_SLC__1SDV_20170222T232637_20170222T232705_015403_019477_F04A'),
 ('S1B_IW_SLC__1SSV_20170204T232555_20170204T232623_004157_00731B_FBFA',
  'S1A_IW_SLC__1SDV_20170318T232638_20170318T232705_015753_019EF5_7A50')]
  
for reference, secondary in tqdm(pairs):
    insar_jobs += hyp3.submit_insar_job(
        reference, secondary, 
        # 指定job的name,用于后面查询
        name='insar-example',
        # 要求结果包含DEM文件。默认是False, 不包含。使用Mintpy需改为True
        include_dem=True,
        # 要求结果包含角度theta和phi文件。默认是False, 不包含。使用Mintpy需改为True
        include_look_vectors=True,
        # 要求结果包含缠绕相位(相位减缠前)结果。默认是False, 不包含。
        include_wrapped_phase=True, 
        # 要求结果包形变结果,包含了LOS形变与垂直形变,其中垂直形变是假设形变全部为垂直方向。默认是False, 不包含。
        include_displacement_maps=True
        # 多视比例,可以是'10x2'(40m) 或者 '20x4' (80m)
        looks='10x2',
        # 自适应滤波强度,接受0.2到1之间的任意小数。值越大,滤波强度越高。如果是0,则不进行滤波。默认为0.6
        phase_filter_parameter=0.5,
        # 是否滤除掉水体中的像元
        apply_water_mask=False,
	)

与RTC作业一样,HyP3.submit_insar_job接受关键字参数来为应用程序定制生成的insar产品。例如,本例中的include_wrapped_phase=True 与 include_displacement_maps=True。

(3)提交autoRIFT jobs

AutoRIFT支持处理 Sentinel-1、Sentinel-2 或 Landsat-8 Collection 2。

  • Sentinel-1 jobs 提交使用 ESA granule IDs
  • Sentinel-2 jobs 提交使用 ESA granule IDs
  • Landsat-8 Collection 2 jobs 提交使用 USGS scene IDs
autorift_pairs = [
    # Sentinel-1 ESA granule IDs
    ('S1A_IW_SLC__1SSH_20170221T204710_20170221T204737_015387_0193F6_AB07',
     'S1B_IW_SLC__1SSH_20170227T204628_20170227T204655_004491_007D11_6654'),
    # Sentinel-2 ESA granule IDs
    ('S2B_MSIL1C_20200612T150759_N0209_R025_T22WEB_20200612T184700',
     'S2A_MSIL1C_20200627T150921_N0209_R025_T22WEB_20200627T170912'),
    # Landsat 8
    ('LC08_L1TP_009011_20200703_20200913_02_T1',
     'LC08_L1TP_009011_20200820_20200905_02_T1'),
]

autorift_jobs = sdk.Batch()
for reference, secondary in autorift_pairs:
    autorift_jobs += hyp3.submit_autorift_job(reference, secondary, name='autorift-example')
print(autorift_jobs)

AutoRIFT目前不接受任何用于产品定制的关键字参数。

3.4 监控 jobs处理进度

一旦提交了一个作业,我们可以观察作业,直到它们完成。HyP3 SDK提供了多种监控jobs处理进度的方式:

  1. 我们可以使用刚才创建的作业类来观察,这需要保持终端一直在运行。一旦批处理中的某个作业完成,hyp3.watch()将返回一个刷新的批处理。
rtc_jobs = hyp3.watch(rtc_jobs)
  1. 如果终端不小心被关闭,我们也可以通过作业名字来手动查找并观察已经提交过的jobs。
rtc_jobs = hyp3.find_jobs(name='rtc-example')
rtc_jobs = hyp3.watch(rtc_jobs)
  1. 如果我们不需要持续观察jobs的进度,也可以刷新作业快照,并输出作业进度信息。BatchesJobs 的集合。它们提供了创建或上次刷新作业时作业状态的快照。要刷新Batches的信息,可以执行:
print(insar_jobs)
insar_jobs = hyp3.refresh(insar_jobs)
print(insar_jobs)

Batches 可以加到一块

print(f'Number of Jobs:\n  RTC:{len(rtc_jobs)}\n  InSAR:{len(insar_jobs)}\n  autoRIFT:{len(autorift_jobs)}')
all_jobs = rtc_jobs + insar_jobs + autorift_jobs
print(f'Total number of Jobs: {len(all_jobs)}')
  1. 你可以通过jobs的处理状态过滤jobs
succeeded_jobs = all_jobs.filter_jobs(succeeded=True, running=False, failed=False)
print(f'Number of succeeded jobs: {len(succeeded_jobs)}')
failed_jobs = all_jobs.filter_jobs(succeeded=False, running=False, failed=True)
print(f'Number of failed jobs: {len(failed_jobs)}')

我们由此可以写一个监测状态的函数:

def job_status(name):
    hyp3 = sdk.HyP3()
    insar_jobs = hyp3.find_jobs(name=name)

    succeeded_jobs = insar_jobs.filter_jobs(succeeded=True, running=False, failed=False)
    failed_jobs = insar_jobs.filter_jobs(succeeded=False, running=False, failed=True)
    running_jobs = insar_jobs.filter_jobs(succeeded=False, running=True, failed=False)

    job_complete = insar_jobs.complete()

    print(f"total: {len(insar_jobs)}, complete: {job_complete}")
    print(f"    success: {len(succeeded_jobs)}")
    print(f"    failed: {len(failed_jobs)}")
    print(f"    running: {len(running_jobs)}")

job_status(name="insar-example")

输出的状态:

total: 500, complete: False
    success: 234
    failed: 0
    running: 266

3.4 下载文件

batches中已经成功的文件可以下载到本地。

result_dir = r'D:\hyp3_result' # 指定下载到本地的文件夹
file_list = succeeded_jobs.download_files(result_dir)

也可以直接下载仍然有运行中的jobs的batches,代码会跳过未完成的jobs,并一直自动下载已经完成的jobs。

result_dir = r'D:\hyp3_result' # 指定下载到本地的文件夹
file_list = all_jobs.download_files(result_dir)
...
S1AA_20181015T232654_20181120T232654_VVP036_INT80_G_ueF_9433.zip: 100%|██████████| 172M/172M [07:48<00:00, 384kB/s]
S1AA_20181015T232654_20181108T232654_VVP024_INT80_G_ueF_5267.zip: 100%|██████████| 172M/172M [29:13<00:00, 103kB/s]
S1AA_20181015T232654_20181027T232654_VVP012_INT80_G_ueF_AEA3.zip: 100%|██████████| 167M/167M [11:09<00:00, 262kB/s]
S1AA_20181003T232654_20181108T232654_VVP036_INT80_G_ueF_EC6D.zip: 100%|██████████| 169M/169M [13:11<00:00, 224kB/s]
 73%|███████▎  | 422/582 [8:04:45<39:35:24, 890.78s/it]

目前,hyp3_sdk 不能自动跳过下载完成的文件。如果下载被迫中断,需要重新下载,想自动跳过已经下载过的文件,可以使用data_downloader 包。

result_dir = r'D:\hyp3_result' # 指定下载到本地的文件夹

while True:
 	#查询jobs是否已经全部处理完
    job_complete = insar_jobs.complete()
    # 查询成功的jobs
    succeeded_jobs = insar_jobs.filter_jobs(succeeded=True, running=False, failed=False)
    if len(succeeded_jobs.jobs) == 0:
        print('No jobs succeeded yet. Waiting 60 seconds...')
        time.sleep(60)
        continue
    else:
        for job in tqdm(succeeded_jobs.jobs):
            for file in job.files:
                download_url = file['url']
                #如果已经下载了一部分,downloader会自动继续以前的下载,如果已经下载完成,则会自动跳过。所以不需要做特殊处理
                downloader.download_data(download_url,folder=result_dir) 
    # 如果提交的jobs已经全部处理,则上面的步奏已经将所有job下载到了本地, 需要跳出循环。否则继续刷新并下载成功的job。
    if job_complete:
        break