Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
464d41e
Import docstring
lukelbd Sep 17, 2019
c962d63
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Sep 17, 2019
e2f0777
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Sep 17, 2019
a89016c
Add _concatenate_axes_docstrings, make behavior dependent on whether …
lukelbd Sep 17, 2019
93c6405
Prepend matplotlib summary to proplot method docstrings
lukelbd Sep 17, 2019
7a5692b
Implement 1d wrappers and begin adding interp docstring segments
lukelbd Sep 17, 2019
cd43068
Standardize docstring fragment names, add new fragments
lukelbd Sep 29, 2019
1ff63cc
Fix ginormous merge conflict
lukelbd Nov 28, 2019
b9c9e6c
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Nov 30, 2019
a41df85
Pep8 compliance
lukelbd Nov 30, 2019
da9e82a
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Nov 30, 2019
fb37b47
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Dec 2, 2019
9ac7946
Merge from master
lukelbd Dec 2, 2019
ae389be
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Dec 2, 2019
27bae6f
Fix RST links
lukelbd Dec 2, 2019
ec6c359
Merge from master
lukelbd Dec 7, 2019
65d3142
Merge from master
lukelbd Dec 14, 2019
902f101
Fix example size
lukelbd Dec 14, 2019
63474ad
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Dec 14, 2019
499d7f2
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Jan 7, 2020
7ff34f0
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Jan 7, 2020
e1131f5
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Jan 7, 2020
d9c2260
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Jan 7, 2020
6c86d3c
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Jan 7, 2020
fb9ba07
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Jan 7, 2020
ca72203
Merge branch 'master' into wrapper-docs-on-methods
lukelbd Jan 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge from master
  • Loading branch information
