Skip to content

Commit 1c53e94

Browse files
committed
Support vlines/hlines/stem
1 parent 65ec4b5 commit 1c53e94

File tree

3 files changed

+83
-25
lines changed

3 files changed

+83
-25
lines changed

docs/1dplots.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -465,12 +465,6 @@
465465
# `~matplotlib.axes.Axes.scatter` now optionally accepts keywords that look
466466
# like `~matplotlib.axes.Axes.plot` keywords (e.g. `color` instead of `c` and
467467
# `markersize` instead of `s`).
468-
#
469-
# We are also considering supporting 2D array input and property cycle
470-
# iteration for more obscure matplotlib plotting commands like
471-
# `~matplotlib.axes.Axes.stem`, `~matplotlib.axes.Axes.step`,
472-
# `~matplotlib.axes.Axes.vlines`, and `~matplotlib.axes.Axes.hlines`. Stay
473-
# tuned.
474468

475469
# %%
476470
import proplot as plot

proplot/axes/base.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
_get_transform,
1414
_add_errorbars, _bar_wrapper, _barh_wrapper, _boxplot_wrapper,
1515
_cmap_changer, _cycle_changer,
16-
_fill_between_wrapper, _fill_betweenx_wrapper,
17-
_hist_wrapper, _parametric_wrapper, _plot_wrapper, _scatter_wrapper,
16+
_fill_between_wrapper, _fill_betweenx_wrapper, _hlines_wrapper,
17+
_hist_wrapper, _parametric_wrapper, _plot_wrapper, _scatter_wrapper, _stem_wrapper,
1818
_standardize_1d, _standardize_2d,
19-
_text_wrapper, _violinplot_wrapper,
19+
_text_wrapper, _violinplot_wrapper, _vlines_wrapper,
2020
colorbar_wrapper, legend_wrapper,
2121
)
2222
from .. import gridspec as pgridspec
@@ -1671,13 +1671,21 @@ def number(self, num):
16711671
pie = _standardize_1d(_cycle_changer(
16721672
maxes.Axes.pie
16731673
))
1674-
stem = _standardize_1d(_cycle_changer(
1675-
maxes.Axes.stem
1676-
))
16771674
step = _standardize_1d(_cycle_changer(
16781675
maxes.Axes.step
16791676
))
16801677

