Skip to content

Commit 6903e33

Browse files
authored
Merge pull request #166 from lukelbd/style-change
Default style changes and miscellaneous plotting improvements
2 parents bc305f3 + 9b7c3c0 commit 6903e33

File tree

17 files changed

+860
-534
lines changed

17 files changed

+860
-534
lines changed

CHANGELOG.rst

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ ProPlot v0.6.0 (2020-##-##)
7171

7272
There are quite a lot of deprecations for this release.
7373

74+
- Rename `add_errorbars` to `~proplot.axes.plot.indicate_error` and rename
75+
various keyword args (:pr:`166`, :commit:`d8c50a8d`).
76+
- Remove ``'rgbcycle'`` setting (:commit:`6653b7f0`).
7477
- Deprecate support for "parametric" plots inside `~matplotlib.axes.Axes.plot`,
7578
instead use `~proplot.axes.Axes.parametric` (:commit:`64210bce`).
7679
- Change `~proplot.utils.units` ``units`` keyword argument to more natural
@@ -115,10 +118,25 @@ There are quite a lot of deprecations for this release.
115118

116119
.. rubric:: Features
117120

118-
- Support building a colormap and `DiscreteNorm` inside `~matplotlib.axes.Axes.scatter`,
119-
just like `contourf` and `pcolormesh` (:pr:`162`).
121+
- Add options to `~proplot.axes.plot.indicate_error` for adding *shading*
122+
to arbitrary plots (:pr:`166`, :commit:`d8c50a8d`). Also support automatic legend
123+
entries for shading and ensure `indicate_error` preserves metadata.
124+
- Wrap ``pcolorfast`` just like ``pcolor`` and ``pcolormesh`` are
125+
wrapped (:commit:`50a262dd`).
126+
- Add ``negpos`` feature to `~proplot.axes.plot.bar_wrapper` and new
127+
:rcraw:`negcolor` and :rcraw:`poscolor` rc keyword arguments (:commit:`ab4d6746`).
128+
- Increase default line width from ``0.6`` to ``0.8`` to match matplotlib defaults
129+
(:commit:`f801852b`; try to avoid frivolously changing defaults).
130+
- Change default resolution for geographic features from ``'lo'`` to ``'med'``
131+
(:commit:`f801852b`).
132+
- Change default line style for geographic gridlines from ``':'`` to ``'-'``
133+
and match style from primary gridlines (:commit:`f801852b`).
134+
- Support cartopy inline meridian and parallel gridlines and support
135+
changing the gridline padding (:commit:`###`).
120136
- Support `cartopy 0.18 <https://scitools.org.uk/cartopy/docs/latest/whats_new.html>`__
121137
locators, formatters, deprecations, and new labelling features (:pr:`158`).
138+
- Support building a colormap and `DiscreteNorm` inside `~matplotlib.axes.Axes.scatter`,
139+
just like `contourf` and `pcolormesh` (:pr:`162`).
122140
- Add :rcraw:`geogrid.labelpad` and :rcraw:`geogrid.rotatelabels` settings
123141
for cartopy gridline labels (:pr:`158`).
124142
- Support more `~proplot.ticker.AutoFormatter` features on
@@ -161,6 +179,8 @@ There are quite a lot of deprecations for this release.
161179

162180
.. rubric:: Bug fixes
163181

182+
- Fix various issues with axis label sharing and axis sharing for
183+
twinned axes and panel axes (:pr:`164`).
164184
- Fix issue drawing bar plots with datetime *x* axes (:pr:`156`).
165185
- Fix issue where `~proplot.ticker.AutoFormatter` tools were not locale-aware, i.e. use
166186
comma as decimal point sometimes (:commit:`c7636296`).
@@ -206,9 +226,8 @@ There are quite a lot of deprecations for this release.
206226
sensible behavior.
207227
- Turn some private `~proplot.config` functions into static
208228
methods (:commit:`6121de03`).
229+
- Remove "smart bounds" feature from `FuncScale` (:commit:`9ac149ea`).
209230
- Clean up axes iterators (:commit:`c8a0768a`).
210-
- Clean up locator and formatter sharing stuff (:commit:`###`).
211-
- Configure label sharing at draw-time rather than label-time (:commit:`###`).
212231

213232
.. rubric:: Documentation
214233

@@ -245,7 +264,6 @@ ProPlot v0.5.0 (2020-02-10)
245264

246265
.. rubric:: Bug fixes
247266

248-
- Fix issue where colormaps cannot have "dot" in name (:commit:`###`).
249267
- Fix issue where `~proplot.styletools.show_cmaps` and
250268
`~proplot.styletools.show_cycles` colormap names were messed up
251269
(:commit:`13045599`)
@@ -256,9 +274,9 @@ ProPlot v0.5.0 (2020-02-10)
256274
`~proplot.wrappers.colorbar_wrapper` were sometimes ignored
257275
(:commit:`fd4f8d5f`).
258276
- Permit passing *lists of colors* to manually shade line contours and filled
259-
contours in `~proplot.wrappers.cmap_changer` (:commit:`###`).
277+
contours in `~proplot.wrappers.cmap_changer`.
260278
- Prevent formatting rightmost meridian label as ``1e-10`` on cartopy map
261-
projections (:commit:`37fdd1eb]`).
279+
projections (:commit:`37fdd1eb`).
262280
- Support CF-time axes by fixing bug in `~proplot.wrappers.standardize_1d`
263281
and `~proplot.wrappers.standardize_2d` (:issue:`103`, :pr:`121`).
264282
- Redirect to the "default" location when using ``legend=True`` and

docs/1dplots.py

Lines changed: 63 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
fig, axs = plot.subplots(ncols=2, share=False)
9595
x = np.linspace(-5, 5, N)
9696
y = state.rand(N, 5)
97-
axs.format(xlabel='xlabel', ylabel='ylabel', ymargin=0.05)
97+
axs.format(xlabel='xlabel', ylabel='ylabel')
9898
axs.format(suptitle='Standardized arguments demonstration')
9999

100100
# Plot by passing both x and y coordinates
@@ -182,66 +182,70 @@
182182
# %% [raw] raw_mimetype="text/restructuredtext"
183183
# .. _ug_errorbars:
184184
#
185-
# Adding error bars
186-
# -----------------
185+
# Error bars and shading
186+
# ----------------------
187187
#
188-
# The `~proplot.axes.add_errorbars` wrapper lets you draw error bars
189-
# on-the-fly by passing certain keyword arguments to
188+
# The `~proplot.axes.indicate_error` wrapper lets you draw error bars
189+
# and error shading on-the-fly by passing certain keyword arguments to
190190
# `~matplotlib.axes.Axes.plot`, `~matplotlib.axes.Axes.scatter`,
191191
# `~matplotlib.axes.Axes.bar`, or `~matplotlib.axes.Axes.barh`.
192192
#
193193
# If you pass 2D arrays to these methods with ``means=True`` or
194194
# ``medians=True``, the means or medians of each column are drawn as points,
195-
# lines, or bars, and error bars are drawn to represent the spread in each
196-
# column. `~proplot.axes.add_errorbars` lets you draw both thin error
197-
# "bars" with optional whiskers, and thick error "boxes" overlayed on top of
198-
# these bars (this can be used to represent different percentil ranges).
199-
# Instead of using 2D arrays, you can also pass error bar coordinates
200-
# *manually* with the `bardata` and `boxdata` keyword arguments. See
201-
# `~proplot.axes.add_errorbars` for details.
195+
# lines, or bars, and error bars or shading is drawn to represent the spread in
196+
# each column. `~proplot.axes.indicate_error` lets you draw thin error
197+
# bars with optional whiskers, thick "boxes" overlayed on top of these bars
198+
# (think of this as a miniature boxplot), or up to 2 intervals of shading.
199+
# Instead of using 2D arrays, you can also pass the error bounds
200+
# *manually* with the `bardata`, `boxdata`, `shadedata`, and `fadedata` keyword
201+
# arguments. See `~proplot.axes.indicate_error` for details.
202202

203-
# %%
204203
import proplot as plot
205204
import numpy as np
206205
import pandas as pd
207206
plot.rc['title.loc'] = 'uc'
208-
plot.rc['axes.ymargin'] = plot.rc['axes.xmargin'] = 0.05
207+
208+
# Generate sample data
209209
state = np.random.RandomState(51423)
210-
data = (
211-
state.rand(20, 8).cumsum(axis=0).cumsum(axis=1)[:, ::-1]
212-
+ 20 * state.normal(size=(20, 8)) + 30
213-
)
210+
data = state.rand(20, 8).cumsum(axis=0).cumsum(axis=1)[:, ::-1]
211+
data = data + 20 * state.normal(size=(20, 8)) + 30
212+
data = pd.DataFrame(data, columns=np.arange(0, 16, 2))
213+
data.name = 'variable'
214+
215+
# Generate figure
214216
fig, axs = plot.subplots(
215217
nrows=3, aspect=1.5, axwidth=4,
216218
share=0, hratios=(2, 1, 1)
217219
)
218-
axs.format(suptitle='Error bars with various plotting commands')
220+
axs.format(suptitle='Indicating error bounds with various plotting commands')
219221
axs[1:].format(xlabel='column number', xticks=1, xgrid=False)
220222

221-
# Asking add_errorbars to calculate bars
223+
# Automatically calculate medians and display default percentile range
222224
ax = axs[0]
223-
obj = ax.barh(data, color='red orange', means=True)
225+
obj = ax.barh(
226+
data, color='light red', legend=True,
227+
medians=True, barpctiles=True, boxpctiles=True
228+
)
224229
ax.format(title='Column statistics')
225230
ax.format(ylabel='column number', title='Bar plot', ygrid=False)
226231

227-
# Showing a standard deviation range instead of percentile range
232+
# Automatically calculate means and display requested standard deviation range
228233
ax = axs[1]
229234
ax.scatter(
230-
data, color='k', marker='_', markersize=50,
231-
medians=True, barstd=True, boxes=False, capsize=2,
232-
barcolor='gray6', barrange=(-1, 1), barzorder=0, barlw=1,
235+
data, color='denim', marker='x', markersize=8**2, linewidth=0.8,
236+
means=True, shadestds=(-1, 1), legend='ll',
233237
)
234238
ax.format(title='Scatter plot')
235239

236-
# Supplying error bar data manually
240+
# Manually supply error bar data and legend labels
237241
ax = axs[2]
238-
boxdata = np.percentile(data, (25, 75), axis=0)
239-
bardata = np.percentile(data, (5, 95), axis=0)
242+
means = data.mean(axis=0)
243+
means.name = data.name
244+
shadedata = np.percentile(data, (25, 75), axis=0) # dark shading
245+
fadedata = np.percentile(data, (5, 95), axis=0) # light shading
240246
ax.plot(
241-
data.mean(axis=0), boxes=True,
242-
edgecolor='k', color='gray9',
243-
boxdata=boxdata, bardata=bardata, barzorder=0,
244-
boxcolor='gray7', barcolor='gray7', boxmarker=False,
247+
means, shadedata=shadedata, fadedata=fadedata,
248+
color='ocean blue', barzorder=0, boxmarker=False, legend='ll',
245249
)
246250
ax.format(title='Line plot')
247251
plot.rc.reset()
@@ -258,9 +262,10 @@
258262
# `~proplot.axes.cycle_changer`, and `~proplot.axes.standardize_1d`.
259263
# You can now *group* or *stack* columns of data by passing 2D arrays to
260264
# `~matplotlib.axes.Axes.bar` or `~matplotlib.axes.Axes.barh`, just like in
261-
# `pandas`. Also, `~matplotlib.axes.Axes.bar` and `~matplotlib.axes.Axes.barh`
262-
# now employ "default" *x* coordinates if you failed to provide them
263-
# explicitly, just like `~matplotlib.axes.Axes.plot`.
265+
# `pandas`, or use different colors for negative and positive bars by
266+
# passing ``negpos=True``. Also, `~matplotlib.axes.Axes.bar` and
267+
# `~matplotlib.axes.Axes.barh` now employ "default" *x* coordinates if you
268+
# failed to provide them explicitly.
264269
#
265270
# To make filled "area" plots, use the new `~proplot.axes.Axes.area` and
266271
# `~proplot.axes.Axes.areax` methods. These are alises for
@@ -270,7 +275,7 @@
270275
# `~proplot.axes.fill_betweenx_wrapper`. You can now *stack* or *overlay*
271276
# columns of data by passing 2D arrays to `~proplot.axes.Axes.area` and
272277
# `~proplot.axes.Axes.areax`, just like in `pandas`. You can also now draw
273-
# area plots that *change color* when the fill boundaries cross each other by
278+
# area plots that change color when the fill boundaries cross each other by
274279
# passing ``negpos=True`` to `~matplotlib.axes.Axes.fill_between`. The most
275280
# common use case for this is highlighting negative and positive areas with
276281
# different colors, as shown below.
@@ -280,7 +285,6 @@
280285
import numpy as np
281286
import pandas as pd
282287
plot.rc.titleloc = 'uc'
283-
plot.rc.margin = 0.05
284288
fig, axs = plot.subplots(nrows=2, aspect=2, axwidth=5, share=0, hratios=(3, 2))
285289
state = np.random.RandomState(51423)
286290
data = state.rand(5, 5).cumsum(axis=0).cumsum(axis=1)[:, ::-1]
@@ -313,33 +317,39 @@
313317
# %%
314318
import proplot as plot
315319
import numpy as np
316-
plot.rc.margin = 0
317-
fig, axs = plot.subplots(array=[[1, 2], [3, 3]], hratios=(1, 0.8), share=0)
318-
axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Area plot demo')
320+
fig, axs = plot.subplots(array=[[1, 2], [3, 3]], hratios=(1, 1.5), share=0)
321+
axs.format(grid=False, xlabel='xlabel', ylabel='ylabel', suptitle='Area plot demo')
319322
state = np.random.RandomState(51423)
320323
data = state.rand(5, 3).cumsum(axis=0)
321324
cycle = ('gray3', 'gray5', 'gray7')
322325

323-
# Overlaid and stacked area patches
326+
# Overlaid area patches
324327
ax = axs[0]
325328
ax.area(
326-
np.arange(5), data, data + state.rand(5)[:, None], cycle=cycle, alpha=0.5,
329+
np.arange(5), data, data + state.rand(5)[:, None], cycle=cycle, alpha=0.7,
327330
legend='uc', legend_kw={'center': True, 'ncols': 2, 'labels': ['z', 'y', 'qqqq']},
328331
)
329332
ax.format(title='Fill between columns')
333+
334+
# Stacked area patches
330335
ax = axs[1]
331336
ax.area(
332337
np.arange(5), data, stacked=True, cycle=cycle, alpha=0.8,
333338
legend='ul', legend_kw={'center': True, 'ncols': 2, 'labels': ['z', 'y', 'qqqq']},
334339
)
335340
ax.format(title='Stack between columns')
336341

337-
# Positive and negative color area patches
342+
# Positive and negative color bars and area patches
338343
ax = axs[2]
339-
data = 5 * (state.rand(20) - 0.5)
340-
ax.area(data, negpos=True, negcolor='blue7', poscolor='red7')
341-
ax.format(title='Positive and negative colors', xlabel='xlabel', ylabel='ylabel')
342-
axs.format(grid=False)
344+
data = 4 * (state.rand(20) - 0.5)
345+
ax.bar(data, bottom=-2, width=1, edgecolor='none', negpos=True)
346+
ax.area(data + 2, y2=2, negpos=True)
347+
for offset in (-2, 2):
348+
ax.axhline(offset, color='k', linewidth=1, linestyle='--')
349+
ax.format(
350+
xmargin=0, xlabel='xlabel', ylabel='ylabel',
351+
title='Positive and negative colors demo', titleweight='bold',
352+
)
343353
plot.rc.reset()
344354

345355

@@ -361,18 +371,19 @@
361371
import proplot as plot
362372
import numpy as np
363373
import pandas as pd
374+
375+
# Generate sample data
364376
N = 500
365377
state = np.random.RandomState(51423)
366-
fig, axs = plot.subplots(ncols=2, axwidth=2.5)
367378
data = state.normal(size=(N, 5)) + 2 * (state.rand(N, 5) - 0.5) * np.arange(5)
368379
data = pd.DataFrame(
369380
data,
370381
columns=pd.Index(['a', 'b', 'c', 'd', 'e'], name='xlabel')
371382
)
372-
axs.format(
373-
ymargin=0.1, xmargin=0.1, grid=False,
374-
suptitle='Boxes and violins demo'
375-
)
383+
384+
# Generate figure
385+
fig, axs = plot.subplots(ncols=2, axwidth=2.5)
386+
axs.format(grid=False, suptitle='Boxes and violins demo')
376387

377388
# Box plots
378389
ax = axs[0]
@@ -428,7 +439,6 @@
428439
x, y, c, cmap=cmap, lw=7, interp=5, capstyle='round', joinstyle='round'
429440
)
430441
ax.format(xlabel='xlabel', ylabel='ylabel', title='Line with smooth gradations')
431-
ax.format(xmargin=0.05, ymargin=0.05)
432442
ax.colorbar(m, loc='b', label='parametric coordinate', locator=5)
433443