lukelbd committed Dec 7, 2019
commit ec6c3599602054b7011601a92b18ab614b1d5215
40 changes: 33 additions & 7 deletions proplot/axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import re
import numpy as np
import inspect
import warnings
import functools
from matplotlib import docstring
from numbers import Integral
Expand All @@ -21,8 +20,8 @@
import matplotlib.transforms as mtransforms
import matplotlib.collections as mcollections
import matplotlib.patheffects as mpatheffects
from . import utils, projs, axistools, styletools
from .utils import _notNone, units
from . import projs, axistools, styletools
from .utils import _warn_proplot, _notNone, units, arange, edges
from .rctools import rc, RC_NODOTSNAMES
from .wrappers import (
_norecurse, _redirect,
Expand Down Expand Up @@ -1023,7 +1022,7 @@ def bar(self, x=None, height=None, width=0.8, bottom=None, *, left=None,
# TODO: Stacked feature is implemented in `cycle_changer`, but makes
# more sense do document here; figure out way to move it here?
if left is not None:
warnings.warn(
_warn_proplot(
'The "left" keyword with bar() is deprecated. '
'Use "x" instead.')
x = left
Expand Down Expand Up @@ -1976,12 +1975,12 @@ def text(self,
if fontname in styletools.fonts:
kwargs['fontfamily'] = fontname
else:
warnings.warn(
_warn_proplot(
f'Font {fontname!r} unavailable. Available fonts are: '
', '.join(map(repr, styletools.fonts)) + '.')
size = _notNone(fontsize, size, None, names=('fontsize', 'size'))
if size is not None:
kwargs['fontsize'] = utils.units(size, 'pt')
kwargs['fontsize'] = units(size, 'pt')
# text.color is ignored sometimes unless we apply this
kwargs.setdefault('color', rc.get('text.color'))

Expand Down Expand Up @@ -2056,7 +2055,7 @@ def violinplot(
# Sanitize input
lw = _notNone(lw, linewidth, None, names=('lw', 'linewidth'))
if kwargs.pop('showextrema', None):
warnings.warn(f'Ignoring showextrema=True.')
_warn_proplot(f'Ignoring showextrema=True.')
if 'showmeans' in kwargs:
kwargs.setdefault('means', kwargs.pop('showmeans'))
if 'showmedians' in kwargs:
Expand Down Expand Up @@ -3840,6 +3839,33 @@ def format(self, *,
magnitude_spectrum = _disable(Axes.magnitude_spectrum)


def _add_gridline_label(self, value, axis, upper_end):
"""Gridliner method monkey patch. Always print number in range
(180W, 180E)."""
# Have 3 choices (see Issue #78):
# 1. lonlines go from -180 to 180, but get double 180 labels at dateline
# 2. lonlines go from -180 to e.g. 150, but no lines from 150 to dateline
# 3. lonlines go from lon_0 - 180 to lon_0 + 180 mod 360, but results
# in non-monotonic array causing double gridlines east of dateline
# 4. lonlines go from lon_0 - 180 to lon_0 + 180 monotonic, but prevents
# labels from being drawn outside of range (-180, 180)
# These monkey patches choose #4 and permit labels being drawn
# outside of (-180 180)
if axis == 'x':
value = (value + 180) % 360 - 180
return type(self)._add_gridline_label(self, value, axis, upper_end)


def _axes_domain(self, *args, **kwargs):
"""Gridliner method monkey patch. Filter valid label coordinates to values
between lon_0 - 180 and lon_0 + 180."""
# See _add_gridline_label for detials
lon_0 = self.axes.projection.proj4_params.get('lon_0', 0)
x_range, y_range = type(self)._axes_domain(self, *args, **kwargs)
x_range = np.asarray(x_range) + lon_0
return x_range, y_range


class GeoAxes(ProjAxes, GeoAxes):
"""Axes subclass for plotting `cartopy \
<https://scitools.org.uk/cartopy/docs/latest/>`__ projections. Initializes
Expand Down
183 changes: 175 additions & 8 deletions proplot/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
import numpy as np
import numpy.ma as ma
import functools
import warnings
from . import axistools, styletools
from .utils import _warn_proplot, _notNone, edges, edges2d, units
from matplotlib import docstring
from .utils import _notNone
from . import utils, axistools, styletools
import matplotlib.axes as maxes
import matplotlib.contour as mcontour
import matplotlib.ticker as mticker
Expand Down Expand Up @@ -313,11 +312,6 @@ def standardize_1d(self, func, *args, **kwargs):
docstring.interpd.update(standardize_1d_args=standardize_1d_args)
docstring.interpd.update(standardize_1d_kwargs=standardize_1d_kwargs)

# NOTE: Why are projection grid fixes in standardize_2d, and not in their
# own wrappers? Because grid fixes must come *after* automatic formatting,
# which means we'd have to apply these wrappers separately on XYAxes,
# BasemapAxes, GeoAxes, and PolarAxes. Would be super redundant.


def _interp_poles(y, Z):
"""Adds data points on the poles as the average of highest
Expand Down Expand Up @@ -1571,6 +1565,74 @@ def legend_wrapper(
color=None, marker=None, lw=None, linewidth=None,
dashes=None, linestyle=None, markersize=None, frameon=None, frame=None,
**kwargs):
"""
Wraps `~proplot.axes.Axes` `~proplot.axes.Axes.legend` and
`~proplot.subplots.Figure` `~proplot.subplots.Figure.legend`, adds some
handy features.

Parameters
----------
handles : list of `~matplotlib.artist.Artist`, optional
List of artists instances, or list of lists of artist instances (see
the `center` keyword). If ``None``, the artists are retrieved with
`~matplotlib.axes.Axes.get_legend_handles_labels`.
labels : list of str, optional
Matching list of string labels, or list of lists of string labels (see
the `center` keywod). If ``None``, the labels are retrieved by calling
`~matplotlib.artist.Artist.get_label` on each
`~matplotlib.artist.Artist` in `handles`.
ncol, ncols : int, optional
The number of columns. `ncols` is an alias, added
for consistency with `~matplotlib.pyplot.subplots`.
order : {'C', 'F'}, optional
Whether legend handles are drawn in row-major (``'C'``) or column-major
(``'F'``) order. Analagous to `numpy.array` ordering. For some reason
``'F'`` was the original matplotlib default. Default is ``'C'``.
center : bool, optional
Whether to center each legend row individually. If ``True``, we
actually draw successive single-row legends stacked on top of each
other.

If ``None``, we infer this setting from `handles`. Default is ``True``
if `handles` is a list of lists; each sublist is used as a *row*
in the legend. Otherwise, default is ``False``.
loc : int or str, optional
The legend location. The following location keys are valid.

================== ================================================
Location Valid keys
================== ================================================
"best" possible ``0``, ``'best'``, ``'b'``, ``'i'``, ``'inset'``
upper right ``1``, ``'upper right'``, ``'ur'``
upper left ``2``, ``'upper left'``, ``'ul'``
lower left ``3``, ``'lower left'``, ``'ll'``
lower right ``4``, ``'lower right'``, ``'lr'``
center left ``5``, ``'center left'``, ``'cl'``
center right ``6``, ``'center right'``, ``'cr'``
lower center ``7``, ``'lower center'``, ``'lc'``
upper center ``8``, ``'upper center'``, ``'uc'``
center ``9``, ``'center'``, ``'c'``
================== ================================================

label, title : str, optional
The legend title. The `label` keyword is also accepted, for consistency
with `colorbar`.
fontsize, fontweight, fontcolor : optional
The font size, weight, and color for legend text.
color, lw, linewidth, marker, linestyle, dashes, markersize : \
property-spec, optional
Properties used to override the legend handles. For example, if you
want a legend that describes variations in line style ignoring
variations in color, you might want to use ``color='k'``. For now this
does not include `facecolor`, `edgecolor`, and `alpha`, because
`~matplotlib.axes.Axes.legend` uses these keyword args to modify the
frame properties.

Other parameters
----------------
**kwargs
Passed to `~matplotlib.axes.Axes.legend`.
"""
# First get legend settings and interpret kwargs.
if order not in ('F', 'C'):
raise ValueError(
Expand Down Expand Up @@ -1937,6 +1999,111 @@ def colorbar_wrapper(
labelsize=None, labelweight=None, labelcolor=None,
ticklabelsize=None, ticklabelweight=None, ticklabelcolor=None,
**kwargs):
"""
Wraps `~proplot.axes.Axes` `~proplot.axes.Axes.colorbar` and
`~proplot.subplots.Figure` `~proplot.subplots.Figure.colorbar`, adds some
handy features.

Parameters
----------
mappable : mappable, list of plot handles, list of color-spec, \
or colormap-spec
There are four options here:

1. A mappable object. Basically, any object with a ``get_cmap`` method,
like the objects returned by `~matplotlib.axes.Axes.contourf` and
`~matplotlib.axes.Axes.pcolormesh`.
2. A list of "plot handles". Basically, any object with a ``get_color``
method, like `~matplotlib.lines.Line2D` instances. A colormap will
be generated from the colors of these objects, and colorbar levels
will be selected using `values`. If `values` is ``None``, we try
to infer them by converting the handle labels returned by
`~matplotlib.artist.Artist.get_label` to `float`. Otherwise, it is
set to ``np.linspace(0, 1, len(mappable))``.
3. A list of hex strings, color string names, or RGB tuples. A colormap
will be generated from these colors, and colorbar levels will be
selected using `values`. If `values` is ``None``, it is set to
``np.linspace(0, 1, len(mappable))``.
4. A `~matplotlib.colors.Colormap` instance. In this case, a colorbar
will be drawn using this colormap and with levels determined by
`values`. If `values` is ``None``, it is set to
``np.linspace(0, 1, cmap._N)``.

values : list of float, optional
Ignored if `mappable` is a mappable object. This maps each color or
plot handle in the `mappable` list to numeric values, from which a
colormap and normalizer are constructed.
extend : {None, 'neither', 'both', 'min', 'max'}, optional
Direction for drawing colorbar "extensions" (i.e. references to
out-of-bounds data with a unique color). These are triangles by
default. If ``None``, we try to use the ``extend`` attribute on the
mappable object. If the attribute is unavailable, we use ``'neither'``.
extendsize : float or str, optional
The length of the colorbar "extensions" in *physical units*.
If float, units are inches. If string, units are interpreted
by `~proplot.utils.units`. Default is :rc:`colorbar.insetextend`
for inset colorbars and :rc:`colorbar.extend` for outer colorbars.

This is handy if you have multiple colorbars in one figure.
With the matplotlib API, it is really hard to get triangle
sizes to match, because the `extendsize` units are *relative*.
tickloc, ticklocation : {'bottom', 'top', 'left', 'right'}, optional
Where to draw tick marks on the colorbar.
label, title : str, optional
The colorbar label. The `title` keyword is also accepted for
consistency with `legend`.
grid : bool, optional
Whether to draw "gridlines" between each level of the colorbar.
Default is :rc:`colorbar.grid`.
tickminor : bool, optional
Whether to add minor ticks to the colorbar with
`~matplotlib.colorbar.ColorbarBase.minorticks_on`. Default is
``False``.
locator, ticks : locator spec, optional
Used to determine the colorbar tick positions. Passed to the
`~proplot.axistools.Locator` constructor.
maxn : int, optional
Used if `locator` is ``None``. Determines the maximum number of levels
that are ticked. Default depends on the colorbar length relative
to the font size. The keyword name "maxn" is meant to mimic
the `~matplotlib.ticker.MaxNLocator` class name.
maxn_minor : int, optional
As with `maxn`, but for minor tick positions. Default depends
on the colorbar length.
locator_kw : dict-like, optional
The locator settings. Passed to `~proplot.axistools.Locator`.
minorlocator, minorticks
As with `locator`, but for the minor ticks.
minorlocator_kw
As for `locator_kw`, but for the minor ticks.
formatter, ticklabels : formatter spec, optional
The tick label format. Passed to the `~proplot.axistools.Formatter`
constructor.
formatter_kw : dict-like, optional
The formatter settings. Passed to `~proplot.axistools.Formatter`.
norm : normalizer spec, optional
Ignored if `values` is ``None``. The normalizer
for converting `values` to colormap colors. Passed to the
`~proplot.styletools.Norm` constructor. As an example, if your
values are logarithmically spaced but you want the level boundaries
to appear halfway in-between the colorbar ticks, try
``norm='log'``.
norm_kw : dict-like, optional
The normalizer settings. Passed to `~proplot.styletools.Norm`.
edgecolor, linewidth : optional
The edge color and line width for the colorbar outline.
labelsize, labelweight, labelcolor : optional
The font size, weight, and color for colorbar label text.
ticklabelsize, ticklabelweight, ticklabelcolor : optional
The font size, weight, and color for colorbar tick labels.
orientation : {'horizontal', 'vertical'}, optional
The colorbar orientation. You should not have to explicitly set this.

Other parameters
----------------
**kwargs
Passed to `~matplotlib.figure.Figure.colorbar`.
"""
# Developer notes
# * Colorbar axes must be of type `matplotlib.axes.Axes`,
# not `~proplot.axes.Axes`, because colorbar uses some internal methods
Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.