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 2022-10-12 18:23:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ipympl (Old)
 and      /work/SRC/openSUSE:Factory/.python-ipympl.new.2275 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-ipympl"

Wed Oct 12 18:23:54 2022 rev:9 rq:1009859 version:unknown

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-ipympl/python-ipympl.changes      
2021-12-24 23:38:49.896776615 +0100
+++ /work/SRC/openSUSE:Factory/.python-ipympl.new.2275/python-ipympl.changes    
2022-10-12 18:24:59.837710309 +0200
@@ -1,0 +2,46 @@
+Sun Oct  9 17:30:00 UTC 2022 - Arun Persaud <a...@gmx.de>
+
+- specfile:
+  * update download path and name of full example
+  * update required matplotlib version
+
+- update to version 0.9.2:
+  * Maintenance
+    + Remove unused 'close' arg to show(). by @anntzer in #466
+    + Move draw_if_interactive logic to
+      new_figure_manager_given_figure. by @anntzer in #468
+    + Add bot for updating galata screenshots by @martinRenou in #484
+    + Add support for ipywidgets 8 by @ianhi in #461
+
+- changes from version 0.9.1:
+  * Fix issue with widget versioning that prevented ipympl to work in
+    Voila, nbsphinx and vscode
+  * update release instructions by @ianhi in #459
+
+- changes from version 0.9.0:
+  * Bump url-parse from 1.5.3 to 1.5.7 by @dependabot in #433
+  * Create docs by @ianhi in #434
+  * remove linting from tests - now in precommit by @ianhi in #444
+  * fixed example notebook filepath by @lento234 in #445
+  * update binder bot link by @ianhi in #447
+  * support double click events by @ianhi in #446
+  * use new matplotlib nightly wheel in tests by @ianhi in #449
+  * [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in #452
+  * add docs to readme by @ianhi in #453
+  * Add model version separate from package version by @ianhi in #448
+
+- changes from version 0.8.8:
+  * fix toolbar for mpl>3.6 by @ianhi in #428
+
+- changes from version 0.8.7:
+  * Remove centering of plot on firefox by @ianhi in #421
+  * Fix CI by @martinRenou in #423
+
+- changes from version 0.8.6:
+  * Use Retrolab on Binder by @martinRenou in #414
+  * Allow ipython-8.0 by @stonebig in #418
+
+- changes from version 0.8.5:
+  * Fix package dependencies by @martinRenou in #410
+
+-------------------------------------------------------------------

Old:
----
  ipympl-0.8.4-py2.py3-none-any.whl
  ipympl.ipynb

New:
----
  full-example.ipynb
  ipympl-0.9.2-py2.py3-none-any.whl

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-ipympl.spec ++++++
--- /var/tmp/diff_new_pack.ZeXzgc/_old  2022-10-12 18:25:02.205716225 +0200
+++ /var/tmp/diff_new_pack.ZeXzgc/_new  2022-10-12 18:25:02.209716235 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-ipympl
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python3-%{**}}
 %define         skip_python2 1
 %define         skip_python36 1
-%define pyver   0.8.4
+%define pyver   0.9.2
 %define jsver   0.10.4
 %bcond_with     test
 Name:           python-ipympl
@@ -30,11 +30,11 @@
 Group:          Development/Languages/Python
 URL:            https://github.com/matplotlib/ipympl
 Source0:        
https://files.pythonhosted.org/packages/py2.py3/i/ipympl/ipympl-%{pyver}-py2.py3-none-any.whl
-Source1:        
https://raw.githubusercontent.com/matplotlib/ipympl/%{pyver}/examples/ipympl.ipynb
+Source1:        
https://github.com/matplotlib/ipympl/raw/%{pyver}/docs/examples/full-example.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 matplotlib >= 3.4.0}
 BuildRequires:  %{python_module matplotlib-web}
 BuildRequires:  %{python_module nbval}
 BuildRequires:  %{python_module pip}
@@ -44,12 +44,12 @@
 BuildRequires:  unzip
 Requires:       python-ipykernel >= 4.7
 Requires:       python-ipywidgets >= 7.6.0
-Requires:       python-matplotlib >= 2.0.0
+Requires:       python-matplotlib >= 3.4.0
 Requires:       python-matplotlib-web
-Provides:       python-jupyter_ipympl = %{pyver}
-Obsoletes:      python-jupyter_ipympl < %{pyver}
 Suggests:       python-jupyterlab
 Suggests:       python-notebook
+Provides:       python-jupyter_ipympl = %{pyver}
+Obsoletes:      python-jupyter_ipympl < %{pyver}
 BuildArch:      noarch
 %python_subpackages
 
@@ -105,7 +105,7 @@
 cp %{buildroot}%{python3_sitelib}/ipympl-%{pyver}.dist-info/LICENSE .
 
 %check
-%pytest --nbval ipympl.ipynb
+%pytest --nbval full-example.ipynb
 
 %files %{python_files}
 %license LICENSE

++++++ full-example.ipynb ++++++
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Comprehensive Example"
   ]
  },
  {
   "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": [
    "# Always hide the toolbar\n",
    "fig.canvas.toolbar_visible = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Put it back to its default\n",
    "fig.canvas.toolbar_visible = 'fade-in-fade-out'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Change the toolbar position\n",
    "fig.canvas.toolbar_position = 'top'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Hide the Figure name at the top of the figure\n",
    "fig.canvas.header_visible = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Hide the footer\n",
    "fig.canvas.footer_visible = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Disable the resizing feature\n",
    "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 `plt.figure()` 
will trigger a display of 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",
    "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": [
    "# 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)"
   ]
  }
 ],
 "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.8.6"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}

Reply via email to