GEE:批量处理和下载指定时间段的MODIS-GPP产品(MOD17A3HGF)
01 说明
- 任务分成两个:第一是指定时间范围,提取该范围内的所有GPP影像求取均值;第二是指定时间范围,按年尺度提取每一年中的
GPP影像求取均值(一年一景) - 要求包括:全球尺度、输出地理坐标系WGS84且分辨率为0.05°、无效值处理;
02 代码说明
2.1 输出指定时间段的影像均值
完整代码:
// 选择需要输出GPP产品的时间范围
var start_date = ee.Date.fromYMD(2023, 1, 1); // 开始日期
var end_date = ee.Date.fromYMD(2023, 12, 31); // 结束日期
var gpp_name = 'Gpp'; // 需要的波段名称, MOD17A3HGF包括Gpp、Npp以及Npp_QC三个波段
var apply_land_mask = true; // 是否掩膜只要陆地地区, 若为true则掩膜;若为false则不进行掩膜
var min_value = 0; // 有效值的范围
var max_value = 65500; // 同理
var out_res = 0.05 // 输出分辨率(单位为°)
// 加载MODIS-GPP产品(MOD17A3HGF)
var gpp_collection = ee.ImageCollection("MODIS/061/MOD17A3HGF"); // 从云计算平台加载指定数据集
// 筛选指定年份的影像
var gpp_img = gpp_collection.filterDate(start_date, end_date).select(gpp_name).mean();
// 获取并应用有效值范围的掩膜
var valid_range_mask = gpp_img.gte(min_value).and(gpp_img.lte(max_value));
gpp_img = gpp_img.updateMask(valid_range_mask);
// 应用缩放因子(缩放后单位为:kg*C/m^2, 由于MOD17A3是年尺度,因此这也可以视为kg*C/m^2/year)
gpp_img = gpp_img.multiply(0.0001);
/*
为什么要应用缩放因子?
因为GEE上存储的数据量非常大, 整数存储相比于小数存储在大数据量面前将会有非常大的性价比减少
更多的存储空间, 因此存储时会先将小数放大n倍转化为小数,在需要时乘以缩放因子即可恢复原来的数值.
*/
// 掩膜(只需要陆地地区)
if (apply_land_mask === true){
var water_mask = ee.Image('MODIS/MOD44W/MOD44W_005_2000_02_24').select('water_mask');
var land_mask = water_mask.eq(0);
gpp_img = gpp_img.updateMask(land_mask);
}
// 定义地理范围
var global_region = ee.Geometry.Rectangle([-180, -90, 180, 90], 'EPSG:4326', false);
// 可视化参数
var gpp_vis_param = {
min: 0.0,
max: 3.0,
palette: ['#bbe029', '#0a9501', '#074b03']
};
// 可视化
Map.setCenter(0, 0, 2); // 显示的中心位置和缩放大小, 参数依次为(经度: 0, 纬度: 0, 缩放级别:2)
// 导出影像到Google Drive
var cur_year = start_date.get('year');
cur_year.evaluate(function(cur_year){
Map.addLayer(gpp_img, gpp_vis_param, 'Annual_GPP_' + cur_year);
Export.image.toDrive({
image: gpp_img.resample('bilinear'), // 输出使用双线性插值, 若不需要删除.resample('bilinear')
description: 'Global_GPP_' + cur_year,
folder: 'Global_GPP',
fileNamePrefix: 'Global_GPP_' + cur_year,
region: global_region,
crs: 'EPSG:4326', // 坐标系为WGS84
crsTransform: [out_res, 0, -180, 0, -out_res, 90], //
maxPixels: 1e13, // 防止像元个数过多拒绝导出, 增加导出上限
formatOptions: {'noData': -9999} // NoData值为-9999
});
});
可能需要说明的是evaluate方法(这段代码使用evaluate方法有点多余,但是后续批量输出下载等是很难避免使用这个方法,不如在这里将这个方法稍微理一理):
原文为:Asynchronously retrieves the value of this object from the server and passes it to the provided callback function.
即异步地将该变量(谁调用的evaluate方法谁就是此处所指代的the value,例如year_list.evaluate(),则the value指代year_list)传递给服务器,让服务器计算它的值,服务器计算好该值之后再将其提供给回调函数。
所以含义是什么?
不管异步这一操作,就是在客户端(你的浏览器)上存在一个变量,这个变量具体的值还不清楚没有计算但是你现在又需要这里面的值来进行后续处理,那么你就可以通过evaluate方法将其传递给服务器(GEE的远程云计算平台),让服务器计算好之后,再传送回给客户端浏览器,再继续在客户端本地进行后续处理,这里的后续处理就是前面提及的回调函数,服务器计算好的结果应该怎么传送回给本地浏览器呢?你用一个变量去接?接住了还需要进行处理? ⇒ 那么方法就是定义一个回调函数以及一个函数的参数,服务器计算好之后将这个计算好的变量值传递给这个回调函数参数,然后运行这个回调函数。
那么异步是什么意思呢?就是year_list.evaluate执行之后,变量到了服务器就好,接着往后运行后续代码,而至于.evaluate()内部的回调函数的定义、运行回调函数它慢慢运行就好了,我的主程序是不会等待的。举一个不恰当的例子就是我在去银行取号排队,中间排队这个过程就是evaluate函数内部做的事情(变量上传给服务器、服务器计算结果、结果返回给回调函数,执行回调函数),但是排队过程我无需排队一直等待(即不用等前面括号内的这一系列事情做完),我可以去做我想做的事情(执行后续代码)例如买零食买玩具。
上述的evaluate方法因为时间关系并没有解释特别到位,但是这里列举一点示例稍微说明一下这个函数
// 情况1
var year_list = [2010, 2011, 2012, 2013, 2014];
year_list.map(function(cur_year){
print(cur_year);
});
// 情况2
var year_list = ee.List.sequence(2010, 2014)
year_list.map(function(cur_year){
print(cur_year);
});
// 情况3
var year_list = ee.List.sequence(2010, 2014)
year_list.evaluate(function(year_list){
year_list.map(function(cur_year){
print(cur_year);
});
})
对于上面三种情况,只有情况2无法运行会报错,为什么呢?这里就需要理解为什么要使用.evaluate()方法了。由于year_list中的各个元素值是需要print输出的。而通过ee.List.sequence定义的year_list使用的map方法是需要在服务端上运行的(这里就要提及为什么情况1的map就不需要,因为通过[]定义的是具体array数组,其map方法不需要在服务器中运行,此外这两个map方法也有一定的差别,如果对于情况2的报错内容仔细查看发现首先是报错map方法没有返回值),而map方法中的print是在本地进行运行的(因为print输出肯定是在浏览器中展示结果自然是需要在本地浏览器中运行),因此map在服务器中运行时,遇到了print,服务器不知道打印到哪里去,因此报错了。但是对于情况3,year_list.evaluate将变量传递给服务器计算之后传回本地浏览器,执行回调函数,由于变量已经传回本地了因此print输出自然没有问题。
至于异步这一问题,查看下方代码和输出自行理解即可,这里不再赘述:
// 情况4
print('1. 代码开始运行')
var year_list = ee.List.sequence(2010, 2014)
year_list.evaluate(function(year_list){
print('3. 获取得到服务器传递的变量值, 批量输出中···')
year_list.map(function(cur_year){
print(cur_year);
});
print('4. 回调函数执行完毕')
})
print('2. 主程序运行完毕')
输出结果:

