Skip to content

Commit 3b1cbaf

Browse files
committed
Major 1d wrapper refactor, add (plot|scatter)x, add 'data' key
1 parent 3ec681e commit 3b1cbaf

File tree

3 files changed

+872
-771
lines changed

3 files changed

+872
-771
lines changed

proplot/axes/base.py

Lines changed: 146 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,9 @@ def area(self, *args, **kwargs):
993993
See also
994994
--------
995995
matplotlib.axes.Axes.fill_between
996+
proplot.axes.standardize_1d
996997
proplot.axes.fill_between_extras
998+
proplot.axes.apply_cycle
997999
"""
9981000
# NOTE: *Cannot* assign area = axes.Axes.fill_between because the
9991001
# wrapper won't be applied and for some reason it messes up
@@ -1007,7 +1009,9 @@ def areax(self, *args, **kwargs):
10071009
See also
10081010
--------
10091011
matplotlib.axes.Axes.fill_betweenx
1012+
proplot.axes.standardize_1d
10101013
proplot.axes.fill_betweenx_extras
1014+
proplot.axes.apply_cycle
10111015
"""
10121016
return self.fill_betweenx(*args, **kwargs)
10131017

@@ -1018,7 +1022,9 @@ def boxes(self, *args, **kwargs):
10181022
See also
10191023
--------
10201024
matplotlib.axes.Axes.boxplot
1025+
proplot.axes.standardize_1d
10211026
proplot.axes.boxplot_extras
1027+
proplot.axes.apply_cycle
10221028
"""
10231029
return self.boxplot(*args, **kwargs)
10241030

@@ -1247,11 +1253,32 @@ def panel_axes(self, side, **kwargs):
12471253
side = self._loc_translate(side, 'panel')
12481254
return self.figure._add_axes_panel(self, side, **kwargs)
12491255

1256+
def plotx(self, *args, **kwargs):
1257+
"""
1258+
As with `~matplotlib.axes.Axes.plot` but interpret a single
1259+
positional argument as *x* and multiple positional arguments
1260+
as *y* and *x* (in that order).
1261+
1262+
Parameters
1263+
----------
1264+
*args, **kwargs
1265+
Passed to `~matplotlib.axes.Axes.plot`.
1266+
1267+
See also
1268+
--------
1269+
matplotlib.axes.Axes.plot
1270+
proplot.axes.standardize_1d
1271+
proplot.axes.indicate_error
1272+
proplot.axes.apply_cycle
1273+
"""
1274+
# NOTE: Arguments are standardized once we reach this block
1275+
x, y, *args = args
1276+
return super().plot(y, x, *args, **kwargs)
1277+
1278+
@docstring.add_snippets
12501279
def parametric(
1251-
self, *args, values=None,
1252-
cmap=None, norm=None, interp=0,
1253-
scalex=True, scaley=True,
1254-
**kwargs
1280+
self, x, y, values=None, cmap=None, norm=None, *,
1281+
interp=0, scalex=True, scaley=True, **kwargs
12551282
):
12561283
"""
12571284
Draw a line whose color changes as a function of the parametric
@@ -1263,17 +1290,9 @@ def parametric(
12631290
----------
12641291
*args : (y,), (x, y), or (x, y, values)
12651292
The coordinates. If `x` is not provided, it is inferred from `y`.
1266-
values : list of float
1267-
The parametric values used to map points on the line to colors
1268-
in the colormap. This can also be passed as a third positional argument.
1269-
cmap : colormap spec, optional
1270-
The colormap specifier, passed to `~proplot.constructor.Colormap`.
1271-
cmap_kw : dict, optional
1272-
Keyword arguments passed to `~proplot.constructor.Colormap`.
1273-
norm : normalizer spec, optional
1274-
The normalizer, passed to `~proplot.constructor.Norm`.
1275-
norm_kw : dict, optional
1276-
Keyword arguments passed to `~proplot.constructor.Norm`.
1293+
The parametric coordinate can be indicated as a third positional
1294+
argument or with the `values` or `levels` keywords.
1295+
%(axes.cmap_norm)s
12771296
interp : int, optional
12781297
If greater than ``0``, we interpolate to additional points
12791298
between the `values` coordinates. The number corresponds to the
@@ -1293,12 +1312,43 @@ def parametric(
12931312
`~matplotlib.collections.LineCollection`
12941313
The parametric line. See `this matplotlib example \
12951314
<https://matplotlib.org/stable/gallery/lines_bars_and_markers/multicolored_line>`__.
1296-
"""
1315+
1316+
See also
1317+
--------
1318+
matplotlib.axes.Axes.plot
1319+
proplot.axes.standardize_1d
1320+
proplot.axes.apply_cmap
1321+
"""
1322+
# Parse input
1323+
# NOTE: Input *x* and *y* will have been standardized by _standardize_1d
1324+
if values is None:
1325+
raise ValueError('Values must be provided.')
1326+
values = wrap._to_ndarray(values)
1327+
ndim = tuple(_.ndim for _ in (x, y, values))
1328+
size = tuple(_.size for _ in (x, y, values))
1329+
if any(_ != 1 for _ in ndim):
1330+
raise ValueError(f'Input coordinates must be 1D. Instead got dimensions {ndim}.') # noqa: E501
1331+
if any(_ != size[0] for _ in size):
1332+
raise ValueError(f'Input coordinates must have identical size. Instead got sizes {size}.') # noqa: E501
1333+
1334+
# Interpolate values to allow for smooth gradations between values
1335+
# (interp=False) or color switchover halfway between points
1336+
# (interp=True). Then optionally interpolate the colormap values.
12971337
# NOTE: The 'extras' wrapper handles input before ingestion by other wrapper
12981338
# functions. *This* method is analogous to a native matplotlib method.
1339+
if interp > 0:
1340+
x_orig, y_orig, v_orig = x, y, values
1341+
x, y, values = [], [], []
1342+
for j in range(x_orig.shape[0] - 1):
1343+
idx = slice(None)
1344+
if j + 1 < x_orig.shape[0] - 1:
1345+
idx = slice(None, -1)
1346+
x.extend(np.linspace(x_orig[j], x_orig[j + 1], interp + 2)[idx].flat)
1347+
y.extend(np.linspace(y_orig[j], y_orig[j + 1], interp + 2)[idx].flat)
1348+
values.extend(np.linspace(v_orig[j], v_orig[j + 1], interp + 2)[idx].flat) # noqa: E501
1349+
x, y, values = np.array(x), np.array(y), np.array(values)
1350+
12991351
# Get coordinates and values for points to the 'left' and 'right' of joints
1300-
x, y = args # standardized by parametric wrapper
1301-
interp # avoid U100 unused argument error (arg is handled by wrapper)
13021352
coords = []
13031353
levels = edges(values)
13041354
for i in range(y.shape[0]):
@@ -1330,16 +1380,41 @@ def parametric(
13301380
self.autoscale_view(scalex=scalex, scaley=scaley)
13311381
hs.values = values
13321382
hs.levels = levels # needed for other functions
1383+
13331384
return hs
13341385

1386+
def scatterx(self, *args, **kwargs):
1387+
"""
1388+
As with `~matplotlib.axes.Axes.scatter` but interpret a single
1389+
positional argument as *x* and multiple positional arguments
1390+
as *y* and *x* (in that order).
1391+
1392+
Parameters
1393+
----------
1394+
*args, **kwargs
1395+
Passed to `~matplotlib.axes.Axes.scatter`.
1396+
1397+
See also
1398+
--------
1399+
proplot.axes.standardize_1d
1400+
matplotlib.axes.Axes.scatter
1401+
proplot.axes.scatterx_extras
1402+
"""
1403+
# NOTE: Arguments are standardized once we reach this block
1404+
x, y, *args = args
1405+
return super().scatter(y, x, *args, **kwargs)
1406+
13351407
def violins(self, *args, **kwargs):
13361408
"""
13371409
Shorthand for `~matplotlib.axes.Axes.violinplot`.
13381410
13391411
See also
13401412
--------
13411413
matplotlib.axes.Axes.violinplot
1414+
proplot.axes.standardize_1d
13421415
proplot.axes.violinplot_extras
1416+
proplot.axes.indicate_error
1417+
proplot.axes.apply_cycle
13431418
"""
13441419
return self.violinplot(*args, **kwargs)
13451420

@@ -1805,89 +1880,102 @@ def number(self, num):
18051880
# Apply 1D plotting command wrappers
18061881
plot = wrap._apply_wrappers(
18071882
maxes.Axes.plot,
1883+
wrap.standardize_1d,
18081884
wrap._plot_extras,
1885+
wrap.indicate_error,
1886+
wrap.apply_cycle,
1887+
)
1888+
plotx = wrap._apply_wrappers(
1889+
plotx,
18091890
wrap.standardize_1d,
1891+
wrap._plotx_extras,
18101892
wrap.indicate_error,
18111893
wrap.apply_cycle,
18121894
)
1895+
step = wrap._apply_wrappers(
1896+
maxes.Axes.step,
1897+
wrap.standardize_1d,
1898+
wrap.apply_cycle,
1899+
)
1900+
stem = wrap._apply_wrappers(
1901+
maxes.Axes.stem,
1902+
wrap.standardize_1d,
1903+
wrap._stem_extras, # TODO check this
1904+
)
1905+
vlines = wrap._apply_wrappers(
1906+
maxes.Axes.vlines,
1907+
wrap.standardize_1d,
1908+
wrap.vlines_extras, # TODO check this
1909+
)
1910+
hlines = wrap._apply_wrappers(
1911+
maxes.Axes.hlines,
1912+
wrap.standardize_1d,
1913+
wrap.hlines_extras, # TODO check this
1914+
)
18131915
scatter = wrap._apply_wrappers(
18141916
maxes.Axes.scatter,
1815-
wrap.scatter_extras,
18161917
wrap.standardize_1d,
1918+
wrap.scatter_extras,
18171919
wrap.indicate_error,
18181920
wrap.apply_cycle,
18191921
)
1820-
hist = wrap._apply_wrappers(
1821-
maxes.Axes.hist,
1822-
wrap._hist_extras,
1922+
scatterx = wrap._apply_wrappers(
1923+
scatterx,
18231924
wrap.standardize_1d,
1925+
wrap.scatterx_extras,
1926+
wrap.indicate_error,
18241927
wrap.apply_cycle,
18251928
)
18261929
bar = wrap._apply_wrappers(
18271930
maxes.Axes.bar,
1828-
wrap.bar_extras,
18291931
wrap.standardize_1d,
1932+
wrap.bar_extras,
18301933
wrap.indicate_error,
18311934
wrap.apply_cycle,
18321935
)
18331936
barh = wrap._apply_wrappers(
18341937
maxes.Axes.barh,
18351938
wrap.barh_extras,
18361939
)
1837-
boxplot = wrap._apply_wrappers(
1838-
maxes.Axes.boxplot,
1839-
wrap.boxplot_extras,
1840-
wrap.standardize_1d,
1841-
wrap.apply_cycle,
1842-
)
1843-
violinplot = wrap._apply_wrappers(
1844-
maxes.Axes.violinplot,
1845-
wrap.violinplot_extras,
1940+
hist = wrap._apply_wrappers(
1941+
maxes.Axes.hist,
18461942
wrap.standardize_1d,
1847-
wrap.indicate_error,
1943+
wrap._hist_extras,
18481944
wrap.apply_cycle,
18491945
)
18501946
fill_between = wrap._apply_wrappers(
18511947
maxes.Axes.fill_between,
1852-
wrap.fill_between_extras,
18531948
wrap.standardize_1d,
1949+
wrap.fill_between_extras,
18541950
wrap.apply_cycle,
18551951
)
18561952
fill_betweenx = wrap._apply_wrappers(
18571953
maxes.Axes.fill_betweenx,
1858-
wrap.fill_betweenx_extras,
18591954
wrap.standardize_1d,
1955+
wrap.fill_betweenx_extras,
18601956
wrap.apply_cycle,
18611957
)
1862-
pie = wrap._apply_wrappers(
1863-
maxes.Axes.pie,
1958+
boxplot = wrap._apply_wrappers(
1959+
maxes.Axes.boxplot,
18641960
wrap.standardize_1d,
1961+
wrap.boxplot_extras,
18651962
wrap.apply_cycle,
1866-
18671963
)
1868-
step = wrap._apply_wrappers(
1869-
maxes.Axes.step,
1964+
violinplot = wrap._apply_wrappers(
1965+
maxes.Axes.violinplot,
18701966
wrap.standardize_1d,
1967+
wrap.violinplot_extras,
1968+
wrap.indicate_error,
18711969
wrap.apply_cycle,
18721970
)
1873-
stem = wrap._apply_wrappers(
1874-
maxes.Axes.stem,
1875-
wrap._stem_extras, # TODO check this
1876-
wrap.standardize_1d,
1877-
)
1878-
hlines = wrap._apply_wrappers(
1879-
maxes.Axes.hlines,
1880-
wrap.hlines_extras, # TODO check this
1881-
wrap.standardize_1d,
1882-
)
1883-
vlines = wrap._apply_wrappers(
1884-
maxes.Axes.vlines,
1885-
wrap.vlines_extras, # TODO check this
1971+
pie = wrap._apply_wrappers(
1972+
maxes.Axes.pie,
18861973
wrap.standardize_1d,
1974+
wrap.apply_cycle,
1975+
18871976
)
18881977
parametric = wrap._apply_wrappers(
18891978
parametric,
1890-
wrap._parametric_extras,
18911979
wrap.standardize_1d,
18921980
wrap.apply_cmap,
18931981
)
@@ -1949,10 +2037,6 @@ def number(self, num):
19492037
maxes.Axes.tricontourf,
19502038
wrap.apply_cmap,
19512039
)
1952-
hist2d = wrap._apply_wrappers(
1953-
maxes.Axes.hist2d,
1954-
wrap.apply_cmap,
1955-
)
19562040
spy = wrap._apply_wrappers(
19572041
maxes.Axes.spy,
19582042
wrap.apply_cmap,
@@ -1965,3 +2049,7 @@ def number(self, num):
19652049
maxes.Axes.matshow,
19662050
wrap.apply_cmap,
19672051
)
2052+
hist2d = wrap._apply_wrappers(
2053+
maxes.Axes.hist2d,
2054+
wrap.apply_cmap,
2055+
)

0 commit comments

Comments
 (0)