434444
# Parametric line with stepped gradations
@@ -463,12 +473,6 @@
463473
# `~matplotlib.axes.Axes.scatter` now optionally accepts keywords that look
464474
# like `~matplotlib.axes.Axes.plot` keywords (e.g. `color` instead of `c` and
465475
# `markersize` instead of `s`).
466-
#
467-
# We are also considering supporting 2D array input and property cycle
468-
# iteration for more obscure matplotlib plotting commands like
469-
# `~matplotlib.axes.Axes.stem`, `~matplotlib.axes.Axes.step`,
470-
# `~matplotlib.axes.Axes.vlines`, and `~matplotlib.axes.Axes.hlines`. Stay
471-
# tuned.
472476

473477
# %%
474478
import proplot as plot

docs/basics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@
200200
xlabel='x-axis', ylabel='y-axis',
201201
xscale='log',
202202
xlim=(1, 10), xticks=1,
203-
ylim=(-2, 2), yticks=plot.arange(-2, 2),
203+
ymargin=0.05, yticks=plot.arange(-2, 2),
204204
yticklabels=('a', 'bb', 'c', 'dd', 'e'),
205205
ytickloc='both', yticklabelloc='both',
206206
xtickdir='inout', xtickminor=False, ygridminor=True,

docs/configuration.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,10 @@ Key Description
8989
``linewidth`` Thickness of axes spines and major tick lines.
9090
``lut`` The number of colors to put in the colormap lookup table.
9191
``margin`` The margin of space between axes edges and objects plotted inside the axes, if ``xlim`` and ``ylim`` are unset.
92+
``negcolor`` The color for negative bars and shaded areas when using ``negpos=True``.
9293
``ocean`` Boolean, toggles ocean patches on and off.
94+
``poscolor`` The color for positive bars and shaded areas when using ``negpos=True``.
9395
``reso`` Resolution of geographic features, one of ``'lo'``, ``'med'``, or ``'hi'``
94-
``rgbcycle`` If ``True``, and ``colorblind`` is the current cycle, this registers the ``colorblind`` colors as ``'r'``, ``'b'``, ``'g'``, etc., like in `seaborn <https://seaborn.pydata.org/tutorial/color_palettes.html>`__.
9596
``rivers`` Boolean, toggles river lines on and off.
9697
``share`` The axis sharing level, one of ``0``, ``1``, ``2``, or ``3``. See `~proplot.ui.subplots` for details.
9798
``small`` Font size for legend text, tick labels, axis labels, and text generated with `~matplotlib.axes.Axes.text`.

