2013-04-24 41 views
11

Tôi có bản đồ 2d của phép biến đổi tọa độ. Dữ liệu tại mỗi điểm là góc xấp xỉ trong hệ tọa độ gốc, từ 0 đến 360. Tôi đang cố gắng sử dụng pyplot.contour để vẽ các đường của góc không đổi, ví dụ: 45 độ. Đường bao xuất hiện dọc theo đường 45 độ giữa hai cực, nhưng có một phần bổ sung cho đường bao nối hai cực cùng với sự gián đoạn 0/360. Điều này làm cho một dòng rất xấu xí răng cưa vì nó về cơ bản chỉ là dấu vết các điểm ảnh với một số gần 0 ở một bên và một gần với 360 trên khác.Dừng pyplot.contour từ vẽ đường bao dọc theo một gián đoạn

Ví dụ: Dưới đây là một hình ảnh sử dụng bản đồ đầy đủ màu: colour map with discontinuity

Bạn có thể thấy sự gián đoạn dọc theo đường cong màu xanh/đỏ ở phía bên trái. Một bên là 360 độ, khác là 0 độ. Khi âm mưu đường nét, tôi nhận được:

contour plot with discontinuity

Lưu ý rằng tất cả các đường nét kết nối hai cực, nhưng mặc dù tôi đã không vẽ đường viền 0 độ, tất cả những đường nét khác theo cùng sự gián đoạn 0 độ (vì pyplot nghĩ rằng nếu nó là 0 ở một bên và 360 ở bên kia, thì phải có tất cả các góc khác ở giữa).

Mã để tạo ra dữ liệu này:

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 

Làm thế nào tôi có thể một trong hai:

  1. dừng pyplot.contour từ cách vẽ một đường viền dọc theo gián đoạn

  2. làm pyplot.contour nhận rằng sự gián đoạn trong góc 0/360 không phải là gián đoạn thực sự chút nào.

Tôi chỉ có thể tăng độ phân giải của dữ liệu cơ bản, nhưng trước khi tôi nhận được một dòng mượt mà, nó bắt đầu mất một thời gian rất dài và rất nhiều bộ nhớ để vẽ.

Tôi cũng sẽ muốn vẽ một đường bao dọc 0 độ, nhưng nếu tôi có thể tìm ra cách ẩn gián đoạn, tôi có thể chuyển nó sang một nơi khác không gần đường bao. Hoặc, nếu tôi có thể làm cho # 2 xảy ra, nó sẽ không là một vấn đề.

+2

Sẽ giúp ích nếu bạn có thể đăng hình ảnh của ô vấn đề hoặc một số mã mẫu để tạo phiên bản (đã được đơn giản hóa). – askewchan

+0

Tôi chỉ thêm các ô mẫu để minh họa vấn đề – GJP

+1

Đây là một cách sử dụng lạ của các đường nét và tôi không nghĩ rằng bạn sẽ có thể làm cho nó hoạt động theo cách bạn muốn. Tuy nhiên, tôi tin rằng bạn có thể nhận được cốt truyện bạn muốn bằng cách sử dụng một thứ gì đó khác ngoài đường viền. Sử dụng 'imshow' sẽ cung cấp cho bạn một cái gì đó giống như âm mưu hàng đầu của bạn và' streamplot' sẽ cho bạn một cái gì đó gần với cốt truyện của bạn. Cốt truyện nào gần hơn với những gì bạn muốn? Bạn có thể cung cấp một chức năng tạo ra trường dữ liệu để chúng tôi có một cái gì đó để chơi với? – Paul

Trả lời

1

này chắc chắn là vẫn còn là một hack, nhưng bạn có thể nhận được đường nét mượt mà đẹp với một cách tiếp cận hai lần:

  1. đường nét Đồ thị của giá trị tuyệt đối của giai đoạn (đi từ -180˚ đến 180˚) để không có gián đoạn.
  2. Lô hai bộ đường nét trong một khu vực hữu hạn để các khuyết tật số gần với đỉnh và đáy của cực trị không leo vào

Đây là mã hoàn chỉnh gắn liền với các ví dụ của bạn:.

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

Người ta có thể khái quát mã này để có được đường nét mượt mà cho bất kỳ chức năng "định kỳ".Những gì còn lại để được thực hiện là tạo ra một tập hợp các đường bao mới với các giá trị chính xác sao cho các bản đồ màu áp dụng chính xác, các nhãn sẽ được áp dụng đúng cách. Tuy nhiên, dường như không phải là cách đơn giản để làm điều này với matplotlib: lớp QuadContourSet có liên quan thực hiện mọi thứ và tôi không thấy cách đơn giản để xây dựng một đối tượng đường bao thích hợp từ các đường viền c1c2.

Các vấn đề liên quan