2013-04-24 3 views
11

Ich habe eine 2D-Karte einer Koordinatentransformation. Die Daten an jedem Punkt sind der Aximutalwinkel im ursprünglichen Koordinatensystem, der von 0 bis 360 reicht. Ich versuche, pyplot.contour zu verwenden, um Linien mit konstantem Winkel, z. 45 Grad. Die Kontur erscheint entlang der 45-Grad-Linie zwischen den beiden Polen, aber es gibt einen zusätzlichen Teil der Kontur, der die zwei Pole entlang der 0/360-Diskontinuität verbindet. Dies macht eine sehr gezackte hässliche Linie, da sie im Grunde nur die Pixel mit einer Zahl nahe 0 auf der einen Seite und einer anderen nahe bei 360 auf der anderen Seite verfolgt.Stop pyplot.contour vom Zeichnen einer Kontur entlang einer Diskontinuität

Beispiele: Hier ist ein Bild voller Farbkarte mit: colour map with discontinuity

Sie die Diskontinuität entlang der blau/rote Kurve auf der linken Seite sehen. Eine Seite ist 360 Grad, die andere ist 0 Grad. Wenn Konturen Plotten, die ich erhalten:

contour plot with discontinuity

Beachten Sie, dass alle Konturen die beiden Pole verbinden, aber auch wenn ich die 0-Grad-Kontur nicht gezeichnet, alle anderen Konturen entlang der 0-Grad-Diskontinuität folgen (weil pyplot denkt, wenn es 0 auf einer Seite und 360 auf der anderen Seite ist, muss es alle anderen Winkel dazwischen geben).

-Code diese Daten zu erzeugen:

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): 
    dgl = np.array(gl) 
    dgb = np.array(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 

Wie kann ich entweder:

  1. Anschlag pyplot.contour von einer Kontur entlang der Diskontinuität Zeichnung

  2. make pyplot.contour erkennen dass die 0/360-Diskontinuität im Winkel überhaupt keine echte Diskontinuität ist.

Ich kann nur die Auflösung der zugrunde liegenden Daten erhöhen, aber bevor ich eine schöne glatte Linie zu bekommen beginnt es eine sehr lange Zeit und sehr viel Speicher auf Grundstück zu nehmen.

Ich möchte auch eine Kontur entlang 0 Grad plotten, aber wenn ich herausfinden kann, wie man die Diskontinuität verstecken kann, kann ich es einfach zu etwas anderem verschieben, nicht in der Nähe einer Kontur. Oder, wenn ich # 2 passieren kann, wird das kein Problem sein.

+2

Es wäre hilfreich, wenn Sie ein Bild des Problemdiagramms oder einen Beispielcode zur Erstellung einer (vereinfachten) Version bereitstellen könnten. – askewchan

+0

Ich habe gerade Beispielplots hinzugefügt, um das Problem zu verdeutlichen – GJP

+1

Dies ist eine seltsame Verwendung von Konturen und ich denke nicht, dass Sie in der Lage sein werden, es so zu machen, wie Sie es wollen. Ich bin jedoch zuversichtlich, dass Sie das gewünschte Plot mit etwas anderem als Kontur erstellen können. Mit 'imshow' erhalten Sie etwas wie Ihre oberste Handlung und' streamplot' gibt Ihnen etwas in der Nähe Ihrer unteren Handlung. Welche Handlung ist näher an dem, was Sie letztendlich wollen? Könnten Sie eine Funktion angeben, die das Datenfeld erzeugt, damit wir etwas zum Spielen haben? – Paul

Antwort

1

Dies ist auf jeden Fall noch ein Hack, aber man kann mit einem zweifachen Ansatz schöner glatte Konturen erhalten:

  1. Plot Konturen des Absolutwertes der Phase (von -180˚ bis 180˚ gehen) damit es keine Diskontinuität gibt.
  2. Plot zwei Sätze von Konturen in einem endlichen Bereich, so dass numerische Defekte nahe das Hoch und Tiefs der Extrema kriechen nicht in

Dies ist der komplette Code zu Ihrem Beispiel anzufügen:.

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) 

Smooth contour plot of phase angle

Man kann diesen Code verallgemeinern für jede „periodische“ Funktion glatte Konturen zu erhalten.Was zu tun ist, ist eine neue Reihe von Konturen mit den korrekten Werten zu erstellen, so dass Colormaps korrekt angewendet werden, werden Etiketten korrekt usw. angewendet. Es scheint jedoch keine einfache Möglichkeit, dies mit Matplotlib zu tun: die entsprechende Klasse QuadContourSet macht alles und ich sehe keine einfache Möglichkeit, aus den Konturen c1 und c2 ein entsprechendes Konturobjekt zu konstruieren.