1678+
# Wrapped by standardizer
1679+
stem = _standardize_1d(_stem_wrapper(
1680+
maxes.Axes.stem
1681+
))
1682+
hlines = _standardize_1d(_hlines_wrapper(
1683+
maxes.Axes.hlines
1684+
))
1685+
vlines = _standardize_1d(_vlines_wrapper(
1686+
maxes.Axes.vlines
1687+
))
1688+
16811689
# Wrapped by cmap wrapper and standardized
16821690
# Also support redirecting to Basemap methods
16831691
hexbin = _standardize_1d(_cmap_changer(

proplot/axes/plot.py

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ def add_errorbars(
10771077
return obj
10781078

10791079

1080-
def _parametric_wrapper_temporary(self, func, *args, interp=0, **kwargs):
1080+
def _parametric_wrapper_private(self, func, *args, interp=0, **kwargs):
10811081
"""
10821082
Calls `~proplot.axes.Axes.parametric` and optionally interpolates values before
10831083
they get passed to `cmap_changer` and the colormap boundaries are drawn.
@@ -1127,7 +1127,7 @@ def _parametric_wrapper_temporary(self, func, *args, interp=0, **kwargs):
11271127
return func(self, x, y, values=values, **kwargs)
11281128

11291129

1130-
def _plot_wrapper_deprecated(
1130+
def _plot_wrapper_private(
11311131
self, func, *args, cmap=None, values=None, **kwargs
11321132
):
11331133
"""
@@ -1278,6 +1278,59 @@ def scatter_wrapper(
12781278
return obj
12791279

12801280

1281+
def _stem_wrapper_private(self, func, *args, **kwargs):
1282+
"""
1283+
Make `use_line_collection` the default to suppress annoying warning message.
1284+
"""
1285+
kwargs.setdefault('use_line_collection', True)
1286+
kwargs.setdefault('linefmt', 'C0-')
1287+
kwargs.setdefault('basefmt', kwargs['linefmt']) # use *same* for base
1288+
try:
1289+
return func(self, *args, **kwargs)
1290+
except TypeError:
1291+
kwargs.pop('use_line_collection') # old version
1292+
return func(self, *args, **kwargs)
1293+
1294+
1295+
def _parse_lines_args(x, args, kwargs):
1296+
"""
1297+
Parse lines arguments. Support automatic *x* coordinates and default
1298+
"minima" at zero.
1299+
"""
1300+
args = list(args)
1301+
if x in kwargs:
1302+
args.insert(0, kwargs.pop(x))
1303+
y = 'y' if x == 'x' else 'x'
1304+
for suffix in ('min', 'max'):
1305+
key = y + suffix
1306+
if key in kwargs:
1307+
args.append(kwargs.pop(key))
1308+
if len(args) == 1:
1309+
x = np.arange(len(np.atleast_1d(args[0])))
1310+
args.insert(0, x)
1311+
if len(args) == 2:
1312+
args.insert(1, 0.0)
1313+
elif len(args) != 3:
1314+
raise TypeError('lines() requires 1 to 3 positional arguments.')
1315+
return args, kwargs
1316+
1317+
1318+
def _hlines_wrapper_private(self, func, *args, **kwargs):
1319+
"""
1320+
Parse hlines arguments.
1321+
"""
1322+
args, kwargs = _parse_lines_args('x', args, kwargs)
1323+
return func(self, *args, **kwargs)
1324+
1325+
1326+
def _vlines_wrapper_private(self, func, *args, **kwargs):
1327+
"""
1328+
Parse vlines arguments.
1329+
"""
1330+
args, kwargs = _parse_lines_args('y', args, kwargs)
1331+
return func(self, *args, **kwargs)
1332+
1333+
12811334
def _fill_between_apply(
12821335
self, func, *args,
12831336
negcolor=None, poscolor=None, negpos=False,
@@ -1938,12 +1991,12 @@ def cycle_changer(
19381991

19391992
# Custom property cycler additions
19401993
# NOTE: By default matplotlib uses _get_patches_for_fill.get_next_color
1941-
# for scatter properties! So we simultaneously iterate through the
1942-
# _get_lines property cycler and apply them.
1943-
apply = set() # which keys to apply from property cycler
1944-
if name == 'scatter':
1994+
# for scatter next scatter color, but cannot get anything else! We simultaneously
1995+
# iterate through the _get_lines property cycler and apply relevant properties.
1996+
apply_from_cycler = set() # which keys to apply from property cycler
1997+
if name in ('scatter',):
19451998
# Figure out which props should be updated
1946-
keys = {*self._get_lines._prop_keys} - {'color', 'linestyle', 'dashes'}
1999+
prop_keys = set(self._get_lines._prop_keys) - {'color', 'linestyle', 'dashes'}
19472000
for key, prop in (
19482001
('markersize', 's'),
19492002
('linewidth', 'linewidths'),
@@ -1953,8 +2006,8 @@ def cycle_changer(
19532006
('marker', 'marker'),
19542007
):
19552008
prop = kwargs.get(prop, None)
1956-
if key in keys and prop is None:
1957-
apply.add(key)
2009+
if key in prop_keys and prop is None: # if key in cycler and property unset
2010+
apply_from_cycler.add(key)
19582011

19592012
# Handle legend labels and
19602013
# WARNING: Most methods that accept 2d arrays use columns of data, but when
@@ -1996,9 +2049,9 @@ def cycle_changer(
19962049
for i in range(ncols):
19972050
# Prop cycle properties
19982051
kw = kwargs.copy()
1999-
if apply:
2052+
if apply_from_cycler:
20002053
props = next(self._get_lines.prop_cycler)
2001-
for key in apply:
2054+
for key in apply_from_cycler:
20022055
value = props[key]
20032056
if key in ('size', 'markersize'):
20042057
key = 's'
@@ -3554,10 +3607,13 @@ def _wrapper(self, *args, **kwargs):
35543607
_fill_between_wrapper = _generate_decorator(fill_between_wrapper)
35553608
_fill_betweenx_wrapper = _generate_decorator(fill_betweenx_wrapper)
35563609
_hist_wrapper = _generate_decorator(hist_wrapper)
3557-
_parametric_wrapper = _generate_decorator(_parametric_wrapper_temporary)
3558-
_plot_wrapper = _generate_decorator(_plot_wrapper_deprecated)
3610+
_hlines_wrapper = _generate_decorator(_hlines_wrapper_private)
3611+
_parametric_wrapper = _generate_decorator(_parametric_wrapper_private)
3612+
_plot_wrapper = _generate_decorator(_plot_wrapper_private)
35593613
_scatter_wrapper = _generate_decorator(scatter_wrapper)
35603614
_standardize_1d = _generate_decorator(standardize_1d)
35613615
_standardize_2d = _generate_decorator(standardize_2d)
3616+
_stem_wrapper = _generate_decorator(_stem_wrapper_private)
35623617
_text_wrapper = _generate_decorator(text_wrapper)
35633618
_violinplot_wrapper = _generate_decorator(violinplot_wrapper)
3619+
_vlines_wrapper = _generate_decorator(_vlines_wrapper_private)

0 commit comments

Comments
 (0)