2011-10-05 3 views
10

Come posso creare un grafico in senso orario? Qualcuno fa una domanda simile here: How to make the angles in a matplotlib polar plot go clockwise with 0° at the top?
Ma non lo capisco.Python: trama polare oraria

import matplotlib.pyplot as plt 
import numpy as np 

fig = plt.figure() 
ax = fig.add_subplot(111, polar=True) 
ax.grid(True) 

theta = np.arange(0,370,10) 
theta = [i*np.pi/180.0 for i in theta] # convert to radians 

x = [3.00001,3,3,3,3,3,3,3,3,3,3,3,3,3,2.5,2,2,2,2,2,1.5,1.5,1,1.5,2,2,2.5,2.5,3,3,3,3,3,3,3,3,3] 
ax.plot(theta, x) 
plt.show() 

EDIT:

import matplotlib.pyplot as plt 
import numpy as np 
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 = np.zeros(tr.shape, np.float_) 
      t = tr[:, 0:1] 
      r = tr[:, 1:2] 
      x = xy[:, 0:1] 
      y = xy[:, 1:2] 
      x[:] = r * np.sin(t) 
      y[:] = r * np.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 = np.sqrt(x*x + y*y) 

fig = plt.figure() 
register_projection(NorthPolarAxes) 
ax=plt.subplot(1, 1, 1, projection='northpolar')  
theta=np.linspace(0,2*np.pi,37) 
x = [3.00001,3,3,3,3,3,3,3,3,3,3,3,3,3,2.5,2,2,2,2, 
    2,1.5,1.5,1,1.5,2,2,2.5,2.5,3,3,3,3,3,3,3,3,3] 
ax.plot(theta, x) 
plt.show() 

Come usare correttamente register_projection (NorthPolarAxes)?

risposta

14

aggiungere queste stringhe:

ax.set_theta_direction(-1) 

ax.set_theta_offset(pi/2.0) 
3

Modifica: Si prega di notare che Pavel ha fornito uno much better solution!


La domanda SO si è collegato al contiene la risposta. Ecco una versione leggermente modificata di ptomato's NorthPolarAxes class con theta=0 puntamento est e in aumento in senso orario:

import matplotlib.pyplot as plt 
import numpy as np 
import matplotlib.projections as projections 
import matplotlib.transforms as mtransforms 

class EastPolarAxes(projections.PolarAxes): 
    ''' 
    A variant of PolarAxes where theta starts pointing East and goes 
    clockwise. 
    https://stackoverflow.com/questions/2417794/2433287#2433287 
    https://stackoverflow.com/questions/7664153/7664545#7664545  
    ''' 
    name = 'eastpolar' 

    class EastPolarTransform(projections.PolarAxes.PolarTransform): 
     """ 
     The base polar transform. This handles projection *theta* and 
     *r* into Cartesian coordinate space *x* and *y*, but does not 
     perform the ultimate affine transformation into the correct 
     position. 
     """   
     def transform(self, tr): 
      xy = np.zeros(tr.shape, np.float_) 
      t = tr[:, 0:1] 
      r = tr[:, 1:2] 
      x = xy[:, 0:1] 
      y = xy[:, 1:2] 
      x[:] = r * np.cos(-t) 
      y[:] = r * np.sin(-t) 
      return xy 

     transform_non_affine = transform 

     def inverted(self): 
      return EastPolarAxes.InvertedEastPolarTransform() 

    class InvertedEastPolarTransform(projections.PolarAxes.InvertedPolarTransform): 
     """ 
     The inverse of the polar transform, mapping Cartesian 
     coordinate space *x* and *y* back to *theta* and *r*. 
     """   
     def transform(self, xy): 
      x = xy[:, 0:1] 
      y = xy[:, 1:] 
      r = np.sqrt(x*x + y*y) 
      theta = npy.arccos(x/r) 
      theta = npy.where(y > 0, 2 * npy.pi - theta, theta) 
      return np.concatenate((theta, r), 1) 

     def inverted(self): 
      return EastPolarAxes.EastPolarTransform() 

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

def eastpolar_axes(): 
    projections.register_projection(EastPolarAxes) 
    ax=plt.subplot(1, 1, 1, projection='eastpolar')  
    theta=np.linspace(0,2*np.pi,37) 
    x = [3.00001,3,3,3,3,3,3,3,3,3,3,3,3,3,2.5,2,2,2,2, 
     2,1.5,1.5,1,1.5,2,2,2.5,2.5,3,3,3,3,3,3,3,3,3] 
    ax.plot(theta, x) 
    plt.show() 

eastpolar_axes() 

enter image description here


Le corde DOC matplotlib/projections/polar.py s' PolarTransform e InvertedPolarTransform sono stati aggiunti perché penso che aiutano a spiegare che cosa ogni componente sta facendo. Questo ti guida nel cambiare le formule.

Per ottenere un comportamento in senso orario, è sufficiente modificare t ->-t:

 x[:] = r * np.cos(-t) 
     y[:] = r * np.sin(-t) 

e in InvertedEastPolarTransform, vogliamo usare 2 * npy.pi - theta quando y > 0 (la parte superiore del mezzo aereo), invece di quando y < 0.

+0

La risposta data da Pavel funziona ed è molto più semplice. –

+0

@PabloReyes: Grazie per avermi informato. – unutbu

7

ax.set_theta_direction(-1) ax.set_theta_direction('N')

è leggermente più comprensibile.