2010-03-10 17 views
26

Tôi đang sử dụng matplotlib và numpy để tạo ra một âm mưu cực. Đây là một số mã mẫu:Làm thế nào để làm cho các góc trong một âm mưu cực matplotlib đi theo chiều kim đồng hồ với 0 ° ở đầu?

import numpy as N 
import matplotlib.pyplot as P 

angle = N.arange(0, 360, 10, dtype=float) * N.pi/180.0 
arbitrary_data = N.abs(N.sin(angle)) + 0.1 * (N.random.random_sample(size=angle.shape) - 0.5) 

P.clf() 
P.polar(angle, arbitrary_data) 
P.show() 

Bạn sẽ nhận thấy rằng 0 ° là lúc 3 giờ trên cốt truyện và các góc quay ngược chiều kim đồng hồ. Nó sẽ hữu ích hơn cho các mục đích trực quan hóa dữ liệu của tôi để có 0 ° lúc 12 giờ và có các góc đi theo chiều kim đồng hồ. Có cách nào để thực hiện việc này bên cạnh việc xoay dữ liệu và thay đổi nhãn trục theo cách thủ công không?

Trả lời

18

Tôi đã tìm thấy nó - matplotlib cho phép bạn tạo các dự báo tùy chỉnh. Tôi đã tạo một tài khoản kế thừa từ PolarAxes.

import numpy as N 
import matplotlib.pyplot as P 

from matplotlib.projections import PolarAxes, register_projection 
from matplotlib.transforms import Affine2D, Bbox, IdentityTransform 

class NorthPolarAxes(PolarAxes): 
    ''' 
    A variant of PolarAxes where theta starts pointing north and goes 
    clockwise. 
    ''' 
    name = 'northpolar' 

    class NorthPolarTransform(PolarAxes.PolarTransform): 
     def transform(self, tr): 
      xy = N.zeros(tr.shape, N.float_) 
      t = tr[:, 0:1] 
      r = tr[:, 1:2] 
      x = xy[:, 0:1] 
      y = xy[:, 1:2] 
      x[:] = r * N.sin(t) 
      y[:] = r * N.cos(t) 
      return xy 

     transform_non_affine = transform 

     def inverted(self): 
      return NorthPolarAxes.InvertedNorthPolarTransform() 

    class InvertedNorthPolarTransform(PolarAxes.InvertedPolarTransform): 
     def transform(self, xy): 
      x = xy[:, 0:1] 
      y = xy[:, 1:] 
      r = N.sqrt(x*x + y*y) 
      theta = N.arctan2(y, x) 
      return N.concatenate((theta, r), 1) 

     def inverted(self): 
      return NorthPolarAxes.NorthPolarTransform() 

    def _set_lim_and_transforms(self): 
     PolarAxes._set_lim_and_transforms(self) 
     self.transProjection = self.NorthPolarTransform() 
     self.transData = (
      self.transScale + 
      self.transProjection + 
      (self.transProjectionAffine + self.transAxes)) 
     self._xaxis_transform = (
      self.transProjection + 
      self.PolarAffine(IdentityTransform(), Bbox.unit()) + 
      self.transAxes) 
     self._xaxis_text1_transform = (
      self._theta_label1_position + 
      self._xaxis_transform) 
     self._yaxis_transform = (
      Affine2D().scale(N.pi * 2.0, 1.0) + 
      self.transData) 
     self._yaxis_text1_transform = (
      self._r_label1_position + 
      Affine2D().scale(1.0/360.0, 1.0) + 
      self._yaxis_transform) 

register_projection(NorthPolarAxes) 

angle = N.arange(0, 360, 10, dtype=float) * N.pi/180.0 
arbitrary_data = (N.abs(N.sin(angle)) + 0.1 * 
    (N.random.random_sample(size=angle.shape) - 0.5)) 

P.clf() 
P.subplot(1, 1, 1, projection='northpolar') 
P.plot(angle, arbitrary_data) 
P.show() 
+1

