How to make the angles in a matplotlib polar plot go clockwise with 0° at the top?


Question

I am using matplotlib and numpy to make a polar plot. Here is some sample code:

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()

You will notice that 0° is at 3 o'clock on the plot, and the angles go counterclockwise. It would be more useful for my data visualization purposes to have 0° at 12 o'clock and have the angles go clockwise. Is there any way to do this besides rotating the data and manually changing the axis labels?

1
29
3/10/2010 2:53:13 PM

Accepted Answer

I found it out -- matplotlib allows you to create custom projections. I created one that inherits from 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()
20
7/14/2011 2:24:10 PM

Updating this question, in Matplotlib 1.1, there are now two methods in PolarAxes for setting the theta direction (CW/CCW) and location for theta=0.

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

Specifically, see set_theta_direction() and set_theta_offset().

Lots of people attempting to do compass-like plots it seems.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon