|
40 | 40 | # ---------------------- |
41 | 41 | # |
42 | 42 | # The `~proplot.axes.standardize_2d` wrapper standardizes |
43 | | -# positional arguments across all 2D plotting methods. Among other things, |
44 | | -# it guesses coordinate *edges* for `~matplotlib.axes.Axes.pcolor` and |
| 43 | +# positional arguments across all 2D plotting methods. |
| 44 | +# `~proplot.axes.standardize_2d` lets you optionally omit the *x* and *y* |
| 45 | +# coordinates, in which case they are inferred from the data. |
| 46 | +# It also guesses coordinate *edges* for `~matplotlib.axes.Axes.pcolor` and |
45 | 47 | # `~matplotlib.axes.Axes.pcolormesh` plots when you supply coordinate |
46 | 48 | # *centers*, and calculates coordinate *centers* for |
47 | 49 | # `~matplotlib.axes.Axes.contourf` and `~matplotlib.axes.Axes.contour` plots |
|
52 | 54 | import proplot as plot |
53 | 55 | import numpy as np |
54 | 56 |
|
55 | | -# Figure and sample data |
| 57 | +# Sample data |
56 | 58 | state = np.random.RandomState(51423) |
57 | 59 | x = y = np.array([-10, -5, 0, 5, 10]) |
58 | 60 | xedges = plot.edges(x) |
59 | 61 | yedges = plot.edges(y) |
60 | 62 | data = state.rand(y.size, x.size) # "center" coordinates |
61 | 63 | lim = (np.min(xedges), np.max(xedges)) |
| 64 | + |
62 | 65 | with plot.rc.context({'image.cmap': 'Grays', 'image.levels': 21}): |
63 | | - fig, axs = plot.subplots(ncols=2, nrows=2, share=False) |
| 66 | + # Figure |
| 67 | + fig, axs = plot.subplots(ncols=2, nrows=2, refwidth=2.3, share=False) |
64 | 68 | axs.format( |
65 | 69 | xlabel='xlabel', ylabel='ylabel', |
66 | 70 | xlim=lim, ylim=lim, xlocator=5, ylocator=5, |
|
82 | 86 | # Pandas and xarray integration |
83 | 87 | # ----------------------------- |
84 | 88 | # |
85 | | -# The `~proplot.axes.standardize_2d` wrapper also integrates 2D |
86 | | -# plotting methods with pandas `~pandas.DataFrame`\ s and xarray |
87 | | -# `~xarray.DataArray`\ s. When you pass a DataFrame or DataArray to any |
88 | | -# plotting command, the x-axis label, y-axis label, legend label, colorbar |
89 | | -# label, and/or title are configured from the metadata. This restores some of |
90 | | -# the convenience you get with the builtin `pandas`_ and `xarray`_ plotting |
91 | | -# functions. This feature is *optional*. Installation of pandas and xarray are |
92 | | -# not required, and it can be disabled by setting :rcraw:`autoformat` to ``False``. |
| 89 | +# The `~proplot.axes.standardize_2d` wrapper integrates 2D plotting |
| 90 | +# methods with pandas `~pandas.DataFrame`\ s and xarray `~xarray.DataArray`\ s. |
| 91 | +# If you omitted *x* and *y* coordinates, `~proplot.axes.standardize_2d` tries to |
| 92 | +# retrieve them from the DataFrame or DataArray. If the coordinates are string |
| 93 | +# labels, `~proplot.axes.standardize_2d` converts them into indices and tick labels |
| 94 | +# using `~matplotlib.ticker.FixedLocator` and `~matplotlib.ticker.IndexFormatter`. |
| 95 | +# If you did not explicitly set the x-axis label, y-axis label, title, or |
| 96 | +# :ref:`on-the-fly legend or colorbar <ug_cbars_axes>` label, |
| 97 | +# `~proplot.axes.standardize_2d` also tries to retrieve them from the DataFrame or |
| 98 | +# DataArray. |
| 99 | +# |
| 100 | +# You can also pass a Dataset, DataFrame, or dictionary to any plotting |
| 101 | +# command using the `data` keyword, then pass dataset keys as positional |
| 102 | +# arguments instead of arrays. For example, ``ax.plot('z', data=dataset)`` |
| 103 | +# is translated to ``ax.plot(dataset['z'])``, and the *x* and *y* coordinates |
| 104 | +# are inferred thereafter. |
| 105 | +# |
| 106 | +# These features restore some of the convenience you get |
| 107 | +# with the builtin `pandas`_ and `xarray`_ plotting functions. They are also |
| 108 | +# *optional* -- installation of pandas and xarray are not required. All of |
| 109 | +# these features can be disabled by setting :rcraw:`autoformat` to ``False`` |
| 110 | +# or by passing ``autoformat=False`` to any plotting command. |
93 | 111 |
|
94 | 112 | # %% |
95 | 113 | import xarray as xr |
|
111 | 129 | plev = xr.DataArray( |
112 | 130 | np.linspace(1000, 0, 20), |
113 | 131 | dims=('plev',), |
114 | | - attrs={'long_name': 'pressure', 'units': 'mb'} |
| 132 | + attrs={'long_name': 'pressure', 'units': 'hPa'} |
115 | 133 | ) |
116 | 134 | da = xr.DataArray( |
117 | 135 | data, |
|
137 | 155 | axs.format(toplabels=('Automatic subplot formatting',)) |
138 | 156 |
|
139 | 157 | # Plot DataArray |
140 | | -cmap = plot.Colormap('RdPu', left=0.05) |
| 158 | +cmap = plot.Colormap('PuBu', left=0.05) |
141 | 159 | axs[0].contourf(da, cmap=cmap, colorbar='l', linewidth=0.7, color='k') |
142 | 160 | axs[0].format(yreverse=True) |
143 | 161 |
|
144 | 162 | # Plot DataFrame |
145 | 163 | axs[1].contourf(df, cmap='YlOrRd', colorbar='r', linewidth=0.7, color='k') |
146 | | -axs[1].format(xtickminor=False) |
| 164 | +axs[1].format(xtickminor=False, yreverse=True) |
147 | 165 |
|
148 | 166 |
|
149 | 167 | # %% [raw] raw_mimetype="text/restructuredtext" |
|
159 | 177 | # plotting method wrapped by `~proplot.axes.apply_cmap`. `cmap` and `cmap_kw` |
160 | 178 | # are passed to `~proplot.constructor.Colormap` and the resulting colormap is |
161 | 179 | # used for the plot. For example, to create and apply a monochromatic colormap, |
162 | | -# you can simply use ``cmap='color name'``. |
| 180 | +# you can simply use ``cmap='color_name'``. |
163 | 181 | # |
164 | 182 | # The `~proplot.axes.apply_cmap` wrapper also |
165 | 183 | # adds the `norm` and `norm_kw` arguments. They are passed to the |
|
175 | 193 | # Sample data |
176 | 194 | N = 20 |
177 | 195 | state = np.random.RandomState(51423) |
178 | | -data = 10 ** (0.25 * np.cumsum(state.rand(N, N), axis=0)) |
| 196 | +data = 11 ** (0.25 * np.cumsum(state.rand(N, N), axis=0)) |
179 | 197 |
|
180 | 198 | # Figure |
181 | | -fig, axs = plot.subplots(ncols=2, span=False) |
| 199 | +fig, axs = plot.subplots(ncols=2, refwidth=2.3, span=False) |
182 | 200 | axs.format( |
183 | 201 | xlabel='xlabel', ylabel='ylabel', grid=True, |
184 | 202 | suptitle='On-the-fly colormaps and normalizers' |
185 | 203 | ) |
186 | 204 |
|
187 | 205 | # Plot with colormaps and normalizers |
188 | | -axs[0].pcolormesh(data, cmap=('orange0', 'blood'), colorbar='b') |
189 | | -axs[1].pcolormesh(data, norm='log', cmap=('orange0', 'blood'), colorbar='b') |
| 206 | +cmap = 'magma' |
| 207 | +axs[0].pcolormesh(data, cmap=cmap, colorbar='b') |
| 208 | +axs[1].pcolormesh(data, norm='log', cmap=cmap, colorbar='b') |
190 | 209 | axs[0].format(title='Linear normalizer') |
191 | 210 | axs[1].format(title='Logarithmic normalizer') |
192 | 211 |
|
193 | 212 |
|
194 | 213 | # %% [raw] raw_mimetype="text/restructuredtext" |
195 | 214 | # .. _ug_discrete: |
196 | 215 | # |
197 | | -# Discrete colormap levels |
| 216 | +# Distinct colormap levels |
198 | 217 | # ------------------------ |
199 | 218 | # |
200 | | -# The `~proplot.axes.apply_cmap` wrapper also applies the |
201 | | -# `~proplot.colors.DiscreteNorm` normalizer to every colormap plot. |
202 | | -# `~proplot.colors.DiscreteNorm` converts data values to colormap colors by (1) |
203 | | -# transforming data using an arbitrary *continuous* normalizer (e.g. |
204 | | -# `~matplotlib.colors.LogNorm`), then (2) mapping the normalized data to |
205 | | -# *discrete* colormap levels (just like `~matplotlib.colors.BoundaryNorm`). |
| 219 | +# The `~proplot.axes.apply_cmap` wrapper also "discretizes" the colormaps |
| 220 | +# used with every plot. This is done using `~proplot.colors.DiscreteNorm`, |
| 221 | +# which converts data values into colormap colors by first (1) transforming |
| 222 | +# the data using an arbitrary *continuous* normalizer (e.g., |
| 223 | +# `~matplotlib.colors.Normalize` or `~matplotlib.colors.LogNorm`), then |
| 224 | +# (2) mapping the normalized data to *distinct* colormap levels. This is |
| 225 | +# similar to matplotlib's `~matplotlib.colors.BoundaryNorm`. |
206 | 226 | # |
207 | | -# By applying `~proplot.colors.DiscreteNorm` to every plot, ProPlot permits |
208 | | -# distinct "levels" even for commands like `~matplotlib.axes.Axes.pcolor` and |
209 | | -# `~matplotlib.axes.Axes.pcolormesh`. Distinct levels can help the reader |
| 227 | +# Applying `~proplot.colors.DiscreteNorm` to every colormap lets us easily |
| 228 | +# draw `matplotlib.axes.Axes.pcolor` and `~matplotlib.axes.Axes.pcolormesh` |
| 229 | +# plots with distinct levels. Distinct levels can help the reader |
210 | 230 | # discern exact numeric values and tends to reveal qualitative structure in |
211 | | -# the figure. They are also critical for users that would *prefer* contours, |
| 231 | +# the data. They are also critical for users that would *prefer* contours, |
212 | 232 | # but have complex 2D coordinate matrices that trip up the contouring |
213 | 233 | # algorithm. `~proplot.colors.DiscreteNorm` also fixes the colormap |
214 | 234 | # end-colors by ensuring the following conditions are met (this may seem |
215 | 235 | # nitpicky, but it is crucial for plots with very few levels): |
216 | 236 | # |
217 | | -# #. All colormaps always span the *entire color range*, independent of the |
218 | | -# `extend` setting. |
| 237 | +# #. All colormaps always span the *entire color range*, independent |
| 238 | +# of the `extend` setting. |
219 | 239 | # #. Cyclic colormaps always have *distinct color levels* on |
220 | 240 | # either end of the colorbar. |
| 241 | +# |
| 242 | +# The colormap levels used with `~proplot.colors.DiscreteNorm` can be configured |
| 243 | +# with the `levels`, `values`, or `N` keywords. If you pass an integer to |
| 244 | +# one of these keywords, approximately that many boundaries are automatically |
| 245 | +# generated at "nice" intervals. The keywords `vmin`, `vmax, and `locator` |
| 246 | +# control how the automatic intervals are chosen. You can also use |
| 247 | +# the `positive`, `negative`, and `symmetric` keywords to ensure that |
| 248 | +# automatically-generated levels are strictly positive, strictly negative, |
| 249 | +# or symmetric about zero (respectively). To generate your own level lists, |
| 250 | +# the `proplot.utils.arange` and `proplot.utils.edges` commands may be useful. |
221 | 251 |
|
222 | 252 | # %% |
223 | 253 | import proplot as plot |
|
228 | 258 | data = (state.normal(0, 1, size=(33, 33))).cumsum(axis=0).cumsum(axis=1) |
229 | 259 |
|
230 | 260 | # Pcolor plot with and without distinct levels |
231 | | -fig, axs = plot.subplots(ncols=2, refwidth=2) |
232 | | -axs.format(suptitle='Pcolor plot with levels') |
233 | | -for ax, n, mode, side in zip(axs, (200, 10), ('Ambiguous', 'Discernible'), 'lr'): |
234 | | - m = ax.pcolor(data, cmap='spectral_r', N=n, symmetric=True) |
| 261 | +fig, axs = plot.subplots(ncols=2, refwidth=2.2) |
| 262 | +axs.format(suptitle='DiscreteNorm with symmetric levels') |
| 263 | +for ax, n, mode, side in zip(axs, (200, 10), ('Ambiguous', 'Distinct'), 'lr'): |
| 264 | + m = ax.pcolor(data, cmap='spectral_r', levels=n, symmetric=True) |
235 | 265 | ax.format(title=f'{mode} level boundaries', yformatter='null') |
236 | 266 | ax.colorbar(m, loc=side, locator=8) |
237 | 267 |
|
|
246 | 276 |
|
247 | 277 | # Figure |
248 | 278 | fig, axs = plot.subplots( |
249 | | - [[0, 0, 1, 1, 0, 0], [2, 3, 3, 4, 4, 5]], |
250 | | - wratios=(1.5, 0.5, 1, 1, 0.5, 1.5), refwidth=1.7, ref=1, right='2em' |
| 279 | + [[0, 1, 1, 0], [2, 3, 4, 5]], |
| 280 | + wratios=(1, 1, 1, 1), hratios=(1.5, 1), |
| 281 | + refwidth=2.4, refaspect=1, right='2em' |
251 | 282 | ) |
252 | | -axs.format(suptitle='DiscreteNorm color-range standardization') |
| 283 | +axs.format(suptitle='DiscreteNorm end-color standardization') |
253 | 284 |
|
254 | 285 | # Cyclic colorbar with distinct end colors |
255 | 286 | ax = axs[0] |
256 | 287 | ax.pcolormesh( |
257 | 288 | data, levels=levels, cmap='phase', extend='neither', |
258 | 289 | colorbar='b', colorbar_kw={'locator': 90} |
259 | 290 | ) |
260 | | -ax.format(title='cyclic colormap\nwith distinct end colors') |
| 291 | +ax.format(title='distinct "cyclic" end colors') |
261 | 292 |
|
262 | 293 | # Colorbars with different extend values |
263 | 294 | for ax, extend in zip(axs[1:], ('min', 'max', 'neither', 'both')): |
264 | 295 | ax.pcolormesh( |
265 | 296 | data[:, :10], levels=levels, cmap='oxy', |
266 | | - extend=extend, colorbar='b', colorbar_kw={'locator': 90} |
| 297 | + extend=extend, colorbar='b', colorbar_kw={'locator': 180} |
267 | 298 | ) |
268 | 299 | ax.format(title=f'extend={extend!r}') |
269 | 300 |
|
|
283 | 314 | # The `~proplot.colors.DivergingNorm` normalizer |
284 | 315 | # ensures the colormap midpoint lies on some *central* data value (usually 0), |
285 | 316 | # even if `vmin`, `vmax`, or `levels` are asymmetric with respect to the central |
286 | | -# value. This can be applied using e.g. ``norm='diverging'`` and be configured |
| 317 | +# value. This can be applied using e.g. ``norm='diverging'`` and configured |
287 | 318 | # to scale colors "fairly" or "unfairly": |
288 | 319 | # |
289 | | -# * With fair scaling (the default), the gradations on either side of the midpoint |
| 320 | +# * With fair scaling (the default), gradations on either side of the midpoint |
290 | 321 | # have equal intensity. If `vmin` and `vmax` are not symmetric about zero, the most |
291 | 322 | # intense colormap colors on one side of the midpoint will be truncated. |
292 | | -# * With unfair scaling, the gradations on either side of the midpoint are warped |
| 323 | +# * With unfair scaling, gradations on either side of the midpoint are warped |
293 | 324 | # so that the full range of colormap colors is traversed. This configuration should |
294 | 325 | # be used with care, as it may lead you to misinterpret your data! |
295 | 326 | # |
|
329 | 360 | data2 = (state.rand(20, 20) - 0.515).cumsum(axis=0).cumsum(axis=1) |
330 | 361 |
|
331 | 362 | # Figure |
332 | | -fig, axs = plot.subplots(nrows=2, ncols=2, refwidth=2.4, order='F') |
| 363 | +fig, axs = plot.subplots(nrows=2, ncols=2, refwidth=2.2, order='F') |
333 | 364 | axs.format(suptitle='Diverging normalizer demo') |
334 | 365 | cmap = plot.Colormap('DryWet', cut=0.1) |
335 | 366 |
|
|
346 | 377 | ax = axs[i] |
347 | 378 | m = ax.contourf(data, cmap=cmap, norm=norm) |
348 | 379 | ax.colorbar(m, loc='b', locator=locator) |
349 | | - ax.format(title=f'{mode.title()}-skewed w/ {fair!r} scaling') |
| 380 | + ax.format(title=f'{mode.title()}-skewed + {fair} scaling') |
350 | 381 | i += 1 |
351 | 382 |
|
352 | 383 |
|
|
356 | 387 | # Contour and gridbox labels |
357 | 388 | # -------------------------- |
358 | 389 | # |
359 | | -# The `~proplot.axes.apply_cmap` wrapper also allows you to quickly add |
| 390 | +# The `~proplot.axes.apply_cmap` wrapper lets you quickly add |
360 | 391 | # *labels* to `~proplot.axes.Axes.heatmap`, `~matplotlib.axes.Axes.pcolor`, |
361 | 392 | # `~matplotlib.axes.Axes.pcolormesh`, `~matplotlib.axes.Axes.contour`, and |
362 | 393 | # `~matplotlib.axes.Axes.contourf` plots by simply using ``labels=True``. |
|
366 | 397 | # `~proplot.axes.apply_cmap` draws contour labels with |
367 | 398 | # `~matplotlib.axes.Axes.clabel` and grid box labels with |
368 | 399 | # `~matplotlib.axes.Axes.text`. You can pass keyword arguments to these |
369 | | -# functions using the `labels_kw` dictionary keyword argument, and change the |
370 | | -# label precision with the `precision` keyword argument. See |
| 400 | +# functions using a `labels_kw` dictionary keyword argument, and change the |
| 401 | +# label precision with the `precision` keyword. See |
371 | 402 | # `~proplot.axes.apply_cmap` for details. |
372 | 403 |
|
373 | 404 | # %% |
|
383 | 414 | # Figure |
384 | 415 | fig, axs = plot.subplots( |
385 | 416 | [[1, 1, 2, 2], [0, 3, 3, 0]], |
386 | | - refwidth=2.2, share=1, span=False, |
| 417 | + refwidth=2.3, share=1, span=False, |
387 | 418 | ) |
388 | 419 | axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Labels demo') |
389 | 420 |
|
|
419 | 450 | # ------------- |
420 | 451 | # |
421 | 452 | # The new `~proplot.axes.Axes.heatmap` command calls |
422 | | -# `~matplotlib.axes.Axes.pcolormesh` and configures the axes with settings |
423 | | -# that are suitable for heatmaps -- fixed aspect ratio, no gridlines, no minor ticks, |
424 | | -# and major ticks at the center of each box. Among other things, this is useful for |
425 | | -# displaying covariance and correlation matrices, as shown below. |
| 453 | +# `~matplotlib.axes.Axes.pcolormesh` and configures the |
| 454 | +# axes with settings that are suitable for heatmaps -- |
| 455 | +# fixed aspect ratio, no gridlines, no minor ticks, |
| 456 | +# and major ticks at the center of each box. Among other |
| 457 | +# things, this is useful for displaying covariance and |
| 458 | +# correlation matrices, as shown below. This should |
| 459 | +# generally only be used with `~proplot.axes.CartesianAxes`. |
426 | 460 |
|
427 | 461 | # %% |
428 | 462 | import proplot as plot |
|
0 commit comments