Skip to content

Commit e9e8634

Browse files
committed
Why proplot
1 parent 6736ea6 commit e9e8634

File tree

1 file changed

+56
-33
lines changed

1 file changed

+56
-33
lines changed

docs/why.rst

Lines changed: 56 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -62,30 +62,45 @@ Constructor functions
6262

6363
<h3>Problem</h3>
6464

65-
Matplotlib and cartopy introduce a bunch of classes with verbose names like `~matplotlib.ticker.MultipleLocator`, `~matplotlib.ticker.FormatStrFormatter`, `~cartopy.crs.AlbersEqualArea`, and `~cartopy.crs.NorthPolarStereo`.
66-
But matplotlib `axis scales <https://matplotlib.org/3.1.0/gallery/scales/scales.html>`__ and `colormaps <https://matplotlib.org/3.1.1/gallery/color/colormap_reference.html>`__ are **registered** under string names, as are `map projections <https://matplotlib.org/basemap/users/mapsetup.html>`__ in basemap. So why not register other verbose class names too?
65+
Matplotlib and cartopy introduce a bunch of classes with verbose names like `~matplotlib.ticker.MultipleLocator`, `~matplotlib.ticker.FormatStrFormatter`, and
66+
`~cartopy.crs.LambertAzimuthalEqualArea`. Since plotting code has a half life of about 30 seconds, typing out all of these extra class names and import statements can be a *major* drag.
67+
68+
*Other* parts of the matplotlib API were designed with this in mind.
69+
`Native axes projections <https://matplotlib.org/3.1.1/api/projections_api.html>`__,
70+
`axis scale classes <https://matplotlib.org/3.1.0/gallery/scales/scales.html>`__, and `colormap instances <https://matplotlib.org/3.1.1/gallery/color/colormap_reference.html>`__ are referenced with "registered" string names,
71+
as are `basemap projection types <https://matplotlib.org/basemap/users/mapsetup.html>`__.
72+
If these are already "registered", why not "register" everything else?
6773

6874
.. raw:: html
6975

7076
<h3>Solution</h3>
7177

72-
In ProPlot, tick locators, tick formatters, axis scales, cartopy projections, colormaps, and property cyclers are all **registered**. This is done by creating **constructor functions** and passing various keyword argument through the functions, allowing users to use class names instead of instances.
73-
74-
This may seem "unpythonic" but it is absolutely invaluable when making plots. Plotting code has a half life of about 30 seconds, and typing out all of these extra class names and import statements gets to be a major drag.
75-
76-
The below table lists the constructor functions and the keyword arguments that use them.
77-
78-
============================== ============================= ================================================================================================================================================================================================
79-
Function Returns Interpreted by
80-
============================== ============================= ================================================================================================================================================================================================
81-
`~proplot.axistools.Locator` Axis locator ``locator=``, ``xlocator=``, ``ylocator=``, ``minorlocator=``, ``xminorlocator=``, ``yminorlocator=``, ``ticks=``, ``xticks=``, ``yticks=``, ``minorticks=``, ``xminorticks=``, ``yminorticks=``
82-
`~proplot.axistools.Formatter` Axis formatter ``formatter=``, ``xformatter=``, ``yformatter=``, ``ticklabels=``, ``xticklabels=``, ``yticklabels=``
83-
`~proplot.axistools.Scale` Axis scale ``xscale=``, ``yscale=``
84-
`~proplot.styletools.Colormap` Colormap ``cmap=``
85-
`~proplot.styletools.Cycle` Property cycler ``cycle=``
86-
`~proplot.styletools.Norm` Colormap normalizer ``norm=``
87-
`~proplot.projs.Proj` Cartopy or basemap projection ``proj=``
88-
============================== ============================= ================================================================================================================================================================================================
78+
In ProPlot, tick locators, tick formatters, axis scales, cartopy projections, colormaps, and property cyclers are all "registered". This is done by creating several **constructor functions** and passing various keyword argument *through* the constructor functions.
79+
This may seem "unpythonic" but it is absolutely invaluable when making plots.
80+
81+
The constructor functions also accept *other* types of input: For
82+
example, scalar numbers passed to `~proplot.axistools.Locator` returns
83+
a `~matplotlib.ticker.MultipleLocator` instance, lists of strings passed
84+
to `~proplot.axistools.Formatter` returns a `~matplotlib.ticker.FixedFormatter` instance, and `~proplot.styletools.Colormap` and `~proplot.styletools.Cycle` accept all kinds of input. And if an instance of the corresponding class is passed to any constructor function, it is simply returned. See :ref:`X and Y axis settings`, :ref:`Colormaps`, and :ref:`Color cycles` for details.
85+
86+
The below table lists the constructor functions and the keyword arguments that
87+
use them.
88+
89+
============================== ============================================================ ============================================================= =================================================================================================================================================================================================
90+
Function Returns Interpreted by Keyword argument(s)
91+
============================== ============================================================ ============================================================= =================================================================================================================================================================================================
92+
`~proplot.axistools.Locator` Axis `~matplotlib.ticker.Locator` `~proplot.axes.Axes.format` and `~proplot.axes.Axes.colorbar` ``locator=``, ``xlocator=``, ``ylocator=``, ``minorlocator=``, ``xminorlocator=``, ``yminorlocator=``, ``ticks=``, ``xticks=``, ``yticks=``, ``minorticks=``, ``xminorticks=``, ``yminorticks=``
93+
`~proplot.axistools.Formatter` Axis `~matplotlib.ticker.Formatter` `~proplot.axes.Axes.format` and `~proplot.axes.Axes.colorbar` ``formatter=``, ``xformatter=``, ``yformatter=``, ``ticklabels=``, ``xticklabels=``, ``yticklabels=``
94+
`~proplot.axistools.Scale` Axis `~matplotlib.scale.ScaleBase` `~proplot.axes.Axes.format` ``xscale=``, ``yscale=``
95+
`~proplot.styletools.Colormap` `~matplotlib.colors.Colormap` instance Various plotting methods ``cmap=``
96+
`~proplot.styletools.Cycle` Property `~cycler.Cycler` Various plotting methods ``cycle=``
97+
`~proplot.styletools.Norm` `~matplotlib.colors.Normalize` instance Various plotting methods ``norm=``
98+
`~proplot.projs.Proj` `~cartopy.crs.Projection` or `~mpl_toolkits.basemap.Basemap` `~proplot.subplots.subplots` ``proj=``
99+
============================== ============================================================ ============================================================= =================================================================================================================================================================================================
100+
101+
Note that `~matplotlib.axes.Axes.set_xscale` and `~matplotlib.axes.Axes.set_yscale`
102+
now accept instances of `~matplotlib.scale.ScaleBase` thanks to a monkey patch
103+
applied by ProPlot.
89104

