Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Axis scale improvements #96

Merged
merged 17 commits into from
Jan 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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