Skip to content

Commit

Permalink
Merge pull request #96 from lukelbd/axis-scale-improvements
Browse files Browse the repository at this point in the history
Axis scale improvements
  • Loading branch information
lukelbd committed Jan 6, 2020
2 parents 67cc2bd + eeaeea8 commit 4799d87
Show file tree
Hide file tree
Showing 8 changed files with 524 additions and 385 deletions.
2 changes: 0 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ repos:
- id: double-quote-string-fixer
- id: check-docstring-first
- id: check-merge-conflict
- id: check-yaml
- id: debug-statements
- id: end-of-file-fixer
- id: trailing-whitespace
- id: flake8
Expand Down
22 changes: 18 additions & 4 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ ProPlot v1.0.0 (2020-##-##)
This will be published when some major refactoring tasks are completed.
See :pr:`45`, :pr:`46`, and :pr:`50`.

ProPlot v0.4.0 (2020-##-##)
ProPlot v0.5.0 (2020-##-##)
===========================
.. rubric:: Deprecated

Expand Down Expand Up @@ -60,17 +60,31 @@ ProPlot v0.4.0 (2020-##-##)
with a default ``.proplotrc`` file, change the auto-generated user ``.proplotrc``
(:pr:`50`).

ProPlot v0.3.2 (2020-##-##)
ProPlot v0.4.0 (2020-##-##)
===========================
.. rubric:: Deprecated

- Remove redundant `~proplot.rctools.use_fonts`, use ``rcParams['sans-serif']``
precedence instead (:pr:`95`).
- `~proplot.axes.Axes.dualx` and `~proplot.axes.Axes.dualx` no longer accept "scale-spec" arguments, must be a function, two functions, or an axis scale instance (:pr:`96`).

.. rubric:: Features

- Add Fira Math as DejaVu Sans-alternative (:pr:`95`). Has complete set of math characters.
- Add TeX Gyre Heros as Helvetica-alternative (:pr:`95`). This is the new open-source default font.
- Add `~proplot.subplots.Figure` ``fallback_to_cm`` kwarg. This is used by `~proplot.styletools.show_fonts` to show dummy glyphs to clearly illustrate when fonts are missing characters, but preserve graceful fallback for end user.

.. rubric:: Bug fixes

- Fix `~proplot.rctools.rc_configurator.context` bug (:issue:`80` and :pr:`91`).
- Improvements to fonts API (:pr:`93`).
- Fix issues with `~proplot.axes.Axes.dualx` and `~proplot.axes.Axes.dualy` with non-linear parent scales (:pr:`96`).
- Ignore TTC fonts because they cannot be saved in EPS/PDF figures (:issue:`94` and :pr:`95`).
- Do not try to use Helvetica Neue because "thin" font style is read as regular (:issue:`94` and :pr:`95`).

.. rubric:: Documentation

- Imperative mood for docstring summaries (:pr:`92`).
- Fix `~proplot.show_cycles` bug (:pr:`90`) and show cycles using colorbars rather than lines.
- Fix `~proplot.styletools.show_cycles` bug (:pr:`90`) and show cycles using colorbars rather than lines.

ProPlot v0.3.1 (2019-12-16)
===========================
Expand Down
78 changes: 48 additions & 30 deletions docs/axis.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,15 @@
"raw_mimetype": "text/restructuredtext"
},
"source": [
"The axis scale can be changed with `~proplot.axes.Axes.format` (keyword args `xscale` and `yscale`). You can now configure the ``'log'`` and ``'symlog'`` axis scales with the more sensible `base`, `linthresh`, `linscale`, and `subs`\n",
"keyword args, rather than ``basex``, ``basey``, etc. Also, ProPlot's `~proplot.axistools.AutoFormatter` formatter is used for all axis scales by default; this can be changed e.g. by passing ``yformatter='log'`` to `~proplot.axes.XYAxes.format`. See `~proplot.axistools.Scale`, `~proplot.axistools.LogScale` and `~proplot.axistools.SymmetricalLogScale` for details."
"The axis scale can be changed with `~proplot.axes.Axes.format` (keyword args `xscale` and `yscale`). ProPlot makes some changes to the axis scale API:\n",
"\n",
"* You can now pass scale classes to `~matplotlib.axes.Axes.set_xscale`, `~matplotlib.axes.Axes.set_yscale`, and `~proplot.axes.Axes.format` directly, rather than just strings.\n",
"* ProPlot `~proplot.axistools.Scale` classes can be instantiated *without* an `~matplotlib.axis.Axis` instance. This is required in matplotlib for backward compatibility reasons.\n",
"* The ``'log'`` and ``'symlog'`` axis scales can be configured with the more sensible `base`, `linthresh`, `linscale`, and `subs` keyword args, rather than `basex`, `basey`, etc. \n",
"* The `~proplot.axistools.AutoFormatter` formatter is used for all axis scales by default. This can be changed e.g. by passing ``yformatter='log'`` to `~proplot.axes.XYAxes.format`.\n",
"* The default minor tick locations for the ``'log'`` and ``'symlog'`` axis scales are now both ``np.arange(1, 10)``. The default \"threshold\" for the ``'symlog'`` axis scale is now ``1``.\n",
"\n",
"See `~proplot.axistools.Scale` for details.\n"
]
},
{
Expand All @@ -230,16 +237,16 @@
"plot.rc.update({'linewidth': 1, 'ticklabelweight': 'bold',\n",
" 'axeslabelweight': 'bold'})\n",
"f, axs = plot.subplots(ncols=2, nrows=2, axwidth=1.8, share=0)\n",
"axs.format(suptitle='Axis scales demo')\n",
"axs.format(suptitle='Axis scales demo', ytickminor=True)\n",
"# Linear and log scales\n",
"axs[0].format(yscale='linear', ylabel='linear scale')\n",
"axs[1].format(ylim=(1e-3, 1e3), yscale='log',\n",
" yscale_kw={'subs': np.arange(1, 10)}, ylabel='log scale')\n",
"axs[1].format(ylim=(1e-3, 1e3), yscale='log', ylabel='log scale')\n",
"axs[:2].plot(np.linspace(0, 1, N), np.linspace(0, 1000, N), lw=lw)\n",
"# Symlog and logit scales\n",
"# Symlog scale\n",
"ax = axs[2]\n",
"ax.format(yscale='symlog', yscale_kw={'linthresh': 1}, ylabel='symlog scale')\n",
"ax.format(yscale='symlog', ylabel='symlog scale')\n",
"ax.plot(np.linspace(0, 1, N), np.linspace(-1000, 1000, N), lw=lw)\n",
"# Logit scale\n",
"ax = axs[3]\n",
"ax.format(yscale='logit', ylabel='logit scale')\n",
"ax.plot(np.linspace(0, 1, N), np.linspace(0.01, 0.99, N), lw=lw)\n",
Expand All @@ -259,7 +266,7 @@
"raw_mimetype": "text/restructuredtext"
},
"source": [
"ProPlot adds several new axis scales. The ``'cutoff'`` scale is great when you have weirdly distributed data (see `~proplot.axistools.CutoffScale`). The ``'sine'`` scale uses the sine function, resulting in an *area weighted* spherical latitude coordinate, and the ``'mercator'`` scale uses the Mercator projection latitude coordinate. The ``'inverse'`` scale is useful when working with spectral data (this is more useful with `~proplot.axes.XYAxes.dualx` and `~proplot.axes.XYAxes.dualy`; see :ref:`Dual unit axes`)."
"ProPlot adds several new axis scales. The ``'cutoff'`` scale is great when you have unusually distributed data (see `~proplot.axistools.CutoffScale`). The ``'sine'`` scale uses the sine function, resulting in an *area weighted* spherical latitude coordinate, and the ``'mercator'`` scale uses the Mercator projection latitude coordinate. The ``'inverse'`` scale is useful when working with spectral data (this is more useful with `~proplot.axes.XYAxes.dualx` and `~proplot.axes.XYAxes.dualy`; see :ref:`Dual unit axes`)."
]
},
{
Expand Down Expand Up @@ -296,7 +303,7 @@
" ax.format(xscale=('cutoff', *iargs), title=title,\n",
" xlim=(0, 4*np.pi), ylabel='wave amplitude',\n",
" xformatter='pi', xlocator=locator,\n",
" xtickminor=False, xgrid=True, ygrid=False, suptitle='Cutoff scales demo')"
" xtickminor=False, xgrid=True, ygrid=False, suptitle='Cutoff axis scales demo')"
]
},
{
Expand All @@ -308,9 +315,9 @@
"import proplot as plot\n",
"import numpy as np\n",
"plot.rc.reset()\n",
"f, axs = plot.subplots(nrows=3, ncols=2, axwidth=1.5, share=0)\n",
"axs.format(rowlabels=[\n",
" 'Power\\nscales', 'Exponential\\nscales', 'Geographic\\nscales'], suptitle='Esoteric axis scales demo')\n",
"f, axs = plot.subplots(nrows=2, ncols=3, axwidth=1.6, share=0, order='F')\n",
"axs.format(collabels=['Power scales', 'Exponential scales', 'Cartographic scales'],\n",
" suptitle='Additional axis scales demo')\n",
"x = np.linspace(0, 1, 50)\n",
"y = 10*x\n",
"state = np.random.RandomState(51423)\n",
Expand All @@ -336,11 +343,10 @@
"data = state.rand(len(x), len(y2))\n",
"for ax, scale, color in zip(axs[4:], ('sine', 'mercator'), ('coral', 'sky blue')):\n",
" ax.plot(x, y, '-', color=color, lw=4)\n",
" # Use 'right' to trim the colormap from 0-1 color range to 0-0.8 color range\n",
" ax.pcolormesh(x, y2, data, cmap='grays', cmap_kw={'right': 0.8})\n",
" ax.format(title=scale.title() + ' y-axis', yscale=scale,\n",
" ytickloc='left',\n",
" yformatter='deglat', grid=False, ylocator=20,\n",
" yformatter='deg', grid=False, ylocator=20,\n",
" xscale='linear', xlim=None, ylim=(-85, 85))"
]
},
Expand All @@ -357,7 +363,9 @@
"raw_mimetype": "text/restructuredtext"
},
"source": [
"The new `~proplot.axes.XYAxes.dualx` and `~proplot.axes.XYAxes.dualy` methods build duplicate *x* and *y* axes meant to represent *alternate units* in the same coordinate range as the \"parent\" axis. Both `~proplot.axes.XYAxes.dualx` and `~proplot.axes.XYAxes.dualy` accept either a *linear function*, a pair of arbitrary *forward and inverse* functions, or a *scale name or class*. In the latter case, the scale is passed to `~proplot.axistools.Scale` and its transforms are used for the forward and inverse functions."
"The new `~proplot.axes.XYAxes.dualx` and `~proplot.axes.XYAxes.dualy` methods build duplicate *x* and *y* axes meant to represent *alternate units* in the same coordinate range as the \"parent\" axis. Both `~proplot.axes.XYAxes.dualx` and `~proplot.axes.XYAxes.dualy` accept either a single linear *forward function*, a pair of arbitrary *forward and inverse functions*, or a *scale name or scale class*. In the latter case, the scale is passed to `~proplot.axistools.Scale`, its transforms are used for the forward and inverse functions, and its default locators and formatters are used for the `~proplot.axistools.FuncScale` default locators and formatters.\n",
"\n",
"Notably, the \"parent\" axis scale is now *arbitrary*. Below, in the first example, we draw \"dual unit\" axes with both *linear* and *symlog* parent scales. The next two examples demonstrate how to use specialized axis scales used for the forward and inverse transforms of the dual axes."
]
},
{
Expand All @@ -368,20 +376,28 @@
"source": [
"import proplot as plot\n",
"plot.rc.update({'grid.alpha': 0.4, 'linewidth': 1, 'grid.linewidth': 1})\n",
"f, axs = plot.subplots(ncols=2, share=0, aspect=2.2, axwidth=3)\n",
"c1 = plot.shade('cerulean', 0.5)\n",
"c2 = plot.shade('red', 0.5)\n",
"f, axs = plot.subplots([[1, 1, 2, 2], [0, 3, 3, 0]],\n",
" share=0, aspect=2.2, axwidth=3)\n",
"axs.format(suptitle='Duplicate axes with custom transformations',\n",
" xcolor=c1, gridcolor=c1,\n",
" ylocator=[], yformatter=[])\n",
"# Meters and kilometers\n",
"ax = axs[0]\n",
"c1, c2 = plot.shade('cerulean', 0.5), plot.shade('red', 0.5)\n",
"ax.format(yformatter='null', xlabel='meters', xlocator=1000, xlim=(0, 5000),\n",
" xcolor=c2, ylocator=[], gridcolor=c2,\n",
" suptitle='Duplicate axes with custom transformations')\n",
"ax.dualx(lambda x: x*1e-3, label='kilometers', grid=True, color=c1)\n",
"ax.format(xlim=(0, 5000), xlabel='meters')\n",
"ax.dualx(lambda x: x*1e-3, label='kilometers',\n",
" grid=True, color=c2, gridcolor=c2)\n",
"# Kelvin and Celsius\n",
"ax = axs[1]\n",
"ax.format(yformatter='null', xlabel='temperature (K)', title='', xlim=(200, 300), ylocator='null',\n",
" xcolor=c2, gridcolor=c2)\n",
"ax.dualx(lambda x: x - 273.15,\n",
" label='temperature (\\N{DEGREE SIGN}C)', grid=True, color=c1, gridcolor=c1)\n",
"ax.format(xlim=(200, 300), xlabel='temperature (K)')\n",
"ax.dualx(lambda x: x - 273.15, label='temperature (\\N{DEGREE SIGN}C)',\n",
" grid=True, color=c2, gridcolor=c2)\n",
"# With symlog parent\n",
"ax = axs[2]\n",
"ax.format(xlim=(-100, 100), xscale='symlog', xlabel='MegaJoules')\n",
"ax.dualx(lambda x: x*1e6, label='Joules', formatter='log',\n",
" grid=True, color=c2, gridcolor=c2)\n",
"plot.rc.reset()"
]
},
Expand All @@ -400,12 +416,14 @@
"ax = axs[0]\n",
"ax.format(xformatter='null', ylabel='pressure (hPa)',\n",
" ylim=(1000, 10), xlocator=[], ycolor=c1, gridcolor=c1)\n",
"ax.dualy('height', label='height (km)', ticks=2.5,\n",
"scale = plot.Scale('height')\n",
"ax.dualy(scale, label='height (km)', ticks=2.5,\n",
" color=c2, gridcolor=c2, grid=True)\n",
"ax = axs[1] # span\n",
"ax.format(xformatter='null', ylabel='height (km)', ylim=(0, 20), xlocator='null',\n",
" grid=True, gridcolor=c2, ycolor=c2)\n",
"ax.dualy('pressure', label='pressure (hPa)', locator=100,\n",
"scale = plot.Scale('pressure')\n",
"ax.dualy(scale, label='pressure (hPa)', locator=100,\n",
" color=c1, gridcolor=c1, grid=True)\n",
"plot.rc.reset()"
]
Expand All @@ -429,9 +447,9 @@
"ax.axvline(cutoff, lw=2, ls='-', color=c2)\n",
"ax.fill_between([cutoff - 0.03, cutoff + 0.03], 0, 1, color=c2, alpha=0.3)\n",
"ax.plot(x, response, color=c1, lw=2)\n",
"ax.format(xlabel='wavenumber (days$^{-1}$)', ylabel='response', gridminor=True)\n",
"ax = ax.dualx('inverse', locator=[\n",
" 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05], label='period (days)')\n",
"ax.format(xlabel='wavenumber (days$^{-1}$)', ylabel='response', grid=False)\n",
"scale = plot.Scale('inverse')\n",
"ax = ax.dualx(scale, locator='log', locator_kw={'subs': (1, 2, 5)}, label='period (days)')\n",
"ax.format(title='Imaginary response function',\n",
" suptitle='Duplicate axes with wavenumber and period')\n",
"plot.rc.reset()"
Expand Down
2 changes: 1 addition & 1 deletion docs/colors_fonts.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
"outputs": [],
"source": [
"import proplot as plot\n",
"f = plot.show_fonts('DejaVu Sans', 'Fira Math', 'Helvetica', 'TeX Gyre Heros')"
"f = plot.show_fonts()"
]
},
{
Expand Down

0 comments on commit 4799d87

Please sign in to comment.