90105
Automatic dimensions and spacing
91106
================================
@@ -187,6 +202,7 @@ unifies the behavior of the three possible `matplotlib.pyplot.subplots` return v
187202
* `~proplot.subplots.axes_grid` supports row-major or column-major 1D indexing, e.g. ``axs[0]``. The order can be changed by passing ``order='F'`` or ``order='C'`` to `~proplot.subplots.subplots`.
188203
* `~proplot.subplots.axes_grid` permits 2D indexing, e.g. ``axs[1,0]``. Since `~proplot.subplots.subplots` can generate figures with arbitrarily complex subplot geometry, this 2D indexing is useful only when the arrangement happens to be a clean 2D matrix.
189204

205+
See :ref:`Creating figures` for details.
190206

191207
..
192208
This goes with ProPlot's theme of preserving the object-oriented spirit, but making things easier for users.
@@ -208,12 +224,14 @@ This approach is not ideal -- plotting methods should be invoked on the `~proplo
208224

209225
<h3>Solution</h3>
210226

211-
ProPlot *reproduces* most of the `xarray.DataArray.plot`, `pandas.DataFrame.plot`, and `pandas.Series.plot` features on the `~proplot.axes.Axes` methods themselves! Axis tick labels, axis labels, subplot titles, and colorbar and legend labels are automatically applied
227+
ProPlot *reproduces* most of the `xarray.DataArray.plot`, `pandas.DataFrame.plot`, and `pandas.Series.plot` features on the `~proplot.axes.Axes` methods themselves!
228+
229+
Axis tick labels, axis labels, subplot titles, and colorbar and legend labels are automatically applied
212230
when a `~xarray.DataArray`, `~pandas.DataFrame`, or `~pandas.Series` is passed through
213231
a plotting method instead of a `~numpy.ndarray`.
214232
This is accomplished by passing positional arguments through the
215233
`~proplot.wrappers.standardize_1d` and `~proplot.wrappers.standardize_2d`
216-
wrappers.
234+
wrappers. See :ref:`1d plotting` and :ref:`2d plotting` for details.
217235

218236
Various plotting improvements
219237
=============================
@@ -302,13 +320,15 @@ overrides various plotting methods:
302320
See :ref:`Geographic and polar plots` for details.
303321

304322
Note that active development on basemap will `halt after 2020 <https://matplotlib.org/basemap/users/intro.html#cartopy-new-management-and-eol-announcement>`__.
305-
This is the right decision: Cartopy is integrated more closely with the matplotlib API
306-
and is more amenable to further development. For now, cartopy is
323+
For now, cartopy is
307324
`missing several features <https://matplotlib.org/basemap/api/basemap_api.html#module-mpl_toolkits.basemap>`__
308325
offered by basemap -- namely, flexible meridian and parallel gridline labels,
309326
drawing physical map scales, and convenience features for adding background images like
310327
the "blue marble". But once these are added to cartopy, ProPlot may remove the `~mpl_toolkits.basemap` integration features.
311328

