Matplotlib polar plot radial axis offset

Renesis picture Renesis · May 17, 2013 · Viewed 11.7k times · Source

I was wondering, is it possible to offset the start of the radial axis or move it outside of the graph.

This is what I'm hoping to achieve:

Goal

And this is what I have for now.

CurRes

I have read the documentation and different topics on SO, but I couldn't find anything helpful. Does that mean that it is not even possible if it is not mentioned anywhere.

Thank you in advance.

EDIT (added snippet of a code used to create the plot):

ax = fig.add_subplot(111, projection='polar')
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)      
ax.plot(X,lines[li]*yScalingFactor,label=linelabels[li],color=color,linestyle=ls)

Answer

Schorsch picture Schorsch · Jun 4, 2013

I am not sure if the polar plot can be adjusted like that. But here is a work-around, based on the last example given here: Floating Axes.

I have included explanatory comments in the code, if you copy/paste it, it should run as-is:

import mpl_toolkits.axisartist.floating_axes as floating_axes
from matplotlib.projections import PolarAxes
from mpl_toolkits.axisartist.grid_finder import FixedLocator, \
     MaxNLocator, DictFormatter
import numpy as np
import matplotlib.pyplot as plt

# generate 100 random data points
# order the theta coordinates

# theta between 0 and 2*pi
theta = np.random.rand(100)*2.*np.pi
theta = np.sort(theta)

# "radius" between 0 and a max value of 40,000
# as roughly in your example
# normalize the r coordinates and offset by 1 (will be clear later)
MAX_R = 40000.
radius = np.random.rand(100)*MAX_R
radius = radius/np.max(radius) + 1.

# initialize figure:
fig = plt.figure()

# set up polar axis
tr = PolarAxes.PolarTransform()

# define angle ticks around the circumference:
angle_ticks = [(0, r"$0$"),
               (.25*np.pi, r"$\frac{1}{4}\pi$"),
               (.5*np.pi, r"$\frac{1}{2}\pi$"), 
               (.75*np.pi, r"$\frac{3}{4}\pi$"),
               (1.*np.pi, r"$\pi$"),
               (1.25*np.pi, r"$\frac{5}{4}\pi$"),
               (1.5*np.pi, r"$\frac{3}{2}\pi$"),
               (1.75*np.pi, r"$\frac{7}{4}\pi$")]

# set up ticks and spacing around the circle
grid_locator1 = FixedLocator([v for v, s in angle_ticks])
tick_formatter1 = DictFormatter(dict(angle_ticks))

# set up grid spacing along the 'radius'
radius_ticks = [(1., '0.0'),
                (1.5, '%i' % (MAX_R/2.)),
                (2.0, '%i' % (MAX_R))]

grid_locator2 = FixedLocator([v for v, s in radius_ticks])
tick_formatter2 = DictFormatter(dict(radius_ticks))

# set up axis:
# tr: the polar axis setup
# extremes: theta max, theta min, r max, r min
# the grid for the theta axis
# the grid for the r axis
# the tick formatting for the theta axis
# the tick formatting for the r axis
grid_helper = floating_axes.GridHelperCurveLinear(tr,
                                                  extremes=(2.*np.pi, 0, 2, 1),
                                                  grid_locator1=grid_locator1,
                                                  grid_locator2=grid_locator2,
                                                  tick_formatter1=tick_formatter1,
                                                  tick_formatter2=tick_formatter2)

ax1 = floating_axes.FloatingSubplot(fig, 111, grid_helper=grid_helper)
fig.add_subplot(ax1)

# create a parasite axes whose transData in RA, cz
aux_ax = ax1.get_aux_axes(tr)

aux_ax.patch = ax1.patch # for aux_ax to have a clip path as in ax
ax1.patch.zorder=0.9 # but this has a side effect that the patch is
                     # drawn twice, and possibly over some other
                     # artists. So, we decrease the zorder a bit to
                     # prevent this.

# plot your data:
aux_ax.plot(theta, radius)
plt.show()  

This will generate the following plot:

pseudo polar plot

You'd have to tweak the axis labels to meet your demands.
I scaled the data because otherwise the same issue as with your plot would have occurred - the inner, empty circle would have been scaled to a dot. You might try the scaling with your polar plot and just put custom labels on the radial axis to achieve a similar effect.