2013-04-24 9 views
11

Mam mapę 2D transformacji współrzędnych. Dane w każdym punkcie to kąt osiowy w oryginalnym układzie współrzędnych, który wynosi od 0 do 360. Próbuję użyć pyplot.contour do wykreślania linii o stałym kącie, np. 45 stopni. Kontur pojawia się wzdłuż 45-stopniowej linii między dwoma biegunami, ale jest dodatkowa część konturu, która łączy dwa bieguny wzdłuż nieciągłości 0/360. To sprawia, że ​​linia jest bardzo nierówna, ponieważ po prostu śledzi piksele z liczbą bliską 0 po jednej stronie i liczbą bliską 360 po drugiej.Zatrzymaj plik pyplot.contour przed rysowaniem konturu wzdłuż nieciągłości

Przykłady: Oto pełny obraz używając mapy kolorów: colour map with discontinuity

Widać nieciągłość wzdłuż niebieski/czerwony krzywej po lewej stronie. Jedna strona ma 360 stopni, a druga 0 stopni. Podczas kreślenia konturów, otrzymuję:

contour plot with discontinuity

pamiętać, że wszystkie kontury połączyć dwa bieguny, ale nawet jeśli nie zostały wykreślone kontur 0 stopni, wszystkie inne kontury podążać wzdłuż nieciągłości 0 stopni (bo pyplot myśli, że jeśli jest 0 po jednej stronie i 360 po drugiej, muszą być wszystkie inne kąty pomiędzy).

Kod produkować te dane:

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 

Jak mogę albo:

  1. przystanek pyplot.contour z rysując kontur wzdłuż nieciągłości

  2. rozpoznać markę pyplot.contour że nieciągłość 0/360 pod kątem nie jest wcale rzeczywistą nieciągłością.

mogę tylko zwiększyć rozdzielczość danych bazowych, ale zanim dostanę gładką linię zaczyna się zająć bardzo dużo czasu i dużo pamięci do działki.

Będę również chciał wykreślić kontur wzdłuż 0 stopni, ale jeśli uda mi się znaleźć sposób na ukrycie nieciągłości, mogę go przesunąć w inne miejsce, nie w pobliżu konturu. Lub, jeśli mogę zrobić # 2, nie będzie to problemem.

+2

Pomoże Ci to opublikować obraz wykresu problemu lub przykładowy kod w celu utworzenia (uproszczonej) wersji. – askewchan

+0

Właśnie dodałem przykładowe wykresy ilustrujące problem. – GJP

+1

To dziwne użycie konturów i nie sądzę, że będziesz w stanie sprawić, że będzie działał tak, jak chcesz. Jestem jednak pewien, że można uzyskać działkę, którą chcesz, używając czegoś innego niż kontur. Użycie 'imshow' da ci coś w rodzaju twojej głównej fabuły, a' streamplot' da ci coś bliskiego twojej dolnej fabule. Która z fabuł jest bliższa temu, czego ostatecznie chcesz? Czy możesz podać funkcję, która tworzy pole danych, więc mamy coś do zabawy? – Paul

Odpowiedz

1

Jest to z pewnością nadal hack, ale można uzyskać ładne gładkie kontury w dwojaki sposób:

  1. Działka kontury wartości bezwzględnej fazy (idąc od -180˚ do 180) tak, że nie ma żadnej nieciągłości.
  2. Działka dwa zestawy konturów w regionie skończonej tak że wady numeryczne blisko szczyty i dna z ekstremów nie pełzanie w

Oto kompletny kod, aby dołączyć do np.

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

można uogólnić ten kod, aby uzyskać gładkie kontury dla dowolnej funkcji „okresowych”.Pozostaje do zrobienia, aby wygenerować nowy zestaw konturów z poprawnymi wartościami, tak aby mapy kolorów były poprawnie stosowane, etykiety będą poprawnie stosowane itd. Jednak nie wydaje się, żeby to było proste z matplotlib: odpowiednia klasa QuadContourSet robi wszystko i nie widzę prostego sposobu konstruowania odpowiedniego obiektu konturu z konturów c1 i c2.

Powiązane problemy