docs/projections.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,6 @@
220220
fig.colorbar(m, loc='b', span=i + 1, label='values', extendsize='1.7em')
221221
else:
222222
ax.pcolor(lon, lat, data, cmap=cmap, globe=globe, extend='both')
223-
if globe:
224-
continue
225-
xi = offset + np.linspace(0, 360, 20)
226-
for cmd in (np.sin, np.cos):
227-
yi = cmd(xi * np.pi / 180) * 60
228-
ax.plot(xi, yi, color='k', lw=0, marker='o')
229223
axs.format(
230224
suptitle=titles[globe],
231225
collabels=['Cartopy example', 'Basemap example'],

docs/sphinxext/custom_roles.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from docutils import nodes
22
from os.path import sep
3-
from proplot.internals import defaults
3+
from proplot.internals import rcsetup
44

55

66
def get_nodes(rawtext, text, inliner):
@@ -20,7 +20,7 @@ def get_nodes(rawtext, text, inliner):
2020
def rc_role(name, rawtext, text, lineno, inliner, options={}, content=[]): # noqa: U100
2121
node_list = get_nodes(rawtext, text, inliner)
2222
try:
23-
default = defaults._get_default_param(text)
23+
default = rcsetup._get_default_param(text)
2424
except KeyError:
2525
pass
2626
else:

docs/why.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,8 @@ designed to make your life easier.
400400
`~matplotlib.axes.Axes.fill_betweenx`, you will be able to use different
401401
colors for positive/negative bars.
402402
* All :ref:`1D plotting methods <ug_1dplots>` can be used to :ref:`add error
403-
bars <ug_errorbars>` using various specialized keyword arguments. You no
404-
longer have to work with the `~matplotlib.axes.Axes.errorbar` method
403+
bars or error shading <ug_errorbars>` using various specialized keyword arguments.
404+
You no longer have to work with the `~matplotlib.axes.Axes.errorbar` method
405405
directly. They also accept a
406406
:ref:`"cycle" keyword argument <ug_cycle_changer>`
407407
interpreted by `~proplot.constructor.Cycle` and optional

0 commit comments

Comments
 (0)