簡體   English   中英

Cartopy pcolormesh,帶有重新標准化的顏色條

[英]Cartopy pcolormesh with re-normalized colorbar

我正在嘗試繪制全局氣溶膠光學深度(AOD),該值通常在0.2左右,但在某些地區可以達到1.2或更大。 理想情況下,我想繪制這些較高的值,而又不丟失較小值的細節。 對數刻度顏色條也不是很合適,因此我嘗試使用兩個線性范圍,如docs中所述:

import matplotlib.pyplot as plt
import matplotlib.colors as colors
import numpy as np
import cartopy.crs as ccrs


class MidpointNormalize(colors.Normalize):
    def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
        self.midpoint = midpoint
        colors.Normalize.__init__(self, vmin, vmax, clip)

    def __call__(self, value, clip=None):
        # I'm ignoring masked values and all kinds of edge cases to make a
        # simple example...
        x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
        res = np.ma.masked_array(np.interp(value, x, y))
        return res

但是,當我嘗試使用Cartopy繪制pcolormesh圖時,這種方法會中斷。 根據圖庫示例之一創建虛擬數據:

def sample_data(shape=(73, 145)):
    """Returns ``lons``, ``lats`` and ``data`` of some fake data."""
    nlats, nlons = shape
    lats = np.linspace(-np.pi / 2, np.pi / 2, nlats)
    lons = np.linspace(0, 2 * np.pi, nlons)
    lons, lats = np.meshgrid(lons, lats)
    wave = 0.75 * (np.sin(2 * lats) ** 8) * np.cos(4 * lons)
    mean = 0.5 * np.cos(2 * lats) * ((np.sin(2 * lats)) ** 2 + 2)

    lats = np.rad2deg(lats)
    lons = np.rad2deg(lons)
    data = wave + mean

    return lons, lats, data


ax = plt.axes(projection=ccrs.Mollweide())
lons, lats, data = sample_data()
ax.contourf(lons, lats, data,
            transform=ccrs.PlateCarree(),
            cmap='spectral', norm=MidpointNormalize(midpoint=0.8))
ax.coastlines()
ax.set_global()
plt.show()

給我這個,看起來不錯: 工作輪廓圖

但是,當使用pcolormesh等效項似乎無效時,它會在0到180度的經度(圖的右半)之間塗抹一組值,而不是在等高線圖中看到的波紋圖案:

ax.pcolormesh(lons, lats, data, 
            transform=ccrs.PlateCarree(),
            cmap='spectral', norm=MidpointNormalize(midpoint=0.8))

破碎的pcolormesh圖

我該如何使它適用於pcolormesh? 當我對Cartopy投影/變換做錯了一些事情時,我通常會看到這種情況,因此大概這與Cartopy繞日期線包裹的方式或簡單的matplotlib示例忽略的邊緣情況之一有關,但我無法弄清楚出來。

請注意,只有在使用自定義Normalization實例時才會發生這種情況。 沒有它,pcolormesh也會按預期工作。

似乎與規范化類內部的屏蔽有關。 所以這是一個有效的版本:

class MidpointNormalize(colors.Normalize):
    def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
        self.midpoint = midpoint
        colors.Normalize.__init__(self, vmin, vmax, clip)

    def __call__(self, value, clip=None):
        result, is_scalar = self.process_value(value)
        (vmin,), _ = self.process_value(self.vmin)
        (vmax,), _ = self.process_value(self.vmax)
        resdat = np.asarray(result.data)
        result = np.ma.array(resdat, mask=result.mask, copy=False)
        x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
        res = np.interp(result, x, y)
        result = np.ma.array(res, mask=result.mask, copy=False)
        if is_scalar:
            result = result[0]
        return result

完整的代碼:

import matplotlib.pyplot as plt
import matplotlib.colors as colors
import numpy as np
import cartopy.crs as ccrs

class MidpointNormalize(colors.Normalize):
    def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
        self.midpoint = midpoint
        colors.Normalize.__init__(self, vmin, vmax, clip)

    def __call__(self, value, clip=None):
        result, is_scalar = self.process_value(value)
        (vmin,), _ = self.process_value(self.vmin)
        (vmax,), _ = self.process_value(self.vmax)
        resdat = np.asarray(result.data)
        result = np.ma.array(resdat, mask=result.mask, copy=False)
        x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
        res = np.interp(result, x, y)
        result = np.ma.array(res, mask=result.mask, copy=False)
        if is_scalar:
            result = result[0]
        return result

def sample_data(shape=(73, 145)):
    """Returns ``lons``, ``lats`` and ``data`` of some fake data."""
    nlats, nlons = shape
    lats = np.linspace(-np.pi / 2, np.pi / 2, nlats)
    lons = np.linspace(0, 2 * np.pi, nlons)
    lons, lats = np.meshgrid(lons, lats)
    wave = 0.75 * (np.sin(2 * lats) ** 8) * np.cos(4 * lons)
    mean = 0.5 * np.cos(2 * lats) * ((np.sin(2 * lats)) ** 2 + 2)

    lats = np.rad2deg(lats)
    lons = np.rad2deg(lons)
    data = wave + mean

    return lons, lats, data


ax = plt.axes(projection=ccrs.Mollweide())
lons, lats, data = sample_data()

norm = norm=MidpointNormalize(midpoint=0.8)
cm = ax.pcolormesh(lons, lats, data, 
            transform=ccrs.PlateCarree(),
            cmap='spectral', norm=norm )

ax.coastlines()
plt.colorbar(cm, orientation="horizontal")
ax.set_global()
plt.show()

產生

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM