13

座標変換の 2 次元マップがあります。各ポイントのデータは、元の座標系の軸角であり、0 から 360 になります。pyplot.contour を使用して、45 度などの一定角度の線をプロットしようとしています。等高線は 2 つの極の間の 45 度の線に沿って表示されますが、等高線には 0/360 の不連続性に沿って 2 つの極を接続する追加の部分があります。これは、基本的に片側に0に近い数値と反対側に360に近い数値を持つピクセルをトレースするだけなので、非常にギザギザの醜い線になります。

例: 以下は、フル カラー マップを使用した画像です。 不連続なカラーマップ

左側の青/赤の曲線に沿って不連続性が見られます。一方は 360 度、もう一方は 0 度です。等高線をプロットすると、次のようになります。

不連続な等高線図

すべての等高線が 2 つの極を接続していることに注意してください。ただし、0 度の等高線をプロットしていませんが、他のすべての等高線は 0 度の不連続に沿って続きます (pyplot は片側が 0 で、反対側が 360 であると考えるため、他のすべての角度はその間にあります)。

このデータを生成するコード:

import numpy as np
import matplotlib.pyplot as plt

jgal = np.array(
    [
        [-0.054875539726, -0.873437108010, -0.483834985808],
        [0.494109453312, -0.444829589425, 0.746982251810],
        [-0.867666135858, -0.198076386122, 0.455983795705],
    ]
)


def s2v3(rra, rdec, r):
    pos0 = r * np.cos(rra) * np.cos(rdec)
    pos1 = r * np.sin(rra) * np.cos(rdec)
    pos2 = r * np.sin(rdec)
    return np.array([pos0, pos1, pos2])


def v2s3(pos):
    x = pos[0]
    y = pos[1]
    z = pos[2]
    if np.isscalar(x):
        x, y, z = np.array([x]), np.array([y]), np.array([z])
    rra = np.arctan2(y, x)
    low = np.where(rra < 0.0)
    high = np.where(rra > 2.0 * np.pi)
    if len(low[0]):
        rra[low] = rra[low] + (2.0 * np.pi)
    if len(high[0]):
        rra[high] = rra[high] - (2.0 * np.pi)
    rxy = np.sqrt(x ** 2 + y ** 2)
    rdec = np.arctan2(z, rxy)
    r = np.sqrt(x ** 2 + y ** 2 + z ** 2)
    if x.size == 1:
        rra = rra[0]
        rdec = rdec[0]
        r = r[0]
    return rra, rdec, r


def gal2fk5(gl, gb):
    rgl = np.deg2rad(gl)
    rgb = np.deg2rad(gb)
    r = 1.0
    pos = s2v3(rgl, rgb, r)

    pos1 = np.dot(pos.transpose(), jgal).transpose()

    rra, rdec, r = v2s3(pos1)

    dra = np.rad2deg(rra)
    ddec = np.rad2deg(rdec)

    return dra, ddec


def make_coords(resolution=50):
    width = 9
    height = 6
    px = width * resolution
    py = height * resolution
    coords = np.zeros((px, py, 4))
    for ix in range(0, px):
        for iy in range(0, py):
            l = 360.0 / px * ix - 180.0
            b = 180.0 / py * iy - 90.0
            dra, ddec = gal2fk5(l, b)
            coords[ix, iy, 0] = dra
            coords[ix, iy, 1] = ddec
            coords[ix, iy, 2] = l
            coords[ix, iy, 3] = b
    return coords


coords = make_coords()

# now do one of these
# plt.imshow(coords[:,:,0],origin='lower') # color plot
plt.contour(
    coords[:, :, 0], levels=[45, 90, 135, 180, 225, 270, 315]
)  # contour plot with jagged ugliness

plt.show()

どうすればよいですか:

  1. pyplot.contour が不連続に沿って輪郭を描くのを止める

  2. pyplot.contour に、角度の 0/360 の不連続が実際の不連続ではないことを認識させます。

基礎となるデータの解像度を上げることはできますが、きれいな滑らかな線が得られるまでには、プロットに非常に長い時間と大量のメモリが必要になります。

また、0 度に沿って等高線をプロットしたいと思いますが、不連続性を非表示にする方法がわかれば、等高線の近くではない別の場所に移動することができます。または、2.が実現できれば問題ありません。

4

2 に答える 2

1

これは間違いなくハックですが、次の 2 つの方法で滑らかな輪郭を得ることができます。

  1. 不連続がないように、位相の絶対値 (-180° から 180° まで) の等高線をプロットします。
  2. 有限領域に 2 セットの等高線をプロットして、極値の上部と下部に近い数値的な欠陥が入り込まないようにします。

例に追加する完全なコードは次のとおりです。

Z = np.exp(1j*np.pi*coords[:,:,0]/180.0)
Z *= np.exp(0.25j*np.pi/2.0)   # Shift to get same contours as in your example
X = np.arange(300)
Y = np.arange(450)

N = 2
levels = 90*(0.5 + (np.arange(N) + 0.5)/N)
c1 = plt.contour(X, Y, abs(np.angle(Z)*180/np.pi), levels=levels)
c2 = plt.contour(X, Y, abs(np.angle(Z*np.exp(0.5j*np.pi))*180/np.pi), levels=levels)

位相角の滑らかな等高線図

このコードを一般化して、「周期的な」関数の滑らかな輪郭を得ることができます。やらなければならないことは、カラーマップが正しく適用され、ラベルが正しく適用されるなど、正しい値で等高線の新しいセットを生成することです。ただし、matplotlib でこれを行う簡単な方法はないようです:クラスはすべてを行いますが、輪郭とQuadContourSetから適切な輪郭オブジェクトを構築する簡単な方法がわかりません。c1c2

于 2013-06-12T08:48:45.017 に答える