Tuyệt vời, điều này nên được bao gồm với các ví dụ chiếu tùy chỉnh của chúng. – Mark

+1

Tôi khuyên bạn nên kết hợp nó vào trong codebase. –

+0

Bất kỳ ý tưởng làm thế nào để có được điều này làm việc với FigureCanvasGTKAgg? – Sardathrion

4

Bạn có thể sửa đổi matplotlib/projections/polar.py của mình.

đâu nó nói:

def transform(self, tr): 
     xy = npy.zeros(tr.shape, npy.float_) 
     t = tr[:, 0:1] 
     r = tr[:, 1:2] 
     x = xy[:, 0:1] 
     y = xy[:, 1:2] 
     x[:] = r * npy.cos(t) 
     y[:] = r * npy.sin(t) 
     return xy 

Làm cho nó nói:

def transform(self, tr): 
     xy = npy.zeros(tr.shape, npy.float_) 
     t = tr[:, 0:1] 
     r = tr[:, 1:2] 
     x = xy[:, 0:1] 
     y = xy[:, 1:2] 
     x[:] = - r * npy.sin(t) 
     y[:] = r * npy.cos(t) 
     return xy 

Tôi không thực sự thử nó, bạn có thể cần phải tinh chỉnh x [:] và y [:] bài tập để khẩu vị của bạn. Thay đổi này sẽ ảnh hưởng đến tất cả các chương trình sử dụng âm mưu cực matplotlib.

+0

Đây là khéo léo, nhưng vá mã là loại gian lận, không phải là nó? Tuy nhiên, bạn đã cho tôi một ý tưởng. Matplotlib cho phép bạn tạo các trục với bất kỳ loại chuyển đổi nào; có lẽ tôi có thể viết một hàm polar() thay thế với biến đổi mà tôi đang tìm kiếm. – ptomato

2

Cả thói quen nghịch nên sử dụng đầy đủ đường dẫn đến biến đổi:

return NorthPolarAxes.InvertedNorthPolarTransform() 

return NorthPolarAxes.NorthPolarTransform() 

Bây giờ, lớp con tự động tạo ra của NorthPolarAxes như NorthPolarAxesSubplot có thể truy cập các biến đổi chức năng.

Hy vọng điều này sẽ hữu ích.

28

Cập nhật câu hỏi này, trong Matplotlib 1.1, hiện có hai phương pháp trong PolarAxes để đặt hướng theta (CW/CCW) và vị trí cho theta = 0.

Check-out http://matplotlib.sourceforge.net/devel/add_new_projection.html#matplotlib.projections.polar.PolarAxes

Cụ thể, xem set_theta_direction()set_theta_offset().

Có vẻ như rất nhiều người cố gắng làm các ô giống như la bàn.

+1

Nếu bạn có trục cực * ax *: ** ax.set_theta_offset (0,5 * numpy.pi) ** – zinjaai

14

Để mở rộng câu trả lời klimaat với một ví dụ:

import math 
angle=[0.,5.,10.,15.,20.,25.,30.,35.,40.,45.,50.,55.,60.,65.,70.,75.,\ 
     80.,85.,90.,95.,100.,105.,110.,115.,120.,125.] 

angle = [math.radians(a) for a in angle] 


lux=[12.67,12.97,12.49,14.58,12.46,12.59,11.26,10.71,17.74,25.95,\ 
    15.07,7.43,6.30,6.39,7.70,9.19,11.30,13.30,14.07,15.92,14.70,\ 
    10.70,6.27,2.69,1.29,0.81] 

import matplotlib.pyplot as P 
import matplotlib 
P.clf() 
sp = P.subplot(1, 1, 1, projection='polar') 
sp.set_theta_zero_location('N') 
sp.set_theta_direction(-1) 
P.plot(angle, lux) 
P.show() 
Các vấn đề liên quan