{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Using Matplotlib Widgets\n", "\n", ".. warning::\n", " When using Matplotlib widgets you need to make sure you always keep a reference to the control sliders, otherwise the callbacks will be garbage collected and cease to work.\n", "\n", "This page is dedicated to showing how to use the ``interactive_*`` functions---such as ``interactive_plot``---with Matplotlib widgets. For\n", "a more general discussion of how to use the ``ipyplot`` submodule see the [Usage-Guide](Usage-Guide.ipynb) page.\n", "\n", "\n", "## Differences from ipywidgets sliders\n", "\n", "**1.** mpl-sliders are different from ipywidgets sliders in that they will only take a min and and max with\n", "an optional step, while for ipywidgets sliders you need to specify all values (at least until version 8).\n", "A consequence of this is that the various ``interactive_*`` methods will only use the first two values of any tuples\n", "passed as a parameter (i.e. they will ignore the ``num`` argument to linspace).\n", "\n", "**2.** Laying out Matplotlib widgets is signifcantly more difficult than laying out elements in a web browser. If you\n", "pass an existing Matplotlib widget a parameter then the plot will update as expected; however, the ``interactive_*``\n", "methods will *not* display it for you. Alternatively, when using ipywidgets widgets, if you give a widget as a parameter\n", "it will be included in the display of the controls created by the function.\n", "\n", "## Basic example\n", "\n", "If you are not using the ``ipympl`` backend then ``mpl_interactions`` will automatically create a new figure to hold all the controls." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# NBVAL_SKIP\n", "# setting the backend in case this is run in a notebook\n", "%matplotlib qt" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "gif": "mpl-sliders.gif" }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "import mpl_interactions.ipyplot as iplt\n", "\n", "x = np.linspace(0, np.pi, 100)\n", "tau = np.linspace(1, 10, 100)\n", "beta = np.linspace(0.001, 1)\n", "\n", "\n", "def f(x, tau, beta):\n", " return np.sin(x * tau) * x ** beta\n", "\n", "\n", "fig, ax = plt.subplots()\n", "controls = iplt.plot(x, f, tau=tau, beta=beta, slider_formats={\"beta\": \"{:.3e}\"})\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Custom positioning of Matplotlib widgets\n", "\n", "There does not seem to be a consistent and simple way to layout Matplotlib widgets in the same figure as the controlled plot.\n", "To address this, mpl_interactions will open a new figure to place all the controls. \n", "\n", "If you would like the sliders and the plot to live in the same figure, you will need to create and position your own slider widget." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "gif": "same-fig-mpl-slider.png" }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from matplotlib.widgets import Slider\n", "\n", "import mpl_interactions.ipyplot as iplt\n", "\n", "fig, ax = plt.subplots()\n", "plt.subplots_adjust(bottom=0.25)\n", "x = np.linspace(0, 2 * np.pi, 200)\n", "\n", "\n", "def f(x, freq):\n", " return np.sin(x * freq)\n", "\n", "\n", "axfreq = plt.axes([0.25, 0.1, 0.65, 0.03])\n", "slider = Slider(axfreq, label=\"freq\", valmin=0.05, valmax=10)\n", "controls = iplt.plot(x, f, freq=slider, ax=ax)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.0" } }, "nbformat": 4, "nbformat_minor": 4 }