北半球亮温图像
使用卫星研究积雪可以解锁原本无法研究的区域信息,尤其是在大范围内。除了覆盖范围广之外,携带无源微波传感器的太阳同步卫星每天都会在相似的时间拍摄两极图像。这些一致的测量使令人难以置信的每日时间序列可以追溯到 1978 年 Nimbus 7 卫星的发射。 Nimbus 计划是 NASA 和 NOAA 首次合作发射专门用于气象研究的卫星,40 多年后,我们仍然受益于对气候研究的早期投资。
在这篇文章中,我们将介绍使用 Matplotlib 和 Cartopy 可视化卫星图像的各种方法。这两个库是我们制作演示地图时非常高效的工具;虽然网络地图风靡一时,但我们通常需要一个非在线托管的高质量可视化。
我们将从使用 Matplotlib 快速且信息丰富的图像图开始,然后深入研究使用 Cartopy 使用 Matplotlib 绘制地理坐标。最后,我们将讨论如何为使用 Matplotlib 制作的图像和地图制作动画以显示随时间的变化让我们学习如何使用 Matplotlib 来可视化阿拉斯加的积雪。
数据
<背景>
我们将与 MEaSUREs 校准增强分辨率无源微波数据集合作,该数据集是美国宇航局制作地球系统数据记录以用于研究环境 (MEaSUREs) 计划的一部分。这个数据集很特别,因为它被重新采样到比传感器最初捕获的分辨率高得多的分辨率;原始像素宽 25km,但新数据像素宽 6.25km。这意味着原来的一个像素,增强到16个像素。
这些无源微波传感器测量的辐射能量非常低,这迫使我们在大范围内测量它以获得良好的读数。虽然与其他类型的卫星图像相比,6.25 公里仍然是一个宽像素,但它使我们能够比以前更详细地研究积雪。
无源微波辐射计测量的主要参数之一是亮温 (TB),它是对移动到卫星上传感器的辐射的辐射度的度量。我们以千兆赫 (GHz) 表示的不同频率测量 TB。对于地面上的雪分析,我们专注于 37GHz 和 19GHz 频率。当地面上没有雪时,两个频率相似,但随着雪在地面上堆积,37GHz 频率的散射会更多。这种差异使我们能够找到雪水当量 (SWE) 的代理变量,即储存在雪体中的水量。
在此图中,可以看到 19GHz 和 37GHz 频段在冬季如何发散,这是由于 37GHz 频段从雪中散射得更多。
这篇文将深入研究了这个数据集,以及我们如何使用无源微波传感器测量的亮度温度来估计积雪中储存的水量。如果您对使用被动微波图像研究雪背后的科学感兴趣,请阅读该文章的前半部分。
<选择研究区域>
为了使用合理数量的数据,我们需要选择一个研究区域,因为使用完整北半球图像的时间序列需要存储大量数据!下面您将看到我们将绘制的阿拉斯加地区。
由于此数据使用 EASE-Grid 2.0 投影,我们必须通过选择左上角和右下角坐标集来选择边界框。等面积可缩放地球 (EASE) 网格是用于全局缩放网格数据的通用格式,可以很好地保留映射对象的区域。不过,EASE 网格不使用纬度和经度;相反,他们选择以米为单位的行/列系统。稍后我将展示如何在纬度/经度和行/列坐标之间进行转换,这称为重投影。
使用 Matplotlib 绘制 SWE
Matplotlib 是 Python 程序员可用的事实上的绘图库。虽然它比交互式绘图库在图形上更简单,但它仍然可以e 一个强大的工具。 Matplotlib 是我的快速绘图和演示的首选库,我想在其中传达特定的观点。交互式地图很难清晰呈现;除非您在进行现场编码演示,否则您永远不想在与观众交谈时与计算机进行交互。
<使用 imshow 进行简单的图像绘图>
绘图是探索性数据分析的关键组成部分,而 Matplotlib 非常适合我们需要的 EDA 类型的快速绘图。使用我们的 SWE 数据,简单地绘制一天的时间序列可以有力地证实我们正确地对图像进行了子集化。
fig = plt.figure(figsize=(12,6)) im = plt.imshow(swe[0,:,:])
使用 Matplotlib 的 imshow 函数可以让我们像绘制任何图像一样绘制栅格数据。我们可以看到该图中的海岸线与我用来创建上面的边界框的 Google 地球轮廓之间的大致相似之处,这意味着我们确实正确地对数据进行了子集化!
但是,该图缺少一些关键组件。让我们用一些基本的 Matplotlib 格式来增加一些信息:
fig = plt.figure(figsize=(12,6)) im = plt.imshow(swe[0,:,:],cmap='gist_rainbow') plt.colorbar(im) plt.title(''SWE (mm) on Jan 23, 1993 | North Slope, Alaska'');
这种图在演示中被经常使用;要想避免分心很简单,并且可以快速理解,以便听众可以专注于我在说什么。在颜色并不总是最饱和的投影仪上展示绘图时,使用对比度更高的颜色图会有所帮助。强烈对比的颜色使人们能够快速看到细微的差异,而这些差异在更微妙的颜色图上很难分辨。
<利用子图>
子图通过允许我们在一个画布上组合多个图为我们提供了许多扩展功能。我们可以使用子图查看我们研究区域在第一年不同季节的快照。
这是一个很酷的图。有趣的是,看到秋天积雪,冬天达到顶峰,并在春天的图像中几乎完全融化。夏季/秋季图像和冬季/春季图像之间的海洋温度也明显变化;我们可以看到,海洋重新变暖所需的时间可能比陆地上的雪融化所需的时间更长。
虽然这些图提供了信息,但由于我们将数据视为通用图像,因此我们丢失了实际使网格与地球一致的坐标参考系统。当我们绘制这样的空间数据时,我们失去了很多正确的形状和空间背景;接下来让我们尝试使用 Cartopy 在地图上绘制它。
<添加投影>
Matplotlib 默认设计为在传统网格空间中绘图。为了在地图上显示数据,我们必须有一个具有匹配投影的底图。幸运的是,存在一个名为 Cartopy 的库,它旨在处理地理空间数据以使用 Matplotlib 进行映射。关于 Matplotlib,我最喜欢的事情之一是开发人员在它之上构建是多么容易; Cartopy 与 Seaborn 有点相似,它构建在 Matplotlib API 之上,为用户带来了更加定制化的工具。
我们首先定义 Cartopy 坐标参考系统 (CCRS) 对象。这些告诉 Cartopy 我们的数据正在使用什么坐标参考系统 (CRS)。
geod = ccrs.Geodetic() proj = ccrs.LambertAzimuthalEqualArea(central_latitude=90.0)我们的数据投影是兰伯特方位角等面积,中心在北极。让我们继续使用我们的新坐标系定义我们的投影和范围来绘制地球的北半球。
在这张地图中,我们俯视北极,左侧为北美,底部为非洲,以供参考。您会注意到我们没有绘制任何数据,这是因为这本质上是我们的新“画布”。 Matplotlib 现在将 EASE-Grid 2.0 坐标视为绘图空间。
如果我们想在这个底图上分层数据,那么我们还需要找到数据的范围。您会注意到,当我们绘制底图时,我们用四个数字定义了范围。这些是边界框左上角和右下角的 x/y 坐标。在这种情况下,-9,000,000–9,000,000 米是 EASE-Grid 2.0 网格中两个 x/y 坐标的完整范围,北极位于点 (0,0)。
我知道我的研究区域左上角坐标是[-145, 66],右下角坐标是[-165, 72]。这些是以度为单位的大地坐标,可以使用前面定义的 Cartopy 对象转换为米 - 由 EASE-Grid 2.0 使用。
您会注意到我们将源坐标参考系设置为 geod ,这是另一个 CCRS 对象,指示使用度数、纬度和经度的大地测量 CRS。我们使用 Lambert 变换坐标方位角等面积 CCRS 对象,因为那是我们的目标投影。
现在我们在适当的 CRS 中有我们的新边界坐标,我们可以继续绘制我们的研究区域:
好的!现在我们将数据叠加到地图上,我们可以使用海岸线来验证我们是否使用正确的投影和方向进行了正确的操作。我最初将 SWE 数据颠倒绘制,因为它与底图具有不同的“原点”,因此如果出现问题,请不要害怕调整方向。
这张地图虽然缩小了一点。很难非常清楚地看到 SWE 数据。我们可以通过调整底图的范围来放大:
ease_extent = [-3000000., 1000000., -1000000., 3000000.]
Cartopy 为 Matplotlib 带来了强大的功能,支持大量预测。
Matplotlib 动图
我们发现使用 Matplotlib 显示连续变化非常困难。我们可以制作子图来显示离散的变化,但是如果不使用动态绘图工具,显示变化是具有挑战性的。对此的一种解决方案是使用动画。制作随时间变化的情节的电影或 gif 并不难,这对于可视化地理空间数据的变化非常有用!让我们尝试为使用 plt.imshow() 绘制 SWE 数据的原始图设置动画。
制作动画真的很容易!关键是我们有一些迭代绘图的方法。在这种情况下,我只需遍历时间序列的 1000 天并保存每个图的快照,然后将其转换为 gif。所以我们首先创建一个 Matplotlib 图形, fig ,我们将它传递给 Camera() 实例化器。现在,每次我们迭代创建一个新图时,我们只需使用 camera.snap() 拍摄当前 Matplotlib 图的快照。
有多种方法可以创建动画 Matplotlib 图。大多数示例可能会使用内置的 Matplotlib.animation 模块。通常,该模块运行良好,但是,有时会遇到了无法在 Windows 10 上导出动画的依赖性问题。 Matplotlib 的动画模块也无法导出为 GIF。
为了避免依赖性问题并直接导出为 GIF,我们可以使用一个名为 celluloid 的库。 Celluloid 是一个轻量级的库,用于从现有的绘图中创建动画。它的开发并不十分活跃,但如果您对内置的 Matplotlib 功能有疑问,我建议您尝试一下。我喜欢它可以很容易地添加到现有图的顶部,而无需对任何功能进行最少的返工。
基本上任何绘制在 Matplotlib 图形上的东西都可以动画化。所以我们也可以在地图上为我们的 SWE 图像制作动画!
我认为这些动画情节非常有趣。能够看到值在陆地和海洋上的变化以及相应的日期确实有助于显示积累和融化的年度周期。我们还可以以各种方式聚合数据,然后对这些聚合进行动画处理。
结语
虽然有时感觉在Python中有比Matplotlib更好的绘图选择,但它仍然是最可靠和最有效的绘图工具之一。Matplotlib做了一个伟大的工作,为我们提供了一个画布,可以定制我们的每一个愿望。如果您需要为演示文稿、论文或文章绘制图,那么Matplotlib的可定制性是无可争议的。
除非您需要交互式地图,否则您可能会发现自己在某些时候使用Matplotlib来在Python中可视化地理空间数据更加方便。幸运的是,像Cartopy这样的库让Matplotlib能够处理各种地理空间数据。