与Matlab的Demcmap等效的Python(高程+/-适当的颜色图) [英] Python equivalent for Matlab's Demcmap (elevation +/- appropriate colormap)

查看:222
本文介绍了与Matlab的Demcmap等效的Python(高程+/-适当的颜色图)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种获取matplotlib合适的高程颜色图的方法.

I am looking for a way to get an elevation appropriate colormap for matplotlib.

cmap'terrain'看起来不错,但是颜色缩放比例不是基于零(即,如果缩放比例为0-> 5000m,则0-> 1000m范围可能是蓝色阴影,您可能会假设是低于海平面)

the cmap 'terrain' looks great but the colorscaling isn't based around zero (i.e. if the scale is 0->5000m, the 0->1000m range may be shades of blue, which you would assume to be for below sea-level)

例如:

Matlab函数的等效项是: demcmap

The Matlab function equivalent is: demcmap

让matplotlib将地形颜色图的绿色/棕色和蓝色移动到零海拔标记附近的最佳方法是什么?

What is the best way to get matplotlib to shift a terrain colormap's greens/browns and blues around the zero elevation mark?

推荐答案

不幸的是,matplotlib不提供Matlab的demcmap功能. python basemap包中实际上可能有一些内置功能,我不知道这些功能.

Unfortunaly, matplotlib does not provide the functionality of Matlab's demcmap. There might actually be some build-in features in the python basemap package, of which I'm not aware.

因此,坚持使用matplotlib板载选项,我们可以将 Normalize 子类化以色图中间的一个点为中心的颜色归一化.可以在StackOverflow上的另一个问题中找到该技术,并针对特定需求进行调整,即设置一个sealevel(最好将其选择为0)和该海平面应对应的色图col_val中的值(介于0和1之间).对于地形图,似乎0.22对应于绿松石色可能是一个不错的选择.
然后可以将Normalize实例作为imshow的参数给出.所产生的图形可以在图片的第一行下方看到.

So, sticking to matplotlib on-board options, we can subclass Normalize to build a color normalization centered around a point in the middle of the colormap. This technique can be found in another question on StackOverflow and adapted to the specific needs, namely to set a sealevel (which is probably best chosen as 0) and the value in the colormap col_val (ranging between 0 and 1) to which this sealevel should correspond. In the case of the terrain map, it seems that 0.22, corresponding to a turqoise color, might be a good choice.
The Normalize instance can then be given as an argument to imshow. The resulting figures can be seen down below in the first row of the picture.

由于围绕海平面的平稳过渡,0附近的值显示为绿松石色,因此很难区分陆地和海洋.
因此,我们可以稍微改变地形图,并剪掉那些颜色,以便更好地看到海岸线.这是通过组合地图的两个部分来完成的,范围从0到0.17,从0.25到0.25. 1,然后剪掉一部分.

Due to the smooth transition around the sealevel the values around 0 appear in a turqoise color, making it hard to distinguish between land and sea.
We can therefore change the terrain map a bit and cut out those colors, such that the coastline is better visible. This is done by combining two parts of the map, ranging from 0 to 0.17 and from 0.25 to 1, and thus cutting out a part of it.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors

class FixPointNormalize(matplotlib.colors.Normalize):
    """ 
    Inspired by https://stackoverflow.com/questions/20144529/shifted-colorbar-matplotlib
    Subclassing Normalize to obtain a colormap with a fixpoint 
    somewhere in the middle of the colormap.

    This may be useful for a `terrain` map, to set the "sea level" 
    to a color in the blue/turquise range. 
    """
    def __init__(self, vmin=None, vmax=None, sealevel=0, col_val = 0.21875, clip=False):
        # sealevel is the fix point of the colormap (in data units)
        self.sealevel = sealevel
        # col_val is the color value in the range [0,1] that should represent the sealevel.
        self.col_val = col_val
        matplotlib.colors.Normalize.__init__(self, vmin, vmax, clip)

    def __call__(self, value, clip=None):
        x, y = [self.vmin, self.sealevel, self.vmax], [0, self.col_val, 1]
        return np.ma.masked_array(np.interp(value, x, y))

# Combine the lower and upper range of the terrain colormap with a gap in the middle
# to let the coastline appear more prominently.
# inspired by https://stackoverflow.com/questions/31051488/combining-two-matplotlib-colormaps
colors_undersea = plt.cm.terrain(np.linspace(0, 0.17, 56))
colors_land = plt.cm.terrain(np.linspace(0.25, 1, 200))
# combine them and build a new colormap
colors = np.vstack((colors_undersea, colors_land))
cut_terrain_map = matplotlib.colors.LinearSegmentedColormap.from_list('cut_terrain', colors)



# invent some data (height in meters relative to sea level)
data = np.linspace(-1000,2400,15**2).reshape((15,15))


# plot example data
fig, ax = plt.subplots(nrows = 2, ncols=3, figsize=(11,6) )
plt.subplots_adjust(left=0.08, right=0.95, bottom=0.05, top=0.92, hspace = 0.28, wspace = 0.15)

plt.figtext(.5, 0.95, "Using 'terrain' and FixedPointNormalize", ha="center", size=14)
norm = FixPointNormalize(sealevel=0, vmax=3400)
im = ax[0,0].imshow(data+1000, norm=norm, cmap=plt.cm.terrain)
fig.colorbar(im, ax=ax[0,0])

norm2 = FixPointNormalize(sealevel=0, vmax=3400)
im2 = ax[0,1].imshow(data, norm=norm2, cmap=plt.cm.terrain)
fig.colorbar(im2, ax=ax[0,1])

norm3 = FixPointNormalize(sealevel=0, vmax=0)
im3 = ax[0,2].imshow(data-2400.1, norm=norm3, cmap=plt.cm.terrain)
fig.colorbar(im3, ax=ax[0,2])

plt.figtext(.5, 0.46, "Using custom cut map and FixedPointNormalize (adding hard edge between land and sea)", ha="center", size=14)
norm4 = FixPointNormalize(sealevel=0, vmax=3400)
im4 = ax[1,0].imshow(data+1000, norm=norm4, cmap=cut_terrain_map)
fig.colorbar(im4, ax=ax[1,0])

norm5 = FixPointNormalize(sealevel=0, vmax=3400)
im5 = ax[1,1].imshow(data, norm=norm5, cmap=cut_terrain_map)
cbar = fig.colorbar(im5, ax=ax[1,1])

norm6 = FixPointNormalize(sealevel=0, vmax=0)
im6 = ax[1,2].imshow(data-2400.1, norm=norm6, cmap=cut_terrain_map)
fig.colorbar(im6, ax=ax[1,2])

for i, name in enumerate(["land only", "coast line", "sea only"]):
    for j in range(2):
        ax[j,i].text(0.96,0.96,name, ha="right", va="top", transform=ax[j,i].transAxes, color="w" )

plt.show()

这篇关于与Matlab的Demcmap等效的Python(高程+/-适当的颜色图)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