2.2 年尺度上批量输出指定时间段的一年影像均值(一年一景)
完整代码:
// 选择需要输出GPP产品的时间范围(一年一景)
var start_date = ee.Date.fromYMD(2001, 1, 1); // 开始日期, MOD17A3的生产范围是2001-1-1至今
var end_date = ee.Date.fromYMD(2020, 12, 31); // 结束日期
var gpp_name = 'Gpp'; // 需要的波段名称, MOD17A3HGF包括Gpp、Npp以及Npp_QC三个波段
var apply_land_mask = true; // 是否掩膜只要陆地地区, 若为true则掩膜;若为false则不进行掩膜
var is_vis = true // 是否在下方地图中显示每一年的GPP产品(耗时)
var min_value = 0; // 有效值的范围
var max_value = 65500; // 同理
var out_res = 0.05; // 输出分辨率(单位为°)
// 获取年列表-用于批量输出
var start_year = start_date.get('year');
var end_year = end_date.get('year');
var year_list = ee.List.sequence(start_year, end_year)
// 加载MODIS-GPP产品(MOD17A3HGF)
var gpp_collection = ee.ImageCollection("MODIS/061/MOD17A3HGF"); // 从云计算平台加载指定数据集
// 获取陆地掩膜
var water_mask = ee.Image('MODIS/MOD44W/MOD44W_005_2000_02_24').select('water_mask');
var land_mask = water_mask.eq(0);
// 定义地理范围(默认全球)
var global_region = ee.Geometry.Rectangle([-180, -90, 180, 90], 'EPSG:4326', false)
// 可视化参数
var gpp_vis_param = {
min: 0.0,
max: 3.0,
palette: ['#bbe029', '#0a9501', '#074b03']
};
// 可视化
Map.setCenter(0, 0, 2); // 显示的中心位置和缩放大小, 参数依次为(经度: 0, 纬度: 0, 缩放级别:2)
// 导出影像到Google Drive(ps: 一年一景是理论, 实际上由于全球区域太大且分辨率过高,因此一年的tiff会分块输出成多个tiff文件)
year_list.evaluate(function(year_list){
year_list.map(function(cur_year){
var cur_start_date = ee.Date.fromYMD(cur_year, 1, 1);
var cur_end_date = ee.Date.fromYMD(cur_year, 12, 31);
// 筛选指定年份的影像
var gpp_img = gpp_collection.filterDate(cur_start_date, cur_end_date).select(gpp_name).first();
// 获取并应用有效值范围的掩膜
var valid_range_mask = gpp_img.gte(min_value).and(gpp_img.lte(max_value));
gpp_img = gpp_img.updateMask(valid_range_mask);
// 应用缩放因子(缩放后单位为:kg*C/m^2, 由于MOD17A3是年尺度,因此这也可以视为kg*C/m^2/year)
gpp_img = gpp_img.multiply(0.0001);
/*
为什么要应用缩放因子?
因为GEE上存储的数据量非常大, 整数存储相比于小数存储在大数据量面前将会有非常大的性价比减少
更多的存储空间, 因此存储时会先将小数放大n倍转化为小数,在需要时乘以缩放因子即可恢复原来的数值.
*/
// 掩膜(只需要陆地地区)
if (apply_land_mask === true){
gpp_img = gpp_img.updateMask(land_mask);
}
// 是否可视化
if (is_vis === true){
Map.addLayer(gpp_img, gpp_vis_param, 'Annual_GPP_' + cur_year);
}
Export.image.toDrive({
image: gpp_img.resample('bilinear'), // 若需要最近邻插值, 删除.resample('bilinear')即可
description: 'Global_GPP_' + cur_year,
folder: 'Global_GPP',
fileNamePrefix: 'Global_GPP_' + cur_year,
crs: 'EPSG:4326', // 坐标系为WGS84
crsTransform: [out_res, 0, -180, 0, -out_res, 90], // 仿射系数
region: global_region, // 输出的地理范围
maxPixels: 1e13, // 防止像元个数过多拒绝导出, 增加导出上限
formatOptions: {'noData': -9999} // NoData值为-9999
});
})
});
这里关于代码说明不在过多赘述,原理类似,只是多加了一层循环。
本文由博客一文多发平台 OpenWrite 发布!
GEE:批量处理和下载指定时间段的MODIS-GPP产品(MOD17A3HGF)的更多相关文章
- .net调用Outlook 批量发送邮件,可指定Outlook中的账号来发送邮件
.net调用Outlook 批量发送邮件,可指定Outlook中的账号来发送邮件 源码可以在我的资源列表中下载: MPOEMail http://download.csdn.net/my VS2012 ...
- shell查找指定时间段内的文件
#!/bin/bash#20170905 输入参数格式echo "显示"$1"的备份文件"date_0=$1date_1=`expr $date_0 + 1`d ...
- php使用curl下载指定大小的文件
php中使用基于libcurl的curl函数,可以对目标url发起http请求并获取返回的响应内容.通常的请求方式类似如下的代码: public function callFunction($url, ...
- 通过wget工具下载指定文件中的URLs对应的资源并保存到指定的本地目录中去并进行文件完整性与可靠性校验
创建URLs文件在终端输入cd target_directory回车,便把当前文件夹切换到了目标文件夹target_directory,此后创建的文件都会丢它里面在终端输入cat > URLs回 ...
- git下载指定的版本
1.查看提交历史 sudo git log 打印如下内容: commit 2e3c19d412ab6a99bb51f338f71537a720a9c706 Author: huangbaog ...
- wget下载指定URL下的特定属性文件
例子:下载指定URL下的kernel开头的所有包 wget https://archives.fedoraproject.org/pub/fedora/linux/updates/28/Everyth ...
- 从官网下载指定版本的JDK
从官网下载指定版本的JDK 一.百度搜索jdk,进入最新版Downloads界面 百度搜索jdk,或者jdk下载,点击进入jdk官网最新版本下载界面,可以看到当前最新版本为jdk12 二.找到JDK历 ...
- python下载指定的版本包
首先我们很多时候在执行pip的时候是不行的 有时候很难成功,这个时候我们就要想其他的版本了 一.是不是这个包需要指定版本, 比如python2的和mysql链接的是,而python3则是mysqlc ...
- 使用PowerShell批量解除锁定下载的文件
使用PowerShell批量解除锁定下载的文件 3.在需要解锁的文件所在的文件夹中空白处,按住Shift然后单击右键,在弹出的右键菜单中,选择“在此处打开PowerShell窗口”, 输入Get-Ch ...
- nodejs如何下载指定版本
浏览了一下nodejs的官网,但是官网没有下载低版本的下载地址,所以找了一个可以下载指定版本node的下载地址https://nodejs.org/download/release/v8.9.4/
随机推荐
- AtCoder Beginner Contest 341-F
AtCoder Beginner Contest 341-F F - Breakdown Problem 给你一个由 \(N\) 个顶点和 \(M\) 条边组成的简单无向图.每个顶点拥有权重\(W_i ...
- Linux xargs命令解析及递归执行dos2unix命令
一.xargs 命令的作用 xargs命令的作用,是将标准输入转为命令行参数. $ echo "hello world" | xargs echo hello world 上面的代 ...
- mysql安装配置启动
1. 安装 & 配置 & 启动 MySQL现在的版本主要分为: 5.x 版本,现在互联网企业中的主流版本,包括:头条.美图.百度.腾讯等互联网公司主流的版本. 8.x 版本,新增了一些 ...
- 论文解读:Knowledge Neurons in Pretrained Transformers
论文发表于自然语言处理顶会ACL-2022(原文链接).本文引入知识神经元 (Knowledge Neuron) 的概念,初步研究了预训练Transformer中是如何存储事实知识的: 1.通 ...
- AI大模型应用开发入门-LangChain开发聊天机器人ChatBot
在大模型应用开发中,状态管理 和 对话追踪 是不可忽视的重要能力,尤其在需要保存上下文.重放对话或进行异步处理时尤为关键. 今天我们来演示如何用 LangChain + OpenAI 的 GPT 模型 ...
- 技术干货|如何利用 ChunJun 实现数据实时同步?
实时同步是 ChunJun 的⼀个重要特性,指在数据同步过程中,数据源与⽬标系统之间的数据传输和更新⼏乎在同⼀时间进⾏. 在实时同步场景中我们更加关注源端,当源系统中的数据发⽣变化时,这些变化会⽴即传 ...
- HyperWorks卫星惯性释放分析(OptiStruct)
Step01:读取模型,并设置求解器模板为 OptiStruct. (1) 读入 IGES 格式的几何模型 Exercise_9a.iges. 在绝大多数 CAE 分析中,都将从一个导入的 CAD 模 ...
- Java源码分析系列笔记-15.CompletableFuture
目录 1. 是什么 2. Future VS CompletableFutre 3. 使用 3.1. 运行一个不返回结果的任务 3.2. 运行一个返回结果的任务 3.3. 线程池 3.4. 手动完成任 ...
- jre 的生成与使用
前言 从 Java 9 开始,Oracle 不再单独提供 JRE(Java Runtime Environment) 的独立安装包,而是推荐开发者使用 模块化的 JRE 或 jlink 工具 来自定义 ...
- 迁移学习&在线学习
简介 英文: transfer learning 以已训练好的模型A为起点,在新场景中,根据新数据建立模型B 目的:将某个领域或任务上学习到的知识或模式,应用到不同但相关的领域或问题中. 特征提取 使 ...