繁体   English   中英

更改 Matplotlib 中的颜色条缩放

[英]Change Colorbar Scaling in Matplotlib

使用 NASA 的 SRTM 数据,我生成了一个全球海拔热图。

全球海拔热图

然而,问题是,由于海拔值的范围,大陆往往会与海洋融为一体。 是否可以更改颜色条的比例,使大陆的边缘与海洋更加不同? 我尝试了不同的 cmap,但它们似乎都遇到了这个问题。

这是我的代码。 我正在初始化一个巨大的数组(带有 0)来保存全局高程数据,然后从 SRTM 数据集中逐个文件填充它。 每个文件是 1 度纬度乘 1 度经度。

我遇到的另一个问题是关于 map 本身。 由于某种原因,阿巴拉契亚山脉似乎已经完全消失了。

import os
import numpy as np
from .srtm_map import MapGenerator
from ..utils.hgt_parser import HGTParser
from tqdm import tqdm
import cv2
import matplotlib.pyplot as plt
import richdem as rd

class GlobalMapGenerator():
    def __init__(self):
        self.gen = MapGenerator()
        self.base_dir = "data/elevation/"
        self.hgt_files = os.listdir(self.base_dir)
        self.global_elevation_data = None
    
    def shrink(data, rows, cols):
        return data.reshape(rows, data.shape[0]/rows, cols, data.shape[1]/cols).sum(axis=1).sum(axis=2)

    def GenerateGlobalElevationMap(self, stride):
        res = 1201//stride
        max_N = 59
        max_W = 180
        max_S = 56
        max_E = 179
        
        # N59 --> N00
        # S01 --> S56
        # E000 --> E179
        # W180 --> W001
        
        # Initialize array global elevation
        self.global_elevation_data = np.zeros(( res*(max_S+max_N+1), res*(max_E+max_W+1) ))

        print("Output Image Shape:", self.global_elevation_data.shape)

        for hgt_file in tqdm(self.hgt_files):
            lat_letter = hgt_file[0]
            lon_letter = hgt_file[3]
            lat = int(hgt_file[1:3])
            lon = int(hgt_file[4:7])

            if lat_letter == "S":
                # Shift south down by max_N, but south starts at S01 so we translate up by 1 too
                lat_trans = max_N + lat - 1
            else:
                # Bigger N lat means further up. E.g. N59 is at index 0 and is higher than N00
                lat_trans = max_N - lat
            
            if lon_letter == "E":
                # Shift east right by max_W
                lon_trans = max_W + lon
            else:
                # Bigger W lon means further left. E.g. W180 is at index 0 and is more left than W001
                lon_trans = max_W - lon

            # load in data from file as resized
            data = cv2.resize(HGTParser(os.path.join(self.base_dir, hgt_file)), (res, res))
            
            # generate bounds (x/y --> lon.lat for data from this file for the giant array)
            lat_bounds = [res*lat_trans, res*(lat_trans+1)]
            lon_bounds = [res*lon_trans, res*(lon_trans+1)]
            
            try:
                self.global_elevation_data[ lat_bounds[0]:lat_bounds[1],  lon_bounds[0]:lon_bounds[1] ] = data
            except:
                print("REFERENCE ERROR: " + hgt_file)
                print("lat: ", lat_bounds)
                print("lon: ", lon_bounds)

        # generate figure
        plt.figure(figsize=(20,20))
        plt.imshow(self.global_elevation_data, cmap="rainbow")
        plt.title("Global Elevation Heatmap")
        plt.colorbar()
        plt.show()
        np.save("figures/GlobalElevationMap.npy", self.global_elevation_data)
        plt.savefig("figures/GlobalElevationMap.png")
    
    def GenerateGlobalSlopeMap(self, stride):
        pass

使用TwoSlopeNorm ( docs ) 作为您的标准,就像这里的示例一样。

从例子:

有时我们希望在概念中心点的任一侧都有不同的颜色图,并且我们希望这两个颜色图具有不同的线性比例。 一个示例是地形 map,其中陆地和海洋的中心为零,但陆地的海拔范围通常大于水的深度范围,并且它们通常由不同的颜色图表示。

如果您将中点设置为海平面 (0),那么您可以根据海洋海拔与陆地海拔有两种截然不同的比例。

示例代码(取自上面链接的示例):

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cbook as cbook
from matplotlib import cm

dem = cbook.get_sample_data('topobathy.npz', np_load=True)
topo = dem['topo']
longitude = dem['longitude']
latitude = dem['latitude']

fig, ax = plt.subplots()
# make a colormap that has land and ocean clearly delineated and of the
# same length (256 + 256)
colors_undersea = plt.cm.terrain(np.linspace(0, 0.17, 256))
colors_land = plt.cm.terrain(np.linspace(0.25, 1, 256))
all_colors = np.vstack((colors_undersea, colors_land))
terrain_map = colors.LinearSegmentedColormap.from_list(
    'terrain_map', all_colors)

# make the norm:  Note the center is offset so that the land has more
# dynamic range:
divnorm = colors.TwoSlopeNorm(vmin=-500., vcenter=0, vmax=4000)

pcm = ax.pcolormesh(longitude, latitude, topo, rasterized=True, norm=divnorm,
                    cmap=terrain_map, shading='auto')
# Simple geographic plot, set aspect ratio beecause distance between lines of
# longitude depends on latitude.
ax.set_aspect(1 / np.cos(np.deg2rad(49)))
ax.set_title('TwoSlopeNorm(x)')
cb = fig.colorbar(pcm, shrink=0.6)
cb.set_ticks([-500, 0, 1000, 2000, 3000, 4000])
plt.show()

带有彩色高程的地图图片

看看它如何用这个简单的用法来缩放数字(来自文档):

>>> import matplotlib. Colors as mcolors
>>> offset = mcolors.TwoSlopeNorm(vmin=-4000., vcenter=0., vmax=10000)
>>> data = [-4000., -2000., 0., 2500., 5000., 7500., 10000.]
>>> offset(data)
array([0., 0.25, 0.5, 0.625, 0.75, 0.875, 1.0])

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM