2

私は matplotlib.plt.contourf で使用されるマスクされた配列を持っており、グローバルマップに温度等高線を投影しています。私は輪郭を滑らかにしようとしていましたが、残念ながら、提案されたソリューションのどれもマスクされた配列を処理できないようです。これらのソリューションをテストしました:

- scipy.ndimage.gaussian_filter - 移動平均

  • scipy.ndimage.zoom

それらのどれも機能しません(マスクされた値もカウントされます)。maskedArray で輪郭を滑らかにする方法はありますか


提案された「修復」ソリューションを試した後にこの部分を追加しましたが、結果は変わりませんでした。これがコードです(役立つ場合)

import Scientific.IO.NetCDF as S
import mpl_toolkits.basemap as bm
import numpy.ma as MA
import numpy as np
import matplotlib.pyplot as plt
import inpaint

def main():

    fileobj = S.NetCDFFile('Bias.ANN.tas_A1_1.nc', mode='r')

    # take the values
    set1 = {'time', 'lat', 'lon'}
    set2 = set(fileobj.variables.keys())
    set3 = set2 - set1
    datadim = set3.pop()
    print "******************datadim: "+datadim
    data = fileobj.variables[datadim].getValue()[0,:,:]


    lon = fileobj.variables['lon'].getValue()
    lat = fileobj.variables['lat'].getValue()
    fileobj.close()


    data, lon = bm.shiftgrid(180.,data, lon,start=False)
    data = MA.masked_equal(data, 1.0e20)
    #data2 = inpaint.replace_nans(data, 10, 0.25, 2, 'idw')
    #- Make 2-D longitude and latitude arrays:

    [lon2d, lat2d] =np.meshgrid(lon, lat)


    #- Set up map:

    mapproj = bm.Basemap(projection='cyl', 
                       llcrnrlat=-90.0, llcrnrlon=-180.00,
                       urcrnrlat=90.0, urcrnrlon=180.0)
    mapproj.drawcoastlines(linewidth=.5)
    mapproj.drawmapboundary(fill_color='.8')
    #mapproj.drawparallels(N.array([-90, -45, 0, 45, 90]), labels=[1,0,0,0])
    #mapproj.drawmeridians(N.array([0, 90, 180, 270, 360]), labels=[0,0,0,1])
    lonall, latall = mapproj(lon2d, lat2d)

    cmap=plt.cm.Spectral
    #- Make a contour plot of the temperature:
    mymapf = plt.contourf(lonall, latall, data, 20, cmap=cmap)
    #plt.clabel(mymapf, fontsize=12)
    plt.title(cmap.name)
    plt.colorbar(mymapf, orientation='horizontal')

    plt.savefig('sample2.png', dpi=150, edgecolor='red', format='png', bbox_inches='tight', pad_inches=.2)
    plt.close()
if __name__ == "__main__":
  main()

このコードからの出力 (最初の図) と Panoply からの同じデータファイルの出力を比較しています。ズームインしてより正確に見ると、滑らかさの問題ではないように見えますが、pyplot モデルは 1 つのストライプをよりスリムにするか、輪郭が早くカットされます (外側の境界はこれを明確に示し、内側の輪郭はこの事実のために異なります)。pyplot モデルは Panoply モデルほど滑らかではないように見えます。(ほぼ) 同じモデルを取得するにはどうすればよいですか? 私はそれを正しく区別していますか?

pyplo の結果

PanoPly の結果

4

3 に答える 3

3

マスクされたデータで機能する単純な平滑化関数がこれを解決します。これにより、データの作成を伴うアプローチ (つまり、補間、修復など) を回避できます。また、データの作成は常に避ける必要があります。

マスクされたデータをスムージングするときに発生する主な問題は、スムージングが各ポイントに対して隣接する値を使用して中心点の新しい値を計算することですが、これらの隣接するデータがマスクされると、中心点の新しい値もマスクされます。マスクされた配列の規則。したがって、マスクされていないデータを使用して計算を行い、マスクを明示的に説明する必要があります。これは簡単に実行できますが、以下の関数にはありませんsmooth

from numpy import *
import pylab as plt

#  make a grid and a striped mask as test data
N = 100
x = linspace(0, 5, N, endpoint=True)
grid = 2. + 1.*(sin(2*pi*x)[:,newaxis]*sin(2*pi*x)>0.)
m = resize((sin(pi*x)>0), (N,N))

plt.imshow(grid.copy(), cmap='jet', interpolation='nearest')
plt.colorbar()
plt.title('original data')


def smooth(u, mask):
    m = ~mask
    r = u*m  # set all 'masked' points to 0. so they aren't used in the smoothing
    a = 4*r[1:-1,1:-1] + r[2:,1:-1] + r[:-2,1:-1] + r[1:-1,2:] + r[1:-1,:-2]
    b = 4*m[1:-1,1:-1] + m[2:,1:-1] + m[:-2,1:-1] + m[1:-1,2:] + m[1:-1,:-2]  # a divisor that accounts for masked points
    b[b==0] = 1.  # for avoiding divide by 0 error (region is masked so value doesn't matter)
    u[1:-1,1:-1] = a/b

# run the data through the smoothing filter a few times
for i in range(10):   
    smooth(grid, m)

mg = ma.array(grid, mask=m)  # put together the mask and the data

plt.figure()
plt.imshow(mg, cmap='jet', interpolation='nearest')
plt.colorbar()
plt.title('smoothed with mask')

plt.show()

ここに画像の説明を入力 ここに画像の説明を入力

要点は、マスクの境界では、マスクされた値がスムージングに使用されないことです。(これは、グリッドの正方形が値を切り替える場所でもあるため、マスクされた隣接する値が使用されているかどうかは図で明らかです。)

于 2013-06-18T17:27:18.210 に答える