geotrellis使用(二十三)动态加载时间序列数据
目录
一、前言
今天要介绍的绝对是华丽的干货。比如我们从互联网上下载到了一系列(每天或者月平均等)的MODIS数据,我们怎么能够对比同一区域不同时间的数据情况,采用传统的方法可能只能将所有要参考的数据用ArcGIS等打开,然后费劲的一一对比等,不仅操作繁琐,搞不好日期等还会对应错。本文就是介绍使用Geotrellis动态加载时间序列数据,使我们能够自由选择日期浏览或者像动画一样循环展示一系列数据。直接进入干货。
二、实现方法
2.1 前台界面
前台与以往保持不变,但是你需要保证能够提供请求时间的时间序列范围,如想实现根据用户输入的日期展示当期数据,那么你需要提供一个日期选择器;如果你想动态加载系列数据那么你必须能够提供这一系列的日期范围,并能够自动改变日期。总之你需要将日期作为一个参数发送到后台已达到请求该日期数据的效果。
2.2 数据准备
这一块与以往变化比较大,首先要对tiff数据进行预处理,重投影等自不需要多言,主要是要给tiff加个时间头信息。有两种方式,可以使用GDAL或者自己写程序,分布介绍如下:
1、使用GDAL实现添加时间头信息
只需要一条命令即可:
gdal_edit -mo TIFFTAG_DATETIME="time" yourtiff.tif
上述命令就会给tiff文件添加一个名为TIFFTAG_DATETIME的头文件信息,time表示你想添加的时间,需要符合ISO标准,否则你需要在导入数据的时候指定时间格式。
2、使用Geotrellis实现添加时间头信息
主要步骤为读取tiff文件、修添加时间头信息、保存新的tiff文件。代码如下:
val tiff = SinglebandGeoTiff(path)
tiff.tags.headTags + (Tags.TIFFTAG_DATETIME -> time)
val newtiff = new SinglebandGeoTiff(tiff.tile, tiff.extent, tiff.crs, Tags(map, tiff.tags.bandTags), tiff.options)
newtiff.write(newTiffPath)
代码同样很简单,但是说实话不如GDAL来的方便,仅供参考。
2.3 时间序列数据导入
数据准备好之后我们就可以开始着手导入,这里面有很多需要改变的地方。
1、改变数据导入类
普通tiff数据导入的时候调用ETL类的方式如下:
Etl.ingest[ProjectedExtent, SpatialKey, Tile](args)
但是到了时间序列数据就要变为:
Etl.ingest[TemporalProjectedExtent, SpaceTimeKey, Tile](args)
主要是添加时间支持,ProjectedExtent变为TemporalProjectedExtent,SpatialKey变为SpaceTimeKey,当然如果是多波段还需要将Tile替换为MultibandTile。
2、改变导入参数
在geotrellis使用(二十)geotrellis1.0版本新功能及变化介绍一文中已经介绍过了1.0版Geotrellis导入数据的方式变为json文件,这里input.json中只需要将format由geotiff改为temporal-geotiff;output.json中需要将keyIndexMethod中的内容改成如下方式:
"keyIndexMethod":{
"type":"zorder",
"temporalResolution": 86400000,
"timeTag":"TIFFTAG_DATETIME",
"timeFormat":"yyyy:MM:dd HH:mm:ss"
}
其中temporalResolution表示时间精度,理论上来说,设置此值表示当你根据时间查询的时候在这个精度范围内的数据都应该能够查询出来,但是实际上好像并不是这样,不知道是其bug还是我操作方式有问题,需要后续进一步研究;timeTag指定时间头字段名称;timeFormat指定时间格式。
完成以上步骤之后即可将时间序列数据导入到accumulo中。
2.4 获取对应时间数据瓦片
前台将请求的时间已经瓦片的x、y、z编号传入后台,后台接收到之后根据此四个参数进行查询,相较普通tiff数据实际上只是多添加了时间条件。请求瓦片代码如下:
val dt = DateTimeFormat.forPattern("yyyy:MM:dd HH:mm:ss").parseDateTime(time)
val key = SpaceTimeKey(x, y, dt)
val layerId = LayerId(name, zoom)
respondWithMediaType(MediaTypes.`image/png`) {
val result = {
val tile = tileReader.reader[SpaceTimeKey, Tile](layerId).read(key)
tile.renderPng.bytes
}
complete(result)
}
其中name表示上一步数据导入时存放的名字;tileReader为AccumuloValueReader实例。这样就能将用户请求的时间以及x、y、z瓦片数据渲染之后发送到前台,这里还需要强调的是Geotrellis中时间处理采用joda开源框架,关于其用法大家可以网上自行搜索。最后为大家附上两张截图,当然如果是动画效果会更好,由于没有录制,仅提供两张截图以达到展示动态的效果。
三、总结
本文为大家简单介绍了如何动态加载时间序列数据,同样读者可以根据自己的需求任意发挥想象,达到自己需要的效果。比如可以实现动态展示全球洋流、大气、农作物、植被等变化情况。凡是在一段时间内有变化的数据,当我们搜集到足够多的数据并添加时间标签之后即可将其“动”起来,我想这种展示效果一定很棒。
Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html