2017-05-15 19 views
1

グローバルエアロゾル光学深度(AOD)をプロットしようとしていますが、値は通常約0.2ですが、一部の地域では1.2以上になることがあります。理想的には、小さな値の詳細を失うことなく、これらの高い値をプロットしたいと思います。対数スケールのカラーバーはどちらか本当に適切ではないので、私はdocsで説明したように2つの線形範囲を使用しようとしました:私はCartopyとpcolormeshプロットを実行しようとするとき再標準化されたカラーバーを使用したCartopyのpcolormesh

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 

これは壊れます。ギャラリー例の1つあたりのダミーデータの作成:

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() 

はOKに見えた、私はこれを与える:

しかし、pcolormesh相当を使用した場合は動作するようには思えない、それが不鮮明セットを持っています

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

broken pcolormesh plot

:代わり輪郭プロットに見られる波状パターンの0度と180度の経度(プロットの右半分)の間の値の

この作業はどのようにしてpcolormeshにすることができますか?私はCartopyの投影/変換に何か問題があったときにこれを見るのが普通です。これはおそらく、Cartopyがdatelineや、単純なmatplotlibの例で無視されるエッジケースの1つを囲む方法と関係していますが、それを出す。

これは、カスタム正規化インスタンスを使用している場合にのみ発生することに注意してください。それがなければ、pcolormeshも期待通りに動作します。

+0

を生成等高線プロットに見られる波状のパターンではなく、経度0度から180度の間の値の私は通常、Cartopy投影/変換で何か問題があったときにこれを見ています... –

+0

OK、ありがとう。私は、それをもっと明確にしようとする問題を編集しました。 0-180度の経度はプロットの右半分で、左半分と対称でなければなりません(等高線プロットがあります)。 –

+0

はい、MidpointNormalizeを使用してカラースケールを標準化するときのみです。はい、そうでしょう...! –

答えて

2

正規化クラス内のマスキングと関係があるようです。 ので、ここで働いているバージョンです。

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 

完全なコード:pcolormesh例(2番目のプロット)が不鮮明セットを持ってい@ImportanceOfBeingErnest

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() 

enter image description here

関連する問題