329+
..
330+
This is the right decision: Cartopy is integrated more closely with the matplotlib API
331+
and is more amenable to further development.
312332
313333
Colormaps and property cycles
314334
=============================
@@ -330,7 +350,7 @@ They are hard to edit and hard to create from scratch.
330350
In ProPlot, it is easy to manipulate colormaps and property cycles:
331351

332352
* The `~proplot.styletools.Colormap` constructor function can be used to slice and merge existing colormaps and/or generate brand new ones.
333-
* The `~proplot.styletools.Cycle` constructor function can be used to make *color cycles* from *colormaps*! These cycles can be applied by passing th e`cycle` keyword argument to plotting commands or changing the :rcraw:`cycle` setting. See :ref:`Color cycles` for details.
353+
* The `~proplot.styletools.Cycle` constructor function can be used to make *color cycles* from *colormaps*! These cycles can be applied by passing the `cycle` keyword argument to plotting commands or changing the :rcraw:`cycle` setting. See :ref:`Color cycles` for details.
334354
* The new `~proplot.styletools.ListedColormap` and `~proplot.styletools.LinearSegmentedColormap` classes include several new methods, e.g. `~proplot.styletools.LinearSegmentedColormap.save` and `~proplot.styletools.LinearSegmentedColormap.concatenate`, and have a much nicer REPL representation.
335355
* The `~proplot.styletools.PerceptuallyUniformColormap` class is used to make :ref:`Perceptually uniform colormaps`. These have smooth, aesthetically pleasing color transitions represent your data *accurately*.
336356

@@ -345,7 +365,10 @@ Smarter colormap normalization
345365
In matplotlib, when ``extend='min'``, ``extend='max'``, or ``extend='neither'`` is passed to `~matplotlib.figure.Figure.colorbar` , colormap colors reserved for "out-of-bounds" values are truncated.
346366

347367
The problem is that matplotlib discretizes colormaps by generating a low-resolution lookup table (see `~matplotlib.colors.LinearSegmentedColormap` for details).
348-
This approach cannot be fine-tuned, creates an unnecessary copy of the colormap, and prevents you from using the resulting colormap for plots with different numbers of levels.
368+
This approach cannot be fine-tuned and creates an unnecessary copy of the colormap.
369+
370+
..
371+
and prevents you from using the resulting colormap for plots with different numbers of levels.
349372
350373
It is clear that the task discretizing colormap colors should be left to the **normalizer**, not the colormap itself. Matplotlib provides `~matplotlib.colors.BoundaryNorm` for this purpose, but it is seldom used and its features are limited.
351374

@@ -376,11 +399,11 @@ ProPlot comes packaged with several additional fonts. The new default font is He
376399

377400
ProPlot adds fonts to matplotlib by making use of a completely undocumented feature: the ``$TTFPATH`` environment variable (matplotlib adds ``.ttf`` and ``.otf`` font files from folders listed in ``$TTFPATH``). You can also use *your own* font files by dropping them in ``~/.proplot/fonts``.
378401

379-
...and much more!
380-
=================
381-
382-
This page is not comprehensive -- it just
383-
illustrates how ProPlot addresses
384-
some of the stickiest matplotlib limitations
385-
that bug your average power user.
386-
See the User Guide for a more comprehensive overview.
402+
..
403+
...and much more!
404+
=================
405+
This page is not comprehensive -- it just
406+
illustrates how ProPlot addresses
407+
some of the stickiest matplotlib limitations
408+
that bug your average power user.
409+
See the User Guide for a more comprehensive overview.

0 commit comments

Comments
 (0)