Maik Hoffmann
2015-04-09 09:41:46 UTC
Hello,
I'm using mpl_toolkits.axisartist.floating_axes.GridHelperCurveLinear
for creating half-polar plots from 180 degree measurements for receive
sensitivity.
Working with the measurement values itself is no problem if I let the
values scaling start at zero.
If I use normalized values I can plot it also, but if I transform it
into the dB scale I got a segfault in this lib.
I provide an example. For my problems I would like to have a solution
that I can either use r limit from -30 to 0 (f3) or changing the tick
labels in figure f2.
And by the way is there a possibility that the if i want to plot data in
the range from 80 to 120, that rlim(80,120) would set the 80 to the
centerpoint? At the moment I got only a small stripe.
[code]
"""Demo of polar plot of arbitrary theta. This is a workaround for MPL's
polar plot limitation
to a full 360 deg.
Based on
http://matplotlib.org/mpl_toolkits/axes_grid/examples/demo_floating_axes.py
get from
https://github.com/neuropy/neuropy/blob/master/neuropy/scripts/polar_demo.py
TODO: license / copyright
"""
from __future__ import division
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D
from matplotlib.projections import PolarAxes
from mpl_toolkits.axisartist import angle_helper
from mpl_toolkits.axisartist.grid_finder import MaxNLocator
from mpl_toolkits.axisartist.floating_axes import GridHelperCurveLinear,
FloatingSubplot
def fractional_polar_axes(f, thlim=(0, 180), rlim=(0, 1), step=(30, 0.2),
thlabel='theta', rlabel='r', ticklabels=True,
theta_offset=0):
"""Return polar axes that adhere to desired theta (in deg) and r
limits. steps for theta
and r are really just hints for the locators."""
th0, th1 = thlim # deg
r0, r1 = rlim
thstep, rstep = step
tr_rotate = Affine2D().translate(theta_offset, 0)
# scale degrees to radians:
tr_scale = Affine2D().scale(np.pi/180., 1.)
#pa = axes(polar="true") # Create a polar axis
pa = PolarAxes
tr = tr_rotate + tr_scale + pa.PolarTransform()
theta_grid_locator = angle_helper.LocatorDMS((th1-th0)//thstep)
r_grid_locator = MaxNLocator((r1-r0)//rstep)
theta_tick_formatter = angle_helper.FormatterDMS()
grid_helper = GridHelperCurveLinear(tr,
extremes=(th0, th1, r0, r1),
grid_locator1=theta_grid_locator,
grid_locator2=r_grid_locator,
tick_formatter1=theta_tick_formatter,
tick_formatter2=None)
a = FloatingSubplot(f, 111, grid_helper=grid_helper)
f.add_subplot(a)
# adjust x axis (theta):
a.axis["bottom"].set_visible(False)
a.axis["top"].set_axis_direction("bottom") # tick direction
a.axis["top"].toggle(ticklabels=ticklabels, label=bool(thlabel))
a.axis["top"].major_ticklabels.set_axis_direction("top")
a.axis["top"].label.set_axis_direction("top")
# adjust y axis (r):
a.axis["left"].set_axis_direction("bottom") # tick direction
a.axis["right"].set_axis_direction("top") # tick direction
a.axis["left"].toggle(ticklabels=ticklabels, label=bool(rlabel))
# add labels:
a.axis["top"].label.set_text(thlabel)
a.axis["left"].label.set_text(rlabel)
# create a parasite axes whose transData is theta, r:
auxa = a.get_aux_axes(tr)
# make aux_ax to have a clip path as in a?:
auxa.patch = a.patch
# 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:
a.patch.zorder = -2
# add sector lines for both dimensions:
thticks = grid_helper.grid_info['lon_info'][0]
rticks = grid_helper.grid_info['lat_info'][0]
for th in thticks[1:-1]: # all but the first and last
auxa.plot([th, th], [r0, r1], '--', c='grey', zorder=-1)
for ri, r in enumerate(rticks):
# plot first r line as axes border in solid black only if it
isn't at r=0
if ri == 0 and r != 0:
ls, lw, color = 'solid', 2, 'black'
else:
ls, lw, color = 'dashed', 1, 'grey'
# From http://stackoverflow.com/a/19828753/2020363
auxa.add_artist(plt.Circle([0, 0], radius=r, ls=ls, lw=lw,
color=color, fill=False,
transform=auxa.transData._b, zorder=-1))
return auxa
if __name__ == '__main__':
f1 = plt.figure(facecolor='white', figsize=(16/2.54, 12/2.54), dpi=600)
a1 = fractional_polar_axes(f1, thlim=(-90, 90),step=(10,
0.2),theta_offset=90)
# example spiral plot:
thstep = 10
th = np.arange(-90, 90+thstep, thstep) # deg
rstep = 1/(len(th)-1)
r = np.arange(0, 1+rstep, rstep)
a1.plot(th, r, 'b')
f1.show()
f2 = plt.figure(facecolor='white', figsize=(16/2.54, 12/2.54), dpi=600)
a2 = fractional_polar_axes(f2, thlim=(-90,
90),rlim=(0,30),step=(10, 8),theta_offset=90)
# example spiral plot:
r2 = 20 * np.log10(r) +30
a2.plot(th, r2, 'b')
f2.show()
f3 = plt.figure(facecolor='white', figsize=(16/2.54, 12/2.54), dpi=600)
a3 = fractional_polar_axes(f2, thlim=(-90, 90),rlim=(-30,0),
step=(10, 8),theta_offset=90)
# example spiral plot:
r3 = 20 * np.log10(r)
a3.plot(th, r2, 'b')
f2.show()
[\code]
--
I'm using mpl_toolkits.axisartist.floating_axes.GridHelperCurveLinear
for creating half-polar plots from 180 degree measurements for receive
sensitivity.
Working with the measurement values itself is no problem if I let the
values scaling start at zero.
If I use normalized values I can plot it also, but if I transform it
into the dB scale I got a segfault in this lib.
I provide an example. For my problems I would like to have a solution
that I can either use r limit from -30 to 0 (f3) or changing the tick
labels in figure f2.
And by the way is there a possibility that the if i want to plot data in
the range from 80 to 120, that rlim(80,120) would set the 80 to the
centerpoint? At the moment I got only a small stripe.
[code]
"""Demo of polar plot of arbitrary theta. This is a workaround for MPL's
polar plot limitation
to a full 360 deg.
Based on
http://matplotlib.org/mpl_toolkits/axes_grid/examples/demo_floating_axes.py
get from
https://github.com/neuropy/neuropy/blob/master/neuropy/scripts/polar_demo.py
TODO: license / copyright
"""
from __future__ import division
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D
from matplotlib.projections import PolarAxes
from mpl_toolkits.axisartist import angle_helper
from mpl_toolkits.axisartist.grid_finder import MaxNLocator
from mpl_toolkits.axisartist.floating_axes import GridHelperCurveLinear,
FloatingSubplot
def fractional_polar_axes(f, thlim=(0, 180), rlim=(0, 1), step=(30, 0.2),
thlabel='theta', rlabel='r', ticklabels=True,
theta_offset=0):
"""Return polar axes that adhere to desired theta (in deg) and r
limits. steps for theta
and r are really just hints for the locators."""
th0, th1 = thlim # deg
r0, r1 = rlim
thstep, rstep = step
tr_rotate = Affine2D().translate(theta_offset, 0)
# scale degrees to radians:
tr_scale = Affine2D().scale(np.pi/180., 1.)
#pa = axes(polar="true") # Create a polar axis
pa = PolarAxes
tr = tr_rotate + tr_scale + pa.PolarTransform()
theta_grid_locator = angle_helper.LocatorDMS((th1-th0)//thstep)
r_grid_locator = MaxNLocator((r1-r0)//rstep)
theta_tick_formatter = angle_helper.FormatterDMS()
grid_helper = GridHelperCurveLinear(tr,
extremes=(th0, th1, r0, r1),
grid_locator1=theta_grid_locator,
grid_locator2=r_grid_locator,
tick_formatter1=theta_tick_formatter,
tick_formatter2=None)
a = FloatingSubplot(f, 111, grid_helper=grid_helper)
f.add_subplot(a)
# adjust x axis (theta):
a.axis["bottom"].set_visible(False)
a.axis["top"].set_axis_direction("bottom") # tick direction
a.axis["top"].toggle(ticklabels=ticklabels, label=bool(thlabel))
a.axis["top"].major_ticklabels.set_axis_direction("top")
a.axis["top"].label.set_axis_direction("top")
# adjust y axis (r):
a.axis["left"].set_axis_direction("bottom") # tick direction
a.axis["right"].set_axis_direction("top") # tick direction
a.axis["left"].toggle(ticklabels=ticklabels, label=bool(rlabel))
# add labels:
a.axis["top"].label.set_text(thlabel)
a.axis["left"].label.set_text(rlabel)
# create a parasite axes whose transData is theta, r:
auxa = a.get_aux_axes(tr)
# make aux_ax to have a clip path as in a?:
auxa.patch = a.patch
# 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:
a.patch.zorder = -2
# add sector lines for both dimensions:
thticks = grid_helper.grid_info['lon_info'][0]
rticks = grid_helper.grid_info['lat_info'][0]
for th in thticks[1:-1]: # all but the first and last
auxa.plot([th, th], [r0, r1], '--', c='grey', zorder=-1)
for ri, r in enumerate(rticks):
# plot first r line as axes border in solid black only if it
isn't at r=0
if ri == 0 and r != 0:
ls, lw, color = 'solid', 2, 'black'
else:
ls, lw, color = 'dashed', 1, 'grey'
# From http://stackoverflow.com/a/19828753/2020363
auxa.add_artist(plt.Circle([0, 0], radius=r, ls=ls, lw=lw,
color=color, fill=False,
transform=auxa.transData._b, zorder=-1))
return auxa
if __name__ == '__main__':
f1 = plt.figure(facecolor='white', figsize=(16/2.54, 12/2.54), dpi=600)
a1 = fractional_polar_axes(f1, thlim=(-90, 90),step=(10,
0.2),theta_offset=90)
# example spiral plot:
thstep = 10
th = np.arange(-90, 90+thstep, thstep) # deg
rstep = 1/(len(th)-1)
r = np.arange(0, 1+rstep, rstep)
a1.plot(th, r, 'b')
f1.show()
f2 = plt.figure(facecolor='white', figsize=(16/2.54, 12/2.54), dpi=600)
a2 = fractional_polar_axes(f2, thlim=(-90,
90),rlim=(0,30),step=(10, 8),theta_offset=90)
# example spiral plot:
r2 = 20 * np.log10(r) +30
a2.plot(th, r2, 'b')
f2.show()
f3 = plt.figure(facecolor='white', figsize=(16/2.54, 12/2.54), dpi=600)
a3 = fractional_polar_axes(f2, thlim=(-90, 90),rlim=(-30,0),
step=(10, 8),theta_offset=90)
# example spiral plot:
r3 = 20 * np.log10(r)
a3.plot(th, r2, 'b')
f2.show()
[\code]
--