From f2784e57129849c5bc953213747d2aaa4b458fe0 Mon Sep 17 00:00:00 2001 From: Jon Mease <jon.mease@gmail.com> Date: Tue, 24 Jul 2018 13:05:18 -0400 Subject: [PATCH] Add new interact and overview notebooks --- notebooks/Interact.ipynb | 92 ++++++ notebooks/Overview.ipynb | 588 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 680 insertions(+) create mode 100644 notebooks/Interact.ipynb create mode 100644 notebooks/Overview.ipynb diff --git a/notebooks/Interact.ipynb b/notebooks/Interact.ipynb new file mode 100644 index 0000000..b989e38 --- /dev/null +++ b/notebooks/Interact.ipynb @@ -0,0 +1,92 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Interact\n", + "Here is a simple example of using the `interact` decorator from ipywidgets to create a simple set of widgets to control the parameters of a plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import plotly.graph_objs as go\n", + "import numpy as np\n", + "from ipywidgets import interact" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we'll create an empty figure, and add an empty scatter trace to it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig = go.FigureWidget()\n", + "scatt = fig.add_scatter()\n", + "fig" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then, write an update function that inputs the frequency factor (`a`) and phase factor (`b`) and sets the `x` and `y` properties of the scatter trace. This function is decorated with the `interact` decorator from the `ipywidgets` package. The decorator parameters are used to specify the ranges of parameters that we want to sweep over. See http://ipywidgets.readthedocs.io/en/latest/examples/Using%20Interact.html for more details." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xs=np.linspace(0, 6, 100)\n", + "\n", + "@interact(a=(1.0, 4.0, 0.01), b=(0, 10.0, 0.01), color=['red', 'green', 'blue'])\n", + "def update(a=3.6, b=4.3, color='blue'):\n", + " with fig.batch_update():\n", + " scatt.x=xs\n", + " scatt.y=np.sin(a*xs-b)\n", + " scatt.line.color=color" + ] + }, + { + "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.6.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/Overview.ipynb b/notebooks/Overview.ipynb new file mode 100644 index 0000000..1f96945 --- /dev/null +++ b/notebooks/Overview.ipynb @@ -0,0 +1,588 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Overview\n", + "\n", + "This notebook introduces some of the new features of plotly.py version 3\n", + "\n", + "## New Features\n", + "\n", + " - New `FigureWidget` class that is an ipywidget for displaying offline plotly figures.\n", + " - Traces can be added and updated interactively by simply assigning to properties\n", + " - The full Traces and Layout API is generated from the plotly schema to provide a great experience for interactive use in the notebook.\n", + " - Data validation covering the full API with clear, informative error messages.\n", + " - Jupyter friendly docstrings on constructor params and properties.\n", + " - Support for setting array properties as numpy arrays. When numpy arrays are used, ipywidgets binary serialization protocol is used to avoid converting these to JSON strings.\n", + " - Context manager API for animation." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# pandas\n", + "import pandas as pd\n", + "\n", + "# numpy\n", + "import numpy as np\n", + "\n", + "# scikit learn\n", + "from sklearn import datasets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load iris dataset\n", + "iris_data = datasets.load_iris()\n", + "feature_names = [name.replace(' (cm)', '').replace(' ', '_') for name in iris_data.feature_names]\n", + "iris_df = pd.DataFrame(iris_data.data, columns=feature_names)\n", + "iris_class = iris_data.target + 1\n", + "iris_df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create and display an empty FigureWidget\n", + "A FigureWidget behaves almost identically to a Figure but it is also an ipywidget that can be displayed directly in the notebook without calling `iplot`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import plotly.graph_objs as go" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "f1 = go.FigureWidget()\n", + "f1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tab completion \n", + "Entering ``f1.add_<tab>`` displays add methods for all of the supported trace types" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# f1.add_" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Entering ``f1.add_scatter(<tab>)`` displays the names of all of the top-level properties for the scatter trace type\n", + "\n", + "Entering ``f1.add_scatter(<shift+tab>)`` displays the signature pop-up. Expanding this pop-up reveals the method doc string which contains the descriptions of all of the top level properties" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# f1.add_scatter(" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Add scatter trace" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "scatt1 = f1.add_scatter(x=iris_df.sepal_length, y=iris_df.petal_width)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "scatt1.mode?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# That's not what we wanted, change the mode to 'markers'\n", + "scatt1.mode = 'markers'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Set size to 8\n", + "scatt1.marker.size = 8" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Color markers by iris class\n", + "scatt1.marker.color = iris_class" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Change colorscale\n", + "scatt1.marker.cmin = 0.5\n", + "scatt1.marker.cmax = 3.5\n", + "scatt1.marker.colorscale = [[0, 'red'], [0.33, 'red'], \n", + " [0.33, 'green'], [0.67, 'green'], \n", + " [0.67, 'blue'], [1.0, 'blue']]\n", + "\n", + "scatt1.marker.showscale = True" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Fix up colorscale ticks\n", + "scatt1.marker.colorbar.ticks = 'outside'\n", + "scatt1.marker.colorbar.tickvals = [1, 2, 3]\n", + "scatt1.marker.colorbar.ticktext = iris_data.target_names.tolist()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Set colorscale title\n", + "scatt1.marker.colorbar.title = 'Species'\n", + "scatt1.marker.colorbar.titlefont.size = 16\n", + "scatt1.marker.colorbar.titlefont.family = 'Rockwell'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Add axis labels\n", + "f1.layout.xaxis.title = 'sepal_length'\n", + "f1.layout.yaxis.title = 'petal_width'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Hover info\n", + "scatt1.text = iris_data.target_names[iris_data.target]\n", + "scatt1.hoverinfo = 'text+x+y'\n", + "f1.layout.hovermode = 'closest'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Animate marker size change" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Set marker size based on petal_length\n", + "with f1.batch_animate(duration=1000):\n", + " scatt1.marker.size = np.sqrt(iris_df.petal_length.values * 50)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Restore constant marker size\n", + "with f1.batch_animate(duration=1000):\n", + " scatt1.marker.size = 8" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Configure colorscale for brushing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "scatt1.marker.colorbar = None\n", + "scatt1.marker.colorscale = [[0, 'lightgray'], [0.5, 'lightgray'], [0.5, 'red'], [1, 'red']]\n", + "scatt1.marker.cmin = -0.5\n", + "scatt1.marker.cmax = 1.5\n", + "scatt1.marker.colorbar.ticks = 'outside'\n", + "scatt1.marker.colorbar.tickvals = [0, 1]\n", + "scatt1.marker.colorbar.ticktext = ['unselected', 'selected']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Reset colors to zeros (unselected)\n", + "scatt1.marker.color = np.zeros(iris_class.size)\n", + "selected = np.zeros(iris_class.size)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Configure brushing callback" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Assigning these variables here is not required. But doing so tricks Jupyter into \n", + "# providing property tab completion on the parameters to the brush function below\n", + "from plotly.callbacks import Points\n", + "trace, points = scatt1, Points()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def brush(trace, points, selector):\n", + " inds = np.array(points.point_inds)\n", + " if inds.size:\n", + " selected[inds] = 1\n", + " trace.marker.color = selected" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "scatt1.on_selection(brush)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now box or lasso select points on the figure and see them turn red" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Reset brush\n", + "selected = np.zeros(iris_class.size)\n", + "scatt1.marker.color = selected" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create second plot with different features" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "f2 = go.FigureWidget(data=[\n", + " go.Scatter(x=iris_df.petal_length, y=iris_df.sepal_width, mode='markers')])\n", + "f2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Set axis titles\n", + "f2.layout.xaxis.title = 'petal_length'\n", + "f2.layout.yaxis.title = 'sepal_width'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Grab trace reference\n", + "scatt2 = f2.data[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "scrolled": false + }, + "outputs": [], + "source": [ + "# Set marker styles / colorbars to match between figures\n", + "scatt2.marker = scatt1.marker" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Configure brush on both plots to update both plots\n", + "def brush(trace, points, state):\n", + " inds = np.array(points.point_inds)\n", + " if inds.size:\n", + " selected = scatt1.marker.color.copy()\n", + " selected[inds] = 1\n", + " scatt1.marker.color = selected\n", + " scatt2.marker.color = selected \n", + " \n", + "scatt1.on_selection(brush)\n", + "scatt2.on_selection(brush)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Reset brush\n", + "def reset_brush(btn):\n", + " selected = np.zeros(iris_class.size)\n", + " scatt1.marker.color = selected\n", + " scatt2.marker.color = selected" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# ipywidgets\n", + "from ipywidgets import HBox, VBox, Button" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create reset button\n", + "button = Button(description=\"clear\")\n", + "button.on_click(reset_brush)\n", + "button" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Hide colorbar for figure 1\n", + "scatt1.marker.showscale = False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Set dragmode to lasso for both plots\n", + "f1.layout.dragmode = 'lasso'\n", + "f2.layout.dragmode = 'lasso'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Display two figures and the reset button\n", + "f1.layout.width = 500\n", + "f2.layout.width = 500" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "VBox([HBox([f1, f2]), button])" + ] + } + ], + "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.6.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} -- GitLab