"""
Module supporting use of scale bars
"""
# -*- coding: utf-8 -*-
# -*- mode: python -*-
# Adapted from mpl_toolkits.axes_grid1
# LICENSE: Python Software Foundation (http://docs.python.org/license.html)
from netpyne import __gui__
if __gui__:
from matplotlib.offsetbox import AnchoredOffsetbox
try:
[docs]
class AnchoredScaleBar(AnchoredOffsetbox):
def __init__(
self,
transform,
sizex=0,
sizey=0,
labelx=None,
labely=None,
loc=4,
pad=0.1,
borderpad=0.1,
sep=2,
prop=None,
barcolor="black",
barwidth=None,
**kwargs
):
"""
Draw a horizontal and/or vertical bar with the size in data coordinate
of the give axes. A label will be drawn underneath (center-aligned).
- transform : the coordinate frame (typically axes.transData)
- sizex,sizey : width of x,y bar, in data units. 0 to omit
- labelx,labely : labels for x,y bars; None to omit
- loc : position in containing axes
- pad, borderpad : padding, in fraction of the legend font size (or prop)
- sep : separation between labels and bars in points.
- **kwargs : additional arguments passed to base class constructor
"""
from matplotlib.patches import Rectangle
from matplotlib.offsetbox import AuxTransformBox, VPacker, HPacker, TextArea, DrawingArea
bars = AuxTransformBox(transform)
if sizex:
bars.add_artist(Rectangle((0, 0), sizex, 0, ec=barcolor, lw=barwidth, fc="none"))
if sizey:
bars.add_artist(Rectangle((0, 0), 0, sizey, ec=barcolor, lw=barwidth, fc="none"))
if sizex and labelx:
self.xlabel = TextArea(labelx, minimumdescent=False)
bars = VPacker(children=[bars, self.xlabel], align="center", pad=0, sep=sep)
if sizey and labely:
self.ylabel = TextArea(labely)
bars = HPacker(children=[self.ylabel, bars], align="center", pad=0, sep=sep)
AnchoredOffsetbox.__init__(
self, loc, pad=pad, borderpad=borderpad, child=bars, prop=prop, frameon=False, **kwargs
)
except NameError:
print("-nogui passed, matplotlib is unavailable")
[docs]
def add_scalebar(
ax, matchx=True, matchy=True, hidex=True, hidey=True, unitsx='', unitsy='', scalex=1, scaley=1, **kwargs
):
"""Add scalebars to axes
Adds a set of scale bars to *ax*, matching the size to the ticks of the plot
and optionally hiding the x and y axes
- ax : the axis to attach ticks to
- matchx,matchy : if True, set size of scale bars to spacing between ticks, if False, size should be set using sizex and sizey params
- hidex,hidey : if True, hide x-axis and y-axis of parent
- **kwargs : additional arguments passed to AnchoredScaleBars
Returns created scalebar object
"""
def f(axis):
l = axis.get_majorticklocs()
return len(l) > 1 and (l[1] - l[0])
if matchx:
kwargs['sizex'] = f(ax.xaxis)
if matchy:
kwargs['sizey'] = f(ax.yaxis)
if 'labelx' not in kwargs or kwargs['labelx'] is None:
kwargs['labelx'] = '%.3g %s' % (kwargs['sizex'] * scalex, unitsx)
if 'labely' not in kwargs or kwargs['labely'] is None:
kwargs['labely'] = '%.3g %s' % (kwargs['sizey'] * scaley, unitsy)
sb = AnchoredScaleBar(ax.transData, **kwargs)
ax.add_artist(sb)
if hidex:
ax.xaxis.set_visible(False)
if hidey:
ax.yaxis.set_visible(False)
if hidex and hidey:
ax.set_frame_on(False)
return sb