Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-ipympl for openSUSE:Factory checked in at 2021-03-02 12:35:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-ipympl (Old) and /work/SRC/openSUSE:Factory/.python-ipympl.new.2378 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-ipympl" Tue Mar 2 12:35:04 2021 rev:7 rq:875985 version:unknown Changes: -------- --- /work/SRC/openSUSE:Factory/python-ipympl/python-ipympl.changes 2020-09-21 17:45:21.701022627 +0200 +++ /work/SRC/openSUSE:Factory/.python-ipympl.new.2378/python-ipympl.changes 2021-03-02 12:46:39.144417537 +0100 @@ -1,0 +2,19 @@ +Mon Mar 1 10:06:28 UTC 2021 - Ben Greiner <c...@bnavigator.de> + +- Remove unused tarball source + +------------------------------------------------------------------- +Fri Feb 26 22:09:01 UTC 2021 - Ben Greiner <c...@bnavigator.de> + +- Update to v0.6.3 w/ labextension v0.8.3 + * Fix JupyterLab 2 support #296 + * Fix plt.pause() behaviour #291 +- Release 0.6.0 + * Add support for JupyterLab 3 +- Use the Wheel as it bundles the js stuff. +- Enable test with example notebook and pytest --nbval +- No requirement on jupyterlab or notebook: The user can decide + how to use this widget with either or. +- Skip python36 build: python36-matplotlib is not available in TW + +------------------------------------------------------------------- Old: ---- ipympl-0.5.8.tar.gz New: ---- ipympl-0.6.3-py2.py3-none-any.whl ipympl.ipynb ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-ipympl.spec ++++++ --- /var/tmp/diff_new_pack.zJIDZL/_old 2021-03-02 12:46:39.632417959 +0100 +++ /var/tmp/diff_new_pack.zJIDZL/_new 2021-03-02 12:46:39.636417962 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-ipympl # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,10 +16,11 @@ # -%{?!python_module:%define python_module() python-%{**} python3-%{**}} +%{?!python_module:%define python_module() python3-%{**}} %define skip_python2 1 -%define labver 0.7.4 -%define mainver 0.5.8 +%define skip_python36 1 +%define labver 0.8.3 +%define mainver 0.6.3 %bcond_with test Name: python-ipympl Version: %{mainver} @@ -28,24 +29,28 @@ License: BSD-3-Clause Group: Development/Languages/Python URL: https://github.com/matplotlib/ipympl -Source: https://files.pythonhosted.org/packages/source/i/ipympl/ipympl-%{mainver}.tar.gz -BuildRequires: %{python_module ipykernel} -BuildRequires: %{python_module ipython} -BuildRequires: %{python_module ipywidgets >= 7.5.0} +Source0: https://files.pythonhosted.org/packages/py2.py3/i/ipympl/ipympl-%{mainver}-py2.py3-none-any.whl +Source1: https://raw.githubusercontent.com/matplotlib/ipympl/master/examples/ipympl.ipynb +BuildRequires: %{python_module Pillow} +BuildRequires: %{python_module ipykernel >= 4.7} +BuildRequires: %{python_module ipywidgets >= 7.6.0} BuildRequires: %{python_module matplotlib >= 2.0.0} -BuildRequires: %{python_module notebook} -BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module matplotlib-web} +BuildRequires: %{python_module nbval} +BuildRequires: %{python_module pip} BuildRequires: fdupes BuildRequires: jupyter-jupyterlab-filesystem -BuildRequires: npm BuildRequires: python-rpm-macros +BuildRequires: unzip Requires: python-ipykernel >= 4.7 -Requires: python-ipython -Requires: python-ipywidgets >= 7.5.0 +Requires: python-ipywidgets >= 7.6.0 Requires: python-matplotlib >= 2.0.0 +Requires: python-matplotlib-web Provides: python-jupyter_ipympl = %{mainver} Obsoletes: python-jupyter_ipympl < %{mainver} Provides: jupyter-ipympl = %{mainver} +Suggests: python-jupyterlab +Suggests: python-notebook BuildArch: noarch %python_subpackages @@ -80,35 +85,37 @@ This package provides the JupyterLab extension. -After installation you must run: -jupyter labextension install @jupyter-widgets/jupyterlab-manager - %prep -%setup -q -n ipympl-%{mainver} +%setup -q -c ipympl-%{mainver} -D -T +%python_expand mkdir -p build; cp %{SOURCE0} build/ +cp %{SOURCE1} . %build -%python_build +: %install -%python_install - +%pyproject_install %jupyter_move_config %python_expand %fdupes %{buildroot}%{$python_sitelib} %fdupes %{buildroot}%{_jupyter_prefix} +cp %{buildroot}%{python3_sitelib}/ipympl-%{mainver}.dist-info/LICENSE . + +%check +%pytest --nbval ipympl.ipynb %files %{python_files} %license LICENSE %{python_sitelib}/ipympl/ -%{python_sitelib}/ipympl-%{mainver}-py*.egg-info +%{python_sitelib}/ipympl-%{mainver}.dist-info %files -n jupyter-ipympl %license LICENSE -%doc README.md %{_jupyter_nbextension_dir}/jupyter-matplotlib %config %{_jupyter_nb_notebook_confdir}/jupyter-matplotlib.json %files -n jupyter-ipympl-jupyterlab %license LICENSE -%{_jupyter_labextensions_dir}/jupyter-matplotlib-%{labver}.tgz +%dir %{_jupyter_prefix}/labextensions +%{_jupyter_prefix}/labextensions/jupyter-matplotlib %changelog ++++++ ipympl.ipynb ++++++ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# The Matplotlib Jupyter Widget Backend\n", "\n", "Enabling interaction with matplotlib charts in the Jupyter notebook and JupyterLab\n", "\n", "https://github.com/matplotlib/ipympl" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Enabling the `widget` backend.\n", "# This requires jupyter-matplotlib a.k.a. ipympl.\n", "# ipympl can be install via pip or conda.\n", "%matplotlib widget\n", "\n", "import matplotlib.pyplot as plt\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Testing matplotlib interactions with a simple plot\n", "fig = plt.figure()\n", "plt.plot(np.sin(np.linspace(0, 20, 100)));" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig.canvas.toolbar_visible = False\n", "fig.canvas.header_visible = False # Hide the Figure name at the top of the figure" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig.canvas.footer_visible = False" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig.canvas.resizable = False" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# If true then scrolling while the mouse is over the canvas will not move the entire notebook\n", "fig.canvas.capture_scroll = True" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also call `display` on `fig.canvas` to display the interactive plot anywhere in the notebooke" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig.canvas.toolbar_visible = True\n", "display(fig.canvas)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or you can `display(fig)` to embed the current plot as a png" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "display(fig)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 3D plotting" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from mpl_toolkits.mplot3d import axes3d\n", "\n", "fig = plt.figure()\n", "ax = fig.add_subplot(111, projection='3d')\n", "\n", "# Grab some test data.\n", "X, Y, Z = axes3d.get_test_data(0.05)\n", "\n", "# Plot a basic wireframe.\n", "ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Subplots" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# A more complex example from the matplotlib gallery\n", "np.random.seed(0)\n", "\n", "n_bins = 10\n", "x = np.random.randn(1000, 3)\n", "\n", "fig, axes = plt.subplots(nrows=2, ncols=2)\n", "ax0, ax1, ax2, ax3 = axes.flatten()\n", "\n", "colors = ['red', 'tan', 'lime']\n", "ax0.hist(x, n_bins, density=1, histtype='bar', color=colors, label=colors)\n", "ax0.legend(prop={'size': 10})\n", "ax0.set_title('bars with legend')\n", "\n", "ax1.hist(x, n_bins, density=1, histtype='bar', stacked=True)\n", "ax1.set_title('stacked bar')\n", "\n", "ax2.hist(x, n_bins, histtype='step', stacked=True, fill=False)\n", "ax2.set_title('stack step (unfilled)')\n", "\n", "# Make a multiple-histogram of data-sets with different length.\n", "x_multi = [np.random.randn(n) for n in [10000, 5000, 2000]]\n", "ax3.hist(x_multi, n_bins, histtype='bar')\n", "ax3.set_title('different sample sizes')\n", "\n", "fig.tight_layout()\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig.canvas.toolbar_position = 'right'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig.canvas.toolbar_visible = False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Interactions with other widgets and layouting\n", "\n", "When you want to embed the figure into a layout of other widgets you should call `plt.ioff()` before creating the figure otherwise code inside of `plt.figure()` will display the canvas automatically and outside of your layout. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Without using `ioff`\n", "\n", "Here we will end up with the figure being displayed twice. The button won't do anything it just placed as an example of layouting." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ipywidgets as widgets\n", "\n", "# ensure we are interactive mode \n", "# this is default but if this notebook is executed out of order it may have been turned off\n", "plt.ion()\n", "\n", "\n", "fig = plt.figure()\n", "ax = fig.gca()\n", "ax.imshow(Z)\n", "\n", "widgets.AppLayout(\n", " center=fig.canvas,\n", " footer=widgets.Button(icon='check'),\n", " pane_heights=[0, 6, 1]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Fixing the double display with `ioff`\n", "\n", "If we make sure interactive mode is off when we create the figure then the figure will only display where we want it to.\n", "\n", "There is ongoing work to allow usage of `ioff` as a context manager, see the [ipympl issue](https://github.com/matplotlib/ipympl/issues/220) and the [matplotlib issue](https://github.com/matplotlib/matplotlib/issues/17013)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.ioff()\n", "fig = plt.figure()\n", "plt.ion()\n", "\n", "ax = fig.gca()\n", "ax.imshow(Z)\n", "\n", "widgets.AppLayout(\n", " center=fig.canvas,\n", " footer=widgets.Button(icon='check'),\n", " pane_heights=[0, 6, 1]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Fixing the double display with `ipywidgets.Output`\n", "\n", "Using `plt.ioff` use matplotlib to avoid the double display of the plot. You can also use `ipywidgets.Output` to capture the plot display to prevent this" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "out = widgets.Output()\n", "with out:\n", " fig = plt.figure()\n", "\n", "ax = fig.gca()\n", "ax.imshow(Z)\n", "\n", "widgets.AppLayout(\n", " center=out,\n", " footer=widgets.Button(icon='check'),\n", " pane_heights=[0, 6, 1]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Interacting with other widgets\n", "\n", "## Changing a line plot with a slide" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# When using the `widget` backend from ipympl,\n", "# fig.canvas is a proper Jupyter interactive widget, which can be embedded in\n", "# an ipywidgets layout. See https://ipywidgets.readthedocs.io/en/stable/examples/Layout%20Templates.html\n", "\n", "# One can bound figure attributes to other widget values.\n", "from ipywidgets import AppLayout, FloatSlider\n", "\n", "plt.ioff()\n", "\n", "slider = FloatSlider(\n", " orientation='horizontal',\n", " description='Factor:',\n", " value=1.0,\n", " min=0.02,\n", " max=2.0\n", ")\n", "\n", "slider.layout.margin = '0px 30% 0px 30%'\n", "slider.layout.width = '40%'\n", "\n", "fig = plt.figure()\n", "fig.canvas.header_visible = False\n", "fig.canvas.layout.min_height = '400px'\n", "plt.title('Plotting: y=sin({} * x)'.format(slider.value))\n", "\n", "x = np.linspace(0, 20, 500)\n", "\n", "lines = plt.plot(x, np.sin(slider.value * x))\n", "\n", "def update_lines(change):\n", " plt.title('Plotting: y=sin({} * x)'.format(change.new))\n", " lines[0].set_data(x, np.sin(change.new * x))\n", " fig.canvas.draw()\n", " fig.canvas.flush_events()\n", "\n", "slider.observe(update_lines, names='value')\n", "\n", "AppLayout(\n", " center=fig.canvas,\n", " footer=slider,\n", " pane_heights=[0, 6, 1]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Update image data in a performant manner\n", "\n", "Two useful tricks to improve performance when updating an image displayed with matplolib are to:\n", "1. Use the `set_data` method instead of calling imshow\n", "2. Precompute and then index the array" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# precomputing all images\n", "x = np.linspace(0,np.pi,200)\n", "y = np.linspace(0,10,200)\n", "X,Y = np.meshgrid(x,y)\n", "parameter = np.linspace(-5,5)\n", "example_image_stack = np.sin(X)[None,:,:]+np.exp(np.cos(Y[None,:,:]*parameter[:,None,None]))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.ioff()\n", "fig = plt.figure()\n", "plt.ion()\n", "im = plt.imshow(example_image_stack[0])\n", "\n", "def update(change):\n", " im.set_data(example_image_stack[change['new']])\n", " fig.canvas.draw_idle()\n", " \n", " \n", "slider = widgets.IntSlider(value=0, min=0, max=len(parameter)-1)\n", "slider.observe(update, names='value')\n", "widgets.VBox([slider, fig.canvas])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Debugging widget updates and matplotlib callbacks\n", "\n", "If an error is raised in the `update` function then will not always display in the notebook which can make debugging difficult. This same issue is also true for matplotlib callbacks on user events such as mousemovement, for example see [issue](https://github.com/matplotlib/ipympl/issues/116). There are two ways to see the output:\n", "1. In jupyterlab the output will show up in the Log Console (View > Show Log Console)\n", "2. using `ipywidgets.Output`\n", "\n", "Here is an example of using an `Output` to capture errors in the update function from the previous example. To induce errors we changed the slider limits so that out of bounds errors will occur:\n", "\n", "From: `slider = widgets.IntSlider(value=0, min=0, max=len(parameter)-1)`\n", "\n", "To: `slider = widgets.IntSlider(value=0, min=0, max=len(parameter)+10)`\n", "\n", "If you move the slider all the way to the right you should see errors from the Output widget" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.ioff()\n", "fig = plt.figure()\n", "plt.ion()\n", "im = plt.imshow(example_image_stack[0])\n", "\n", "out = widgets.Output()\n", "@out.capture()\n", "def update(change):\n", " with out:\n", " if change['name'] == 'value':\n", " im.set_data(example_image_stack[change['new']])\n", " fig.canvas.draw_idle\n", " \n", " \n", "slider = widgets.IntSlider(value=0, min=0, max=len(parameter)+10)\n", "slider.observe(update)\n", "display(widgets.VBox([slider, fig.canvas]))\n", "display(out)" ] }, { "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.7.8" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }