Format: application/octet-stream
⬇ Download File (487.3 KB)
   1  {
   2   "cells": [
   3    {
   4     "cell_type": "markdown",
   5     "metadata": {},
   6     "source": [
   7      "---\n",
   8      "\n",
   9      "_You are currently looking at **version 1.0** of this notebook. To download notebooks and datafiles, as well as get help on Jupyter notebooks in the Coursera platform, visit the [Jupyter Notebook FAQ](https://www.coursera.org/learn/python-machine-learning/resources/bANLa) course resource._\n",
  10      "\n",
  11      "---"
  12     ]
  13    },
  14    {
  15     "cell_type": "markdown",
  16     "metadata": {},
  17     "source": [
  18      "# Applied Machine Learning: Module 2 (Supervised Learning, Part I)"
  19     ]
  20    },
  21    {
  22     "cell_type": "markdown",
  23     "metadata": {},
  24     "source": [
  25      "## Preamble and Review"
  26     ]
  27    },
  28    {
  29     "cell_type": "code",
  30     "execution_count": 1,
  31     "metadata": {},
  32     "outputs": [
  33      {
  34       "name": "stdout",
  35       "output_type": "stream",
  36       "text": [
  37        "Accuracy of K-NN classifier on training set: 0.95\n",
  38        "Accuracy of K-NN classifier on test set: 1.00\n",
  39        "Predicted fruit type for  [[5.5, 2.2, 10, 0.7]]  is  orange\n"
  40       ]
  41      }
  42     ],
  43     "source": [
  44      "%matplotlib notebook\n",
  45      "import numpy as np\n",
  46      "import pandas as pd\n",
  47      "import seaborn as sn\n",
  48      "import matplotlib.pyplot as plt\n",
  49      "\n",
  50      "from sklearn.model_selection import train_test_split\n",
  51      "from sklearn.neighbors import KNeighborsClassifier\n",
  52      "\n",
  53      "np.set_printoptions(precision=2)\n",
  54      "\n",
  55      "\n",
  56      "fruits = pd.read_table('fruit_data_with_colors.txt')\n",
  57      "\n",
  58      "feature_names_fruits = ['height', 'width', 'mass', 'color_score']\n",
  59      "X_fruits = fruits[feature_names_fruits]\n",
  60      "y_fruits = fruits['fruit_label']\n",
  61      "target_names_fruits = ['apple', 'mandarin', 'orange', 'lemon']\n",
  62      "\n",
  63      "X_fruits_2d = fruits[['height', 'width']]\n",
  64      "y_fruits_2d = fruits['fruit_label']\n",
  65      "\n",
  66      "X_train, X_test, y_train, y_test = train_test_split(X_fruits, y_fruits, random_state=0)\n",
  67      "\n",
  68      "from sklearn.preprocessing import MinMaxScaler\n",
  69      "scaler = MinMaxScaler()\n",
  70      "X_train_scaled = scaler.fit_transform(X_train)\n",
  71      "# we must apply the scaling to the test set that we computed for the training set\n",
  72      "X_test_scaled = scaler.transform(X_test)\n",
  73      "\n",
  74      "knn = KNeighborsClassifier(n_neighbors = 5)\n",
  75      "knn.fit(X_train_scaled, y_train)\n",
  76      "print('Accuracy of K-NN classifier on training set: {:.2f}'\n",
  77      "     .format(knn.score(X_train_scaled, y_train)))\n",
  78      "print('Accuracy of K-NN classifier on test set: {:.2f}'\n",
  79      "     .format(knn.score(X_test_scaled, y_test)))\n",
  80      "\n",
  81      "example_fruit = [[5.5, 2.2, 10, 0.70]]\n",
  82      "print('Predicted fruit type for ', example_fruit, ' is ', \n",
  83      "      target_names_fruits[knn.predict(example_fruit)[0]-1])"
  84     ]
  85    },
  86    {
  87     "cell_type": "markdown",
  88     "metadata": {},
  89     "source": [
  90      "## Datasets"
  91     ]
  92    },
  93    {
  94     "cell_type": "code",
  95     "execution_count": 2,
  96     "metadata": {
  97      "scrolled": false
  98     },
  99     "outputs": [
 100      {
 101       "data": {
 102        "application/javascript": [
 103         "/* Put everything inside the global mpl namespace */\n",
 104         "/* global mpl */\n",
 105         "window.mpl = {};\n",
 106         "\n",
 107         "mpl.get_websocket_type = function () {\n",
 108         "    if (typeof WebSocket !== 'undefined') {\n",
 109         "        return WebSocket;\n",
 110         "    } else if (typeof MozWebSocket !== 'undefined') {\n",
 111         "        return MozWebSocket;\n",
 112         "    } else {\n",
 113         "        alert(\n",
 114         "            'Your browser does not have WebSocket support. ' +\n",
 115         "                'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
 116         "                'Firefox 4 and 5 are also supported but you ' +\n",
 117         "                'have to enable WebSockets in about:config.'\n",
 118         "        );\n",
 119         "    }\n",
 120         "};\n",
 121         "\n",
 122         "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n",
 123         "    this.id = figure_id;\n",
 124         "\n",
 125         "    this.ws = websocket;\n",
 126         "\n",
 127         "    this.supports_binary = this.ws.binaryType !== undefined;\n",
 128         "\n",
 129         "    if (!this.supports_binary) {\n",
 130         "        var warnings = document.getElementById('mpl-warnings');\n",
 131         "        if (warnings) {\n",
 132         "            warnings.style.display = 'block';\n",
 133         "            warnings.textContent =\n",
 134         "                'This browser does not support binary websocket messages. ' +\n",
 135         "                'Performance may be slow.';\n",
 136         "        }\n",
 137         "    }\n",
 138         "\n",
 139         "    this.imageObj = new Image();\n",
 140         "\n",
 141         "    this.context = undefined;\n",
 142         "    this.message = undefined;\n",
 143         "    this.canvas = undefined;\n",
 144         "    this.rubberband_canvas = undefined;\n",
 145         "    this.rubberband_context = undefined;\n",
 146         "    this.format_dropdown = undefined;\n",
 147         "\n",
 148         "    this.image_mode = 'full';\n",
 149         "\n",
 150         "    this.root = document.createElement('div');\n",
 151         "    this.root.setAttribute('style', 'display: inline-block');\n",
 152         "    this._root_extra_style(this.root);\n",
 153         "\n",
 154         "    parent_element.appendChild(this.root);\n",
 155         "\n",
 156         "    this._init_header(this);\n",
 157         "    this._init_canvas(this);\n",
 158         "    this._init_toolbar(this);\n",
 159         "\n",
 160         "    var fig = this;\n",
 161         "\n",
 162         "    this.waiting = false;\n",
 163         "\n",
 164         "    this.ws.onopen = function () {\n",
 165         "        fig.send_message('supports_binary', { value: fig.supports_binary });\n",
 166         "        fig.send_message('send_image_mode', {});\n",
 167         "        if (fig.ratio !== 1) {\n",
 168         "            fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n",
 169         "        }\n",
 170         "        fig.send_message('refresh', {});\n",
 171         "    };\n",
 172         "\n",
 173         "    this.imageObj.onload = function () {\n",
 174         "        if (fig.image_mode === 'full') {\n",
 175         "            // Full images could contain transparency (where diff images\n",
 176         "            // almost always do), so we need to clear the canvas so that\n",
 177         "            // there is no ghosting.\n",
 178         "            fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
 179         "        }\n",
 180         "        fig.context.drawImage(fig.imageObj, 0, 0);\n",
 181         "    };\n",
 182         "\n",
 183         "    this.imageObj.onunload = function () {\n",
 184         "        fig.ws.close();\n",
 185         "    };\n",
 186         "\n",
 187         "    this.ws.onmessage = this._make_on_message_function(this);\n",
 188         "\n",
 189         "    this.ondownload = ondownload;\n",
 190         "};\n",
 191         "\n",
 192         "mpl.figure.prototype._init_header = function () {\n",
 193         "    var titlebar = document.createElement('div');\n",
 194         "    titlebar.classList =\n",
 195         "        'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n",
 196         "    var titletext = document.createElement('div');\n",
 197         "    titletext.classList = 'ui-dialog-title';\n",
 198         "    titletext.setAttribute(\n",
 199         "        'style',\n",
 200         "        'width: 100%; text-align: center; padding: 3px;'\n",
 201         "    );\n",
 202         "    titlebar.appendChild(titletext);\n",
 203         "    this.root.appendChild(titlebar);\n",
 204         "    this.header = titletext;\n",
 205         "};\n",
 206         "\n",
 207         "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n",
 208         "\n",
 209         "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n",
 210         "\n",
 211         "mpl.figure.prototype._init_canvas = function () {\n",
 212         "    var fig = this;\n",
 213         "\n",
 214         "    var canvas_div = (this.canvas_div = document.createElement('div'));\n",
 215         "    canvas_div.setAttribute(\n",
 216         "        'style',\n",
 217         "        'border: 1px solid #ddd;' +\n",
 218         "            'box-sizing: content-box;' +\n",
 219         "            'clear: both;' +\n",
 220         "            'min-height: 1px;' +\n",
 221         "            'min-width: 1px;' +\n",
 222         "            'outline: 0;' +\n",
 223         "            'overflow: hidden;' +\n",
 224         "            'position: relative;' +\n",
 225         "            'resize: both;'\n",
 226         "    );\n",
 227         "\n",
 228         "    function on_keyboard_event_closure(name) {\n",
 229         "        return function (event) {\n",
 230         "            return fig.key_event(event, name);\n",
 231         "        };\n",
 232         "    }\n",
 233         "\n",
 234         "    canvas_div.addEventListener(\n",
 235         "        'keydown',\n",
 236         "        on_keyboard_event_closure('key_press')\n",
 237         "    );\n",
 238         "    canvas_div.addEventListener(\n",
 239         "        'keyup',\n",
 240         "        on_keyboard_event_closure('key_release')\n",
 241         "    );\n",
 242         "\n",
 243         "    this._canvas_extra_style(canvas_div);\n",
 244         "    this.root.appendChild(canvas_div);\n",
 245         "\n",
 246         "    var canvas = (this.canvas = document.createElement('canvas'));\n",
 247         "    canvas.classList.add('mpl-canvas');\n",
 248         "    canvas.setAttribute('style', 'box-sizing: content-box;');\n",
 249         "\n",
 250         "    this.context = canvas.getContext('2d');\n",
 251         "\n",
 252         "    var backingStore =\n",
 253         "        this.context.backingStorePixelRatio ||\n",
 254         "        this.context.webkitBackingStorePixelRatio ||\n",
 255         "        this.context.mozBackingStorePixelRatio ||\n",
 256         "        this.context.msBackingStorePixelRatio ||\n",
 257         "        this.context.oBackingStorePixelRatio ||\n",
 258         "        this.context.backingStorePixelRatio ||\n",
 259         "        1;\n",
 260         "\n",
 261         "    this.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
 262         "\n",
 263         "    var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n",
 264         "        'canvas'\n",
 265         "    ));\n",
 266         "    rubberband_canvas.setAttribute(\n",
 267         "        'style',\n",
 268         "        'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n",
 269         "    );\n",
 270         "\n",
 271         "    // Apply a ponyfill if ResizeObserver is not implemented by browser.\n",
 272         "    if (this.ResizeObserver === undefined) {\n",
 273         "        if (window.ResizeObserver !== undefined) {\n",
 274         "            this.ResizeObserver = window.ResizeObserver;\n",
 275         "        } else {\n",
 276         "            var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n",
 277         "            this.ResizeObserver = obs.ResizeObserver;\n",
 278         "        }\n",
 279         "    }\n",
 280         "\n",
 281         "    this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n",
 282         "        var nentries = entries.length;\n",
 283         "        for (var i = 0; i < nentries; i++) {\n",
 284         "            var entry = entries[i];\n",
 285         "            var width, height;\n",
 286         "            if (entry.contentBoxSize) {\n",
 287         "                if (entry.contentBoxSize instanceof Array) {\n",
 288         "                    // Chrome 84 implements new version of spec.\n",
 289         "                    width = entry.contentBoxSize[0].inlineSize;\n",
 290         "                    height = entry.contentBoxSize[0].blockSize;\n",
 291         "                } else {\n",
 292         "                    // Firefox implements old version of spec.\n",
 293         "                    width = entry.contentBoxSize.inlineSize;\n",
 294         "                    height = entry.contentBoxSize.blockSize;\n",
 295         "                }\n",
 296         "            } else {\n",
 297         "                // Chrome <84 implements even older version of spec.\n",
 298         "                width = entry.contentRect.width;\n",
 299         "                height = entry.contentRect.height;\n",
 300         "            }\n",
 301         "\n",
 302         "            // Keep the size of the canvas and rubber band canvas in sync with\n",
 303         "            // the canvas container.\n",
 304         "            if (entry.devicePixelContentBoxSize) {\n",
 305         "                // Chrome 84 implements new version of spec.\n",
 306         "                canvas.setAttribute(\n",
 307         "                    'width',\n",
 308         "                    entry.devicePixelContentBoxSize[0].inlineSize\n",
 309         "                );\n",
 310         "                canvas.setAttribute(\n",
 311         "                    'height',\n",
 312         "                    entry.devicePixelContentBoxSize[0].blockSize\n",
 313         "                );\n",
 314         "            } else {\n",
 315         "                canvas.setAttribute('width', width * fig.ratio);\n",
 316         "                canvas.setAttribute('height', height * fig.ratio);\n",
 317         "            }\n",
 318         "            canvas.setAttribute(\n",
 319         "                'style',\n",
 320         "                'width: ' + width + 'px; height: ' + height + 'px;'\n",
 321         "            );\n",
 322         "\n",
 323         "            rubberband_canvas.setAttribute('width', width);\n",
 324         "            rubberband_canvas.setAttribute('height', height);\n",
 325         "\n",
 326         "            // And update the size in Python. We ignore the initial 0/0 size\n",
 327         "            // that occurs as the element is placed into the DOM, which should\n",
 328         "            // otherwise not happen due to the minimum size styling.\n",
 329         "            if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n",
 330         "                fig.request_resize(width, height);\n",
 331         "            }\n",
 332         "        }\n",
 333         "    });\n",
 334         "    this.resizeObserverInstance.observe(canvas_div);\n",
 335         "\n",
 336         "    function on_mouse_event_closure(name) {\n",
 337         "        return function (event) {\n",
 338         "            return fig.mouse_event(event, name);\n",
 339         "        };\n",
 340         "    }\n",
 341         "\n",
 342         "    rubberband_canvas.addEventListener(\n",
 343         "        'mousedown',\n",
 344         "        on_mouse_event_closure('button_press')\n",
 345         "    );\n",
 346         "    rubberband_canvas.addEventListener(\n",
 347         "        'mouseup',\n",
 348         "        on_mouse_event_closure('button_release')\n",
 349         "    );\n",
 350         "    // Throttle sequential mouse events to 1 every 20ms.\n",
 351         "    rubberband_canvas.addEventListener(\n",
 352         "        'mousemove',\n",
 353         "        on_mouse_event_closure('motion_notify')\n",
 354         "    );\n",
 355         "\n",
 356         "    rubberband_canvas.addEventListener(\n",
 357         "        'mouseenter',\n",
 358         "        on_mouse_event_closure('figure_enter')\n",
 359         "    );\n",
 360         "    rubberband_canvas.addEventListener(\n",
 361         "        'mouseleave',\n",
 362         "        on_mouse_event_closure('figure_leave')\n",
 363         "    );\n",
 364         "\n",
 365         "    canvas_div.addEventListener('wheel', function (event) {\n",
 366         "        if (event.deltaY < 0) {\n",
 367         "            event.step = 1;\n",
 368         "        } else {\n",
 369         "            event.step = -1;\n",
 370         "        }\n",
 371         "        on_mouse_event_closure('scroll')(event);\n",
 372         "    });\n",
 373         "\n",
 374         "    canvas_div.appendChild(canvas);\n",
 375         "    canvas_div.appendChild(rubberband_canvas);\n",
 376         "\n",
 377         "    this.rubberband_context = rubberband_canvas.getContext('2d');\n",
 378         "    this.rubberband_context.strokeStyle = '#000000';\n",
 379         "\n",
 380         "    this._resize_canvas = function (width, height, forward) {\n",
 381         "        if (forward) {\n",
 382         "            canvas_div.style.width = width + 'px';\n",
 383         "            canvas_div.style.height = height + 'px';\n",
 384         "        }\n",
 385         "    };\n",
 386         "\n",
 387         "    // Disable right mouse context menu.\n",
 388         "    this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n",
 389         "        event.preventDefault();\n",
 390         "        return false;\n",
 391         "    });\n",
 392         "\n",
 393         "    function set_focus() {\n",
 394         "        canvas.focus();\n",
 395         "        canvas_div.focus();\n",
 396         "    }\n",
 397         "\n",
 398         "    window.setTimeout(set_focus, 100);\n",
 399         "};\n",
 400         "\n",
 401         "mpl.figure.prototype._init_toolbar = function () {\n",
 402         "    var fig = this;\n",
 403         "\n",
 404         "    var toolbar = document.createElement('div');\n",
 405         "    toolbar.classList = 'mpl-toolbar';\n",
 406         "    this.root.appendChild(toolbar);\n",
 407         "\n",
 408         "    function on_click_closure(name) {\n",
 409         "        return function (_event) {\n",
 410         "            return fig.toolbar_button_onclick(name);\n",
 411         "        };\n",
 412         "    }\n",
 413         "\n",
 414         "    function on_mouseover_closure(tooltip) {\n",
 415         "        return function (event) {\n",
 416         "            if (!event.currentTarget.disabled) {\n",
 417         "                return fig.toolbar_button_onmouseover(tooltip);\n",
 418         "            }\n",
 419         "        };\n",
 420         "    }\n",
 421         "\n",
 422         "    fig.buttons = {};\n",
 423         "    var buttonGroup = document.createElement('div');\n",
 424         "    buttonGroup.classList = 'mpl-button-group';\n",
 425         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
 426         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
 427         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
 428         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
 429         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
 430         "\n",
 431         "        if (!name) {\n",
 432         "            /* Instead of a spacer, we start a new button group. */\n",
 433         "            if (buttonGroup.hasChildNodes()) {\n",
 434         "                toolbar.appendChild(buttonGroup);\n",
 435         "            }\n",
 436         "            buttonGroup = document.createElement('div');\n",
 437         "            buttonGroup.classList = 'mpl-button-group';\n",
 438         "            continue;\n",
 439         "        }\n",
 440         "\n",
 441         "        var button = (fig.buttons[name] = document.createElement('button'));\n",
 442         "        button.classList = 'mpl-widget';\n",
 443         "        button.setAttribute('role', 'button');\n",
 444         "        button.setAttribute('aria-disabled', 'false');\n",
 445         "        button.addEventListener('click', on_click_closure(method_name));\n",
 446         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
 447         "\n",
 448         "        var icon_img = document.createElement('img');\n",
 449         "        icon_img.src = '_images/' + image + '.png';\n",
 450         "        icon_img.srcset = '_images/' + image + '_large.png 2x';\n",
 451         "        icon_img.alt = tooltip;\n",
 452         "        button.appendChild(icon_img);\n",
 453         "\n",
 454         "        buttonGroup.appendChild(button);\n",
 455         "    }\n",
 456         "\n",
 457         "    if (buttonGroup.hasChildNodes()) {\n",
 458         "        toolbar.appendChild(buttonGroup);\n",
 459         "    }\n",
 460         "\n",
 461         "    var fmt_picker = document.createElement('select');\n",
 462         "    fmt_picker.classList = 'mpl-widget';\n",
 463         "    toolbar.appendChild(fmt_picker);\n",
 464         "    this.format_dropdown = fmt_picker;\n",
 465         "\n",
 466         "    for (var ind in mpl.extensions) {\n",
 467         "        var fmt = mpl.extensions[ind];\n",
 468         "        var option = document.createElement('option');\n",
 469         "        option.selected = fmt === mpl.default_extension;\n",
 470         "        option.innerHTML = fmt;\n",
 471         "        fmt_picker.appendChild(option);\n",
 472         "    }\n",
 473         "\n",
 474         "    var status_bar = document.createElement('span');\n",
 475         "    status_bar.classList = 'mpl-message';\n",
 476         "    toolbar.appendChild(status_bar);\n",
 477         "    this.message = status_bar;\n",
 478         "};\n",
 479         "\n",
 480         "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n",
 481         "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
 482         "    // which will in turn request a refresh of the image.\n",
 483         "    this.send_message('resize', { width: x_pixels, height: y_pixels });\n",
 484         "};\n",
 485         "\n",
 486         "mpl.figure.prototype.send_message = function (type, properties) {\n",
 487         "    properties['type'] = type;\n",
 488         "    properties['figure_id'] = this.id;\n",
 489         "    this.ws.send(JSON.stringify(properties));\n",
 490         "};\n",
 491         "\n",
 492         "mpl.figure.prototype.send_draw_message = function () {\n",
 493         "    if (!this.waiting) {\n",
 494         "        this.waiting = true;\n",
 495         "        this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n",
 496         "    }\n",
 497         "};\n",
 498         "\n",
 499         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
 500         "    var format_dropdown = fig.format_dropdown;\n",
 501         "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
 502         "    fig.ondownload(fig, format);\n",
 503         "};\n",
 504         "\n",
 505         "mpl.figure.prototype.handle_resize = function (fig, msg) {\n",
 506         "    var size = msg['size'];\n",
 507         "    if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n",
 508         "        fig._resize_canvas(size[0], size[1], msg['forward']);\n",
 509         "        fig.send_message('refresh', {});\n",
 510         "    }\n",
 511         "};\n",
 512         "\n",
 513         "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n",
 514         "    var x0 = msg['x0'] / fig.ratio;\n",
 515         "    var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n",
 516         "    var x1 = msg['x1'] / fig.ratio;\n",
 517         "    var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n",
 518         "    x0 = Math.floor(x0) + 0.5;\n",
 519         "    y0 = Math.floor(y0) + 0.5;\n",
 520         "    x1 = Math.floor(x1) + 0.5;\n",
 521         "    y1 = Math.floor(y1) + 0.5;\n",
 522         "    var min_x = Math.min(x0, x1);\n",
 523         "    var min_y = Math.min(y0, y1);\n",
 524         "    var width = Math.abs(x1 - x0);\n",
 525         "    var height = Math.abs(y1 - y0);\n",
 526         "\n",
 527         "    fig.rubberband_context.clearRect(\n",
 528         "        0,\n",
 529         "        0,\n",
 530         "        fig.canvas.width / fig.ratio,\n",
 531         "        fig.canvas.height / fig.ratio\n",
 532         "    );\n",
 533         "\n",
 534         "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
 535         "};\n",
 536         "\n",
 537         "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n",
 538         "    // Updates the figure title.\n",
 539         "    fig.header.textContent = msg['label'];\n",
 540         "};\n",
 541         "\n",
 542         "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n",
 543         "    var cursor = msg['cursor'];\n",
 544         "    switch (cursor) {\n",
 545         "        case 0:\n",
 546         "            cursor = 'pointer';\n",
 547         "            break;\n",
 548         "        case 1:\n",
 549         "            cursor = 'default';\n",
 550         "            break;\n",
 551         "        case 2:\n",
 552         "            cursor = 'crosshair';\n",
 553         "            break;\n",
 554         "        case 3:\n",
 555         "            cursor = 'move';\n",
 556         "            break;\n",
 557         "    }\n",
 558         "    fig.rubberband_canvas.style.cursor = cursor;\n",
 559         "};\n",
 560         "\n",
 561         "mpl.figure.prototype.handle_message = function (fig, msg) {\n",
 562         "    fig.message.textContent = msg['message'];\n",
 563         "};\n",
 564         "\n",
 565         "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n",
 566         "    // Request the server to send over a new figure.\n",
 567         "    fig.send_draw_message();\n",
 568         "};\n",
 569         "\n",
 570         "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n",
 571         "    fig.image_mode = msg['mode'];\n",
 572         "};\n",
 573         "\n",
 574         "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n",
 575         "    for (var key in msg) {\n",
 576         "        if (!(key in fig.buttons)) {\n",
 577         "            continue;\n",
 578         "        }\n",
 579         "        fig.buttons[key].disabled = !msg[key];\n",
 580         "        fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n",
 581         "    }\n",
 582         "};\n",
 583         "\n",
 584         "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n",
 585         "    if (msg['mode'] === 'PAN') {\n",
 586         "        fig.buttons['Pan'].classList.add('active');\n",
 587         "        fig.buttons['Zoom'].classList.remove('active');\n",
 588         "    } else if (msg['mode'] === 'ZOOM') {\n",
 589         "        fig.buttons['Pan'].classList.remove('active');\n",
 590         "        fig.buttons['Zoom'].classList.add('active');\n",
 591         "    } else {\n",
 592         "        fig.buttons['Pan'].classList.remove('active');\n",
 593         "        fig.buttons['Zoom'].classList.remove('active');\n",
 594         "    }\n",
 595         "};\n",
 596         "\n",
 597         "mpl.figure.prototype.updated_canvas_event = function () {\n",
 598         "    // Called whenever the canvas gets updated.\n",
 599         "    this.send_message('ack', {});\n",
 600         "};\n",
 601         "\n",
 602         "// A function to construct a web socket function for onmessage handling.\n",
 603         "// Called in the figure constructor.\n",
 604         "mpl.figure.prototype._make_on_message_function = function (fig) {\n",
 605         "    return function socket_on_message(evt) {\n",
 606         "        if (evt.data instanceof Blob) {\n",
 607         "            /* FIXME: We get \"Resource interpreted as Image but\n",
 608         "             * transferred with MIME type text/plain:\" errors on\n",
 609         "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
 610         "             * to be part of the websocket stream */\n",
 611         "            evt.data.type = 'image/png';\n",
 612         "\n",
 613         "            /* Free the memory for the previous frames */\n",
 614         "            if (fig.imageObj.src) {\n",
 615         "                (window.URL || window.webkitURL).revokeObjectURL(\n",
 616         "                    fig.imageObj.src\n",
 617         "                );\n",
 618         "            }\n",
 619         "\n",
 620         "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
 621         "                evt.data\n",
 622         "            );\n",
 623         "            fig.updated_canvas_event();\n",
 624         "            fig.waiting = false;\n",
 625         "            return;\n",
 626         "        } else if (\n",
 627         "            typeof evt.data === 'string' &&\n",
 628         "            evt.data.slice(0, 21) === 'data:image/png;base64'\n",
 629         "        ) {\n",
 630         "            fig.imageObj.src = evt.data;\n",
 631         "            fig.updated_canvas_event();\n",
 632         "            fig.waiting = false;\n",
 633         "            return;\n",
 634         "        }\n",
 635         "\n",
 636         "        var msg = JSON.parse(evt.data);\n",
 637         "        var msg_type = msg['type'];\n",
 638         "\n",
 639         "        // Call the  \"handle_{type}\" callback, which takes\n",
 640         "        // the figure and JSON message as its only arguments.\n",
 641         "        try {\n",
 642         "            var callback = fig['handle_' + msg_type];\n",
 643         "        } catch (e) {\n",
 644         "            console.log(\n",
 645         "                \"No handler for the '\" + msg_type + \"' message type: \",\n",
 646         "                msg\n",
 647         "            );\n",
 648         "            return;\n",
 649         "        }\n",
 650         "\n",
 651         "        if (callback) {\n",
 652         "            try {\n",
 653         "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
 654         "                callback(fig, msg);\n",
 655         "            } catch (e) {\n",
 656         "                console.log(\n",
 657         "                    \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n",
 658         "                    e,\n",
 659         "                    e.stack,\n",
 660         "                    msg\n",
 661         "                );\n",
 662         "            }\n",
 663         "        }\n",
 664         "    };\n",
 665         "};\n",
 666         "\n",
 667         "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
 668         "mpl.findpos = function (e) {\n",
 669         "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
 670         "    var targ;\n",
 671         "    if (!e) {\n",
 672         "        e = window.event;\n",
 673         "    }\n",
 674         "    if (e.target) {\n",
 675         "        targ = e.target;\n",
 676         "    } else if (e.srcElement) {\n",
 677         "        targ = e.srcElement;\n",
 678         "    }\n",
 679         "    if (targ.nodeType === 3) {\n",
 680         "        // defeat Safari bug\n",
 681         "        targ = targ.parentNode;\n",
 682         "    }\n",
 683         "\n",
 684         "    // pageX,Y are the mouse positions relative to the document\n",
 685         "    var boundingRect = targ.getBoundingClientRect();\n",
 686         "    var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n",
 687         "    var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n",
 688         "\n",
 689         "    return { x: x, y: y };\n",
 690         "};\n",
 691         "\n",
 692         "/*\n",
 693         " * return a copy of an object with only non-object keys\n",
 694         " * we need this to avoid circular references\n",
 695         " * http://stackoverflow.com/a/24161582/3208463\n",
 696         " */\n",
 697         "function simpleKeys(original) {\n",
 698         "    return Object.keys(original).reduce(function (obj, key) {\n",
 699         "        if (typeof original[key] !== 'object') {\n",
 700         "            obj[key] = original[key];\n",
 701         "        }\n",
 702         "        return obj;\n",
 703         "    }, {});\n",
 704         "}\n",
 705         "\n",
 706         "mpl.figure.prototype.mouse_event = function (event, name) {\n",
 707         "    var canvas_pos = mpl.findpos(event);\n",
 708         "\n",
 709         "    if (name === 'button_press') {\n",
 710         "        this.canvas.focus();\n",
 711         "        this.canvas_div.focus();\n",
 712         "    }\n",
 713         "\n",
 714         "    var x = canvas_pos.x * this.ratio;\n",
 715         "    var y = canvas_pos.y * this.ratio;\n",
 716         "\n",
 717         "    this.send_message(name, {\n",
 718         "        x: x,\n",
 719         "        y: y,\n",
 720         "        button: event.button,\n",
 721         "        step: event.step,\n",
 722         "        guiEvent: simpleKeys(event),\n",
 723         "    });\n",
 724         "\n",
 725         "    /* This prevents the web browser from automatically changing to\n",
 726         "     * the text insertion cursor when the button is pressed.  We want\n",
 727         "     * to control all of the cursor setting manually through the\n",
 728         "     * 'cursor' event from matplotlib */\n",
 729         "    event.preventDefault();\n",
 730         "    return false;\n",
 731         "};\n",
 732         "\n",
 733         "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n",
 734         "    // Handle any extra behaviour associated with a key event\n",
 735         "};\n",
 736         "\n",
 737         "mpl.figure.prototype.key_event = function (event, name) {\n",
 738         "    // Prevent repeat events\n",
 739         "    if (name === 'key_press') {\n",
 740         "        if (event.which === this._key) {\n",
 741         "            return;\n",
 742         "        } else {\n",
 743         "            this._key = event.which;\n",
 744         "        }\n",
 745         "    }\n",
 746         "    if (name === 'key_release') {\n",
 747         "        this._key = null;\n",
 748         "    }\n",
 749         "\n",
 750         "    var value = '';\n",
 751         "    if (event.ctrlKey && event.which !== 17) {\n",
 752         "        value += 'ctrl+';\n",
 753         "    }\n",
 754         "    if (event.altKey && event.which !== 18) {\n",
 755         "        value += 'alt+';\n",
 756         "    }\n",
 757         "    if (event.shiftKey && event.which !== 16) {\n",
 758         "        value += 'shift+';\n",
 759         "    }\n",
 760         "\n",
 761         "    value += 'k';\n",
 762         "    value += event.which.toString();\n",
 763         "\n",
 764         "    this._key_event_extra(event, name);\n",
 765         "\n",
 766         "    this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n",
 767         "    return false;\n",
 768         "};\n",
 769         "\n",
 770         "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n",
 771         "    if (name === 'download') {\n",
 772         "        this.handle_save(this, null);\n",
 773         "    } else {\n",
 774         "        this.send_message('toolbar_button', { name: name });\n",
 775         "    }\n",
 776         "};\n",
 777         "\n",
 778         "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n",
 779         "    this.message.textContent = tooltip;\n",
 780         "};\n",
 781         "\n",
 782         "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n",
 783         "// prettier-ignore\n",
 784         "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n",
 785         "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
 786         "\n",
 787         "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
 788         "\n",
 789         "mpl.default_extension = \"png\";/* global mpl */\n",
 790         "\n",
 791         "var comm_websocket_adapter = function (comm) {\n",
 792         "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
 793         "    // object with the appropriate methods. Currently this is a non binary\n",
 794         "    // socket, so there is still some room for performance tuning.\n",
 795         "    var ws = {};\n",
 796         "\n",
 797         "    ws.close = function () {\n",
 798         "        comm.close();\n",
 799         "    };\n",
 800         "    ws.send = function (m) {\n",
 801         "        //console.log('sending', m);\n",
 802         "        comm.send(m);\n",
 803         "    };\n",
 804         "    // Register the callback with on_msg.\n",
 805         "    comm.on_msg(function (msg) {\n",
 806         "        //console.log('receiving', msg['content']['data'], msg);\n",
 807         "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
 808         "        ws.onmessage(msg['content']['data']);\n",
 809         "    });\n",
 810         "    return ws;\n",
 811         "};\n",
 812         "\n",
 813         "mpl.mpl_figure_comm = function (comm, msg) {\n",
 814         "    // This is the function which gets called when the mpl process\n",
 815         "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
 816         "\n",
 817         "    var id = msg.content.data.id;\n",
 818         "    // Get hold of the div created by the display call when the Comm\n",
 819         "    // socket was opened in Python.\n",
 820         "    var element = document.getElementById(id);\n",
 821         "    var ws_proxy = comm_websocket_adapter(comm);\n",
 822         "\n",
 823         "    function ondownload(figure, _format) {\n",
 824         "        window.open(figure.canvas.toDataURL());\n",
 825         "    }\n",
 826         "\n",
 827         "    var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n",
 828         "\n",
 829         "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
 830         "    // web socket which is closed, not our websocket->open comm proxy.\n",
 831         "    ws_proxy.onopen();\n",
 832         "\n",
 833         "    fig.parent_element = element;\n",
 834         "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
 835         "    if (!fig.cell_info) {\n",
 836         "        console.error('Failed to find cell for figure', id, fig);\n",
 837         "        return;\n",
 838         "    }\n",
 839         "    fig.cell_info[0].output_area.element.on(\n",
 840         "        'cleared',\n",
 841         "        { fig: fig },\n",
 842         "        fig._remove_fig_handler\n",
 843         "    );\n",
 844         "};\n",
 845         "\n",
 846         "mpl.figure.prototype.handle_close = function (fig, msg) {\n",
 847         "    var width = fig.canvas.width / fig.ratio;\n",
 848         "    fig.cell_info[0].output_area.element.off(\n",
 849         "        'cleared',\n",
 850         "        fig._remove_fig_handler\n",
 851         "    );\n",
 852         "    fig.resizeObserverInstance.unobserve(fig.canvas_div);\n",
 853         "\n",
 854         "    // Update the output cell to use the data from the current canvas.\n",
 855         "    fig.push_to_output();\n",
 856         "    var dataURL = fig.canvas.toDataURL();\n",
 857         "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
 858         "    // the notebook keyboard shortcuts fail.\n",
 859         "    IPython.keyboard_manager.enable();\n",
 860         "    fig.parent_element.innerHTML =\n",
 861         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
 862         "    fig.close_ws(fig, msg);\n",
 863         "};\n",
 864         "\n",
 865         "mpl.figure.prototype.close_ws = function (fig, msg) {\n",
 866         "    fig.send_message('closing', msg);\n",
 867         "    // fig.ws.close()\n",
 868         "};\n",
 869         "\n",
 870         "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n",
 871         "    // Turn the data on the canvas into data in the output cell.\n",
 872         "    var width = this.canvas.width / this.ratio;\n",
 873         "    var dataURL = this.canvas.toDataURL();\n",
 874         "    this.cell_info[1]['text/html'] =\n",
 875         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
 876         "};\n",
 877         "\n",
 878         "mpl.figure.prototype.updated_canvas_event = function () {\n",
 879         "    // Tell IPython that the notebook contents must change.\n",
 880         "    IPython.notebook.set_dirty(true);\n",
 881         "    this.send_message('ack', {});\n",
 882         "    var fig = this;\n",
 883         "    // Wait a second, then push the new image to the DOM so\n",
 884         "    // that it is saved nicely (might be nice to debounce this).\n",
 885         "    setTimeout(function () {\n",
 886         "        fig.push_to_output();\n",
 887         "    }, 1000);\n",
 888         "};\n",
 889         "\n",
 890         "mpl.figure.prototype._init_toolbar = function () {\n",
 891         "    var fig = this;\n",
 892         "\n",
 893         "    var toolbar = document.createElement('div');\n",
 894         "    toolbar.classList = 'btn-toolbar';\n",
 895         "    this.root.appendChild(toolbar);\n",
 896         "\n",
 897         "    function on_click_closure(name) {\n",
 898         "        return function (_event) {\n",
 899         "            return fig.toolbar_button_onclick(name);\n",
 900         "        };\n",
 901         "    }\n",
 902         "\n",
 903         "    function on_mouseover_closure(tooltip) {\n",
 904         "        return function (event) {\n",
 905         "            if (!event.currentTarget.disabled) {\n",
 906         "                return fig.toolbar_button_onmouseover(tooltip);\n",
 907         "            }\n",
 908         "        };\n",
 909         "    }\n",
 910         "\n",
 911         "    fig.buttons = {};\n",
 912         "    var buttonGroup = document.createElement('div');\n",
 913         "    buttonGroup.classList = 'btn-group';\n",
 914         "    var button;\n",
 915         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
 916         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
 917         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
 918         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
 919         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
 920         "\n",
 921         "        if (!name) {\n",
 922         "            /* Instead of a spacer, we start a new button group. */\n",
 923         "            if (buttonGroup.hasChildNodes()) {\n",
 924         "                toolbar.appendChild(buttonGroup);\n",
 925         "            }\n",
 926         "            buttonGroup = document.createElement('div');\n",
 927         "            buttonGroup.classList = 'btn-group';\n",
 928         "            continue;\n",
 929         "        }\n",
 930         "\n",
 931         "        button = fig.buttons[name] = document.createElement('button');\n",
 932         "        button.classList = 'btn btn-default';\n",
 933         "        button.href = '#';\n",
 934         "        button.title = name;\n",
 935         "        button.innerHTML = '<i class=\"fa ' + image + ' fa-lg\"></i>';\n",
 936         "        button.addEventListener('click', on_click_closure(method_name));\n",
 937         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
 938         "        buttonGroup.appendChild(button);\n",
 939         "    }\n",
 940         "\n",
 941         "    if (buttonGroup.hasChildNodes()) {\n",
 942         "        toolbar.appendChild(buttonGroup);\n",
 943         "    }\n",
 944         "\n",
 945         "    // Add the status bar.\n",
 946         "    var status_bar = document.createElement('span');\n",
 947         "    status_bar.classList = 'mpl-message pull-right';\n",
 948         "    toolbar.appendChild(status_bar);\n",
 949         "    this.message = status_bar;\n",
 950         "\n",
 951         "    // Add the close button to the window.\n",
 952         "    var buttongrp = document.createElement('div');\n",
 953         "    buttongrp.classList = 'btn-group inline pull-right';\n",
 954         "    button = document.createElement('button');\n",
 955         "    button.classList = 'btn btn-mini btn-primary';\n",
 956         "    button.href = '#';\n",
 957         "    button.title = 'Stop Interaction';\n",
 958         "    button.innerHTML = '<i class=\"fa fa-power-off icon-remove icon-large\"></i>';\n",
 959         "    button.addEventListener('click', function (_evt) {\n",
 960         "        fig.handle_close(fig, {});\n",
 961         "    });\n",
 962         "    button.addEventListener(\n",
 963         "        'mouseover',\n",
 964         "        on_mouseover_closure('Stop Interaction')\n",
 965         "    );\n",
 966         "    buttongrp.appendChild(button);\n",
 967         "    var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n",
 968         "    titlebar.insertBefore(buttongrp, titlebar.firstChild);\n",
 969         "};\n",
 970         "\n",
 971         "mpl.figure.prototype._remove_fig_handler = function (event) {\n",
 972         "    var fig = event.data.fig;\n",
 973         "    if (event.target !== this) {\n",
 974         "        // Ignore bubbled events from children.\n",
 975         "        return;\n",
 976         "    }\n",
 977         "    fig.close_ws(fig, {});\n",
 978         "};\n",
 979         "\n",
 980         "mpl.figure.prototype._root_extra_style = function (el) {\n",
 981         "    el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n",
 982         "};\n",
 983         "\n",
 984         "mpl.figure.prototype._canvas_extra_style = function (el) {\n",
 985         "    // this is important to make the div 'focusable\n",
 986         "    el.setAttribute('tabindex', 0);\n",
 987         "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
 988         "    // off when our div gets focus\n",
 989         "\n",
 990         "    // location in version 3\n",
 991         "    if (IPython.notebook.keyboard_manager) {\n",
 992         "        IPython.notebook.keyboard_manager.register_events(el);\n",
 993         "    } else {\n",
 994         "        // location in version 2\n",
 995         "        IPython.keyboard_manager.register_events(el);\n",
 996         "    }\n",
 997         "};\n",
 998         "\n",
 999         "mpl.figure.prototype._key_event_extra = function (event, _name) {\n",
1000         "    var manager = IPython.notebook.keyboard_manager;\n",
1001         "    if (!manager) {\n",
1002         "        manager = IPython.keyboard_manager;\n",
1003         "    }\n",
1004         "\n",
1005         "    // Check for shift+enter\n",
1006         "    if (event.shiftKey && event.which === 13) {\n",
1007         "        this.canvas_div.blur();\n",
1008         "        // select the cell after this one\n",
1009         "        var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
1010         "        IPython.notebook.select(index + 1);\n",
1011         "    }\n",
1012         "};\n",
1013         "\n",
1014         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
1015         "    fig.ondownload(fig, null);\n",
1016         "};\n",
1017         "\n",
1018         "mpl.find_output_cell = function (html_output) {\n",
1019         "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
1020         "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
1021         "    // IPython event is triggered only after the cells have been serialised, which for\n",
1022         "    // our purposes (turning an active figure into a static one), is too late.\n",
1023         "    var cells = IPython.notebook.get_cells();\n",
1024         "    var ncells = cells.length;\n",
1025         "    for (var i = 0; i < ncells; i++) {\n",
1026         "        var cell = cells[i];\n",
1027         "        if (cell.cell_type === 'code') {\n",
1028         "            for (var j = 0; j < cell.output_area.outputs.length; j++) {\n",
1029         "                var data = cell.output_area.outputs[j];\n",
1030         "                if (data.data) {\n",
1031         "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
1032         "                    data = data.data;\n",
1033         "                }\n",
1034         "                if (data['text/html'] === html_output) {\n",
1035         "                    return [cell, data, j];\n",
1036         "                }\n",
1037         "            }\n",
1038         "        }\n",
1039         "    }\n",
1040         "};\n",
1041         "\n",
1042         "// Register the function which deals with the matplotlib target/channel.\n",
1043         "// The kernel may be null if the page has been refreshed.\n",
1044         "if (IPython.notebook.kernel !== null) {\n",
1045         "    IPython.notebook.kernel.comm_manager.register_target(\n",
1046         "        'matplotlib',\n",
1047         "        mpl.mpl_figure_comm\n",
1048         "    );\n",
1049         "}\n"
1050        ],
1051        "text/plain": [
1052         "<IPython.core.display.Javascript object>"
1053        ]
1054       },
1055       "metadata": {},
1056       "output_type": "display_data"
1057      },
1058      {
1059       "data": {
1060        "text/html": [
1061         "<div id='beb48092-c450-45b4-bd2a-8f24de3b03ac'></div>"
1062        ],
1063        "text/plain": [
1064         "<IPython.core.display.HTML object>"
1065        ]
1066       },
1067       "metadata": {},
1068       "output_type": "display_data"
1069      },
1070      {
1071       "data": {
1072        "application/javascript": [
1073         "/* Put everything inside the global mpl namespace */\n",
1074         "/* global mpl */\n",
1075         "window.mpl = {};\n",
1076         "\n",
1077         "mpl.get_websocket_type = function () {\n",
1078         "    if (typeof WebSocket !== 'undefined') {\n",
1079         "        return WebSocket;\n",
1080         "    } else if (typeof MozWebSocket !== 'undefined') {\n",
1081         "        return MozWebSocket;\n",
1082         "    } else {\n",
1083         "        alert(\n",
1084         "            'Your browser does not have WebSocket support. ' +\n",
1085         "                'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
1086         "                'Firefox 4 and 5 are also supported but you ' +\n",
1087         "                'have to enable WebSockets in about:config.'\n",
1088         "        );\n",
1089         "    }\n",
1090         "};\n",
1091         "\n",
1092         "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n",
1093         "    this.id = figure_id;\n",
1094         "\n",
1095         "    this.ws = websocket;\n",
1096         "\n",
1097         "    this.supports_binary = this.ws.binaryType !== undefined;\n",
1098         "\n",
1099         "    if (!this.supports_binary) {\n",
1100         "        var warnings = document.getElementById('mpl-warnings');\n",
1101         "        if (warnings) {\n",
1102         "            warnings.style.display = 'block';\n",
1103         "            warnings.textContent =\n",
1104         "                'This browser does not support binary websocket messages. ' +\n",
1105         "                'Performance may be slow.';\n",
1106         "        }\n",
1107         "    }\n",
1108         "\n",
1109         "    this.imageObj = new Image();\n",
1110         "\n",
1111         "    this.context = undefined;\n",
1112         "    this.message = undefined;\n",
1113         "    this.canvas = undefined;\n",
1114         "    this.rubberband_canvas = undefined;\n",
1115         "    this.rubberband_context = undefined;\n",
1116         "    this.format_dropdown = undefined;\n",
1117         "\n",
1118         "    this.image_mode = 'full';\n",
1119         "\n",
1120         "    this.root = document.createElement('div');\n",
1121         "    this.root.setAttribute('style', 'display: inline-block');\n",
1122         "    this._root_extra_style(this.root);\n",
1123         "\n",
1124         "    parent_element.appendChild(this.root);\n",
1125         "\n",
1126         "    this._init_header(this);\n",
1127         "    this._init_canvas(this);\n",
1128         "    this._init_toolbar(this);\n",
1129         "\n",
1130         "    var fig = this;\n",
1131         "\n",
1132         "    this.waiting = false;\n",
1133         "\n",
1134         "    this.ws.onopen = function () {\n",
1135         "        fig.send_message('supports_binary', { value: fig.supports_binary });\n",
1136         "        fig.send_message('send_image_mode', {});\n",
1137         "        if (fig.ratio !== 1) {\n",
1138         "            fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n",
1139         "        }\n",
1140         "        fig.send_message('refresh', {});\n",
1141         "    };\n",
1142         "\n",
1143         "    this.imageObj.onload = function () {\n",
1144         "        if (fig.image_mode === 'full') {\n",
1145         "            // Full images could contain transparency (where diff images\n",
1146         "            // almost always do), so we need to clear the canvas so that\n",
1147         "            // there is no ghosting.\n",
1148         "            fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
1149         "        }\n",
1150         "        fig.context.drawImage(fig.imageObj, 0, 0);\n",
1151         "    };\n",
1152         "\n",
1153         "    this.imageObj.onunload = function () {\n",
1154         "        fig.ws.close();\n",
1155         "    };\n",
1156         "\n",
1157         "    this.ws.onmessage = this._make_on_message_function(this);\n",
1158         "\n",
1159         "    this.ondownload = ondownload;\n",
1160         "};\n",
1161         "\n",
1162         "mpl.figure.prototype._init_header = function () {\n",
1163         "    var titlebar = document.createElement('div');\n",
1164         "    titlebar.classList =\n",
1165         "        'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n",
1166         "    var titletext = document.createElement('div');\n",
1167         "    titletext.classList = 'ui-dialog-title';\n",
1168         "    titletext.setAttribute(\n",
1169         "        'style',\n",
1170         "        'width: 100%; text-align: center; padding: 3px;'\n",
1171         "    );\n",
1172         "    titlebar.appendChild(titletext);\n",
1173         "    this.root.appendChild(titlebar);\n",
1174         "    this.header = titletext;\n",
1175         "};\n",
1176         "\n",
1177         "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n",
1178         "\n",
1179         "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n",
1180         "\n",
1181         "mpl.figure.prototype._init_canvas = function () {\n",
1182         "    var fig = this;\n",
1183         "\n",
1184         "    var canvas_div = (this.canvas_div = document.createElement('div'));\n",
1185         "    canvas_div.setAttribute(\n",
1186         "        'style',\n",
1187         "        'border: 1px solid #ddd;' +\n",
1188         "            'box-sizing: content-box;' +\n",
1189         "            'clear: both;' +\n",
1190         "            'min-height: 1px;' +\n",
1191         "            'min-width: 1px;' +\n",
1192         "            'outline: 0;' +\n",
1193         "            'overflow: hidden;' +\n",
1194         "            'position: relative;' +\n",
1195         "            'resize: both;'\n",
1196         "    );\n",
1197         "\n",
1198         "    function on_keyboard_event_closure(name) {\n",
1199         "        return function (event) {\n",
1200         "            return fig.key_event(event, name);\n",
1201         "        };\n",
1202         "    }\n",
1203         "\n",
1204         "    canvas_div.addEventListener(\n",
1205         "        'keydown',\n",
1206         "        on_keyboard_event_closure('key_press')\n",
1207         "    );\n",
1208         "    canvas_div.addEventListener(\n",
1209         "        'keyup',\n",
1210         "        on_keyboard_event_closure('key_release')\n",
1211         "    );\n",
1212         "\n",
1213         "    this._canvas_extra_style(canvas_div);\n",
1214         "    this.root.appendChild(canvas_div);\n",
1215         "\n",
1216         "    var canvas = (this.canvas = document.createElement('canvas'));\n",
1217         "    canvas.classList.add('mpl-canvas');\n",
1218         "    canvas.setAttribute('style', 'box-sizing: content-box;');\n",
1219         "\n",
1220         "    this.context = canvas.getContext('2d');\n",
1221         "\n",
1222         "    var backingStore =\n",
1223         "        this.context.backingStorePixelRatio ||\n",
1224         "        this.context.webkitBackingStorePixelRatio ||\n",
1225         "        this.context.mozBackingStorePixelRatio ||\n",
1226         "        this.context.msBackingStorePixelRatio ||\n",
1227         "        this.context.oBackingStorePixelRatio ||\n",
1228         "        this.context.backingStorePixelRatio ||\n",
1229         "        1;\n",
1230         "\n",
1231         "    this.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
1232         "\n",
1233         "    var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n",
1234         "        'canvas'\n",
1235         "    ));\n",
1236         "    rubberband_canvas.setAttribute(\n",
1237         "        'style',\n",
1238         "        'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n",
1239         "    );\n",
1240         "\n",
1241         "    // Apply a ponyfill if ResizeObserver is not implemented by browser.\n",
1242         "    if (this.ResizeObserver === undefined) {\n",
1243         "        if (window.ResizeObserver !== undefined) {\n",
1244         "            this.ResizeObserver = window.ResizeObserver;\n",
1245         "        } else {\n",
1246         "            var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n",
1247         "            this.ResizeObserver = obs.ResizeObserver;\n",
1248         "        }\n",
1249         "    }\n",
1250         "\n",
1251         "    this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n",
1252         "        var nentries = entries.length;\n",
1253         "        for (var i = 0; i < nentries; i++) {\n",
1254         "            var entry = entries[i];\n",
1255         "            var width, height;\n",
1256         "            if (entry.contentBoxSize) {\n",
1257         "                if (entry.contentBoxSize instanceof Array) {\n",
1258         "                    // Chrome 84 implements new version of spec.\n",
1259         "                    width = entry.contentBoxSize[0].inlineSize;\n",
1260         "                    height = entry.contentBoxSize[0].blockSize;\n",
1261         "                } else {\n",
1262         "                    // Firefox implements old version of spec.\n",
1263         "                    width = entry.contentBoxSize.inlineSize;\n",
1264         "                    height = entry.contentBoxSize.blockSize;\n",
1265         "                }\n",
1266         "            } else {\n",
1267         "                // Chrome <84 implements even older version of spec.\n",
1268         "                width = entry.contentRect.width;\n",
1269         "                height = entry.contentRect.height;\n",
1270         "            }\n",
1271         "\n",
1272         "            // Keep the size of the canvas and rubber band canvas in sync with\n",
1273         "            // the canvas container.\n",
1274         "            if (entry.devicePixelContentBoxSize) {\n",
1275         "                // Chrome 84 implements new version of spec.\n",
1276         "                canvas.setAttribute(\n",
1277         "                    'width',\n",
1278         "                    entry.devicePixelContentBoxSize[0].inlineSize\n",
1279         "                );\n",
1280         "                canvas.setAttribute(\n",
1281         "                    'height',\n",
1282         "                    entry.devicePixelContentBoxSize[0].blockSize\n",
1283         "                );\n",
1284         "            } else {\n",
1285         "                canvas.setAttribute('width', width * fig.ratio);\n",
1286         "                canvas.setAttribute('height', height * fig.ratio);\n",
1287         "            }\n",
1288         "            canvas.setAttribute(\n",
1289         "                'style',\n",
1290         "                'width: ' + width + 'px; height: ' + height + 'px;'\n",
1291         "            );\n",
1292         "\n",
1293         "            rubberband_canvas.setAttribute('width', width);\n",
1294         "            rubberband_canvas.setAttribute('height', height);\n",
1295         "\n",
1296         "            // And update the size in Python. We ignore the initial 0/0 size\n",
1297         "            // that occurs as the element is placed into the DOM, which should\n",
1298         "            // otherwise not happen due to the minimum size styling.\n",
1299         "            if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n",
1300         "                fig.request_resize(width, height);\n",
1301         "            }\n",
1302         "        }\n",
1303         "    });\n",
1304         "    this.resizeObserverInstance.observe(canvas_div);\n",
1305         "\n",
1306         "    function on_mouse_event_closure(name) {\n",
1307         "        return function (event) {\n",
1308         "            return fig.mouse_event(event, name);\n",
1309         "        };\n",
1310         "    }\n",
1311         "\n",
1312         "    rubberband_canvas.addEventListener(\n",
1313         "        'mousedown',\n",
1314         "        on_mouse_event_closure('button_press')\n",
1315         "    );\n",
1316         "    rubberband_canvas.addEventListener(\n",
1317         "        'mouseup',\n",
1318         "        on_mouse_event_closure('button_release')\n",
1319         "    );\n",
1320         "    // Throttle sequential mouse events to 1 every 20ms.\n",
1321         "    rubberband_canvas.addEventListener(\n",
1322         "        'mousemove',\n",
1323         "        on_mouse_event_closure('motion_notify')\n",
1324         "    );\n",
1325         "\n",
1326         "    rubberband_canvas.addEventListener(\n",
1327         "        'mouseenter',\n",
1328         "        on_mouse_event_closure('figure_enter')\n",
1329         "    );\n",
1330         "    rubberband_canvas.addEventListener(\n",
1331         "        'mouseleave',\n",
1332         "        on_mouse_event_closure('figure_leave')\n",
1333         "    );\n",
1334         "\n",
1335         "    canvas_div.addEventListener('wheel', function (event) {\n",
1336         "        if (event.deltaY < 0) {\n",
1337         "            event.step = 1;\n",
1338         "        } else {\n",
1339         "            event.step = -1;\n",
1340         "        }\n",
1341         "        on_mouse_event_closure('scroll')(event);\n",
1342         "    });\n",
1343         "\n",
1344         "    canvas_div.appendChild(canvas);\n",
1345         "    canvas_div.appendChild(rubberband_canvas);\n",
1346         "\n",
1347         "    this.rubberband_context = rubberband_canvas.getContext('2d');\n",
1348         "    this.rubberband_context.strokeStyle = '#000000';\n",
1349         "\n",
1350         "    this._resize_canvas = function (width, height, forward) {\n",
1351         "        if (forward) {\n",
1352         "            canvas_div.style.width = width + 'px';\n",
1353         "            canvas_div.style.height = height + 'px';\n",
1354         "        }\n",
1355         "    };\n",
1356         "\n",
1357         "    // Disable right mouse context menu.\n",
1358         "    this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n",
1359         "        event.preventDefault();\n",
1360         "        return false;\n",
1361         "    });\n",
1362         "\n",
1363         "    function set_focus() {\n",
1364         "        canvas.focus();\n",
1365         "        canvas_div.focus();\n",
1366         "    }\n",
1367         "\n",
1368         "    window.setTimeout(set_focus, 100);\n",
1369         "};\n",
1370         "\n",
1371         "mpl.figure.prototype._init_toolbar = function () {\n",
1372         "    var fig = this;\n",
1373         "\n",
1374         "    var toolbar = document.createElement('div');\n",
1375         "    toolbar.classList = 'mpl-toolbar';\n",
1376         "    this.root.appendChild(toolbar);\n",
1377         "\n",
1378         "    function on_click_closure(name) {\n",
1379         "        return function (_event) {\n",
1380         "            return fig.toolbar_button_onclick(name);\n",
1381         "        };\n",
1382         "    }\n",
1383         "\n",
1384         "    function on_mouseover_closure(tooltip) {\n",
1385         "        return function (event) {\n",
1386         "            if (!event.currentTarget.disabled) {\n",
1387         "                return fig.toolbar_button_onmouseover(tooltip);\n",
1388         "            }\n",
1389         "        };\n",
1390         "    }\n",
1391         "\n",
1392         "    fig.buttons = {};\n",
1393         "    var buttonGroup = document.createElement('div');\n",
1394         "    buttonGroup.classList = 'mpl-button-group';\n",
1395         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
1396         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
1397         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
1398         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
1399         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
1400         "\n",
1401         "        if (!name) {\n",
1402         "            /* Instead of a spacer, we start a new button group. */\n",
1403         "            if (buttonGroup.hasChildNodes()) {\n",
1404         "                toolbar.appendChild(buttonGroup);\n",
1405         "            }\n",
1406         "            buttonGroup = document.createElement('div');\n",
1407         "            buttonGroup.classList = 'mpl-button-group';\n",
1408         "            continue;\n",
1409         "        }\n",
1410         "\n",
1411         "        var button = (fig.buttons[name] = document.createElement('button'));\n",
1412         "        button.classList = 'mpl-widget';\n",
1413         "        button.setAttribute('role', 'button');\n",
1414         "        button.setAttribute('aria-disabled', 'false');\n",
1415         "        button.addEventListener('click', on_click_closure(method_name));\n",
1416         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
1417         "\n",
1418         "        var icon_img = document.createElement('img');\n",
1419         "        icon_img.src = '_images/' + image + '.png';\n",
1420         "        icon_img.srcset = '_images/' + image + '_large.png 2x';\n",
1421         "        icon_img.alt = tooltip;\n",
1422         "        button.appendChild(icon_img);\n",
1423         "\n",
1424         "        buttonGroup.appendChild(button);\n",
1425         "    }\n",
1426         "\n",
1427         "    if (buttonGroup.hasChildNodes()) {\n",
1428         "        toolbar.appendChild(buttonGroup);\n",
1429         "    }\n",
1430         "\n",
1431         "    var fmt_picker = document.createElement('select');\n",
1432         "    fmt_picker.classList = 'mpl-widget';\n",
1433         "    toolbar.appendChild(fmt_picker);\n",
1434         "    this.format_dropdown = fmt_picker;\n",
1435         "\n",
1436         "    for (var ind in mpl.extensions) {\n",
1437         "        var fmt = mpl.extensions[ind];\n",
1438         "        var option = document.createElement('option');\n",
1439         "        option.selected = fmt === mpl.default_extension;\n",
1440         "        option.innerHTML = fmt;\n",
1441         "        fmt_picker.appendChild(option);\n",
1442         "    }\n",
1443         "\n",
1444         "    var status_bar = document.createElement('span');\n",
1445         "    status_bar.classList = 'mpl-message';\n",
1446         "    toolbar.appendChild(status_bar);\n",
1447         "    this.message = status_bar;\n",
1448         "};\n",
1449         "\n",
1450         "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n",
1451         "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
1452         "    // which will in turn request a refresh of the image.\n",
1453         "    this.send_message('resize', { width: x_pixels, height: y_pixels });\n",
1454         "};\n",
1455         "\n",
1456         "mpl.figure.prototype.send_message = function (type, properties) {\n",
1457         "    properties['type'] = type;\n",
1458         "    properties['figure_id'] = this.id;\n",
1459         "    this.ws.send(JSON.stringify(properties));\n",
1460         "};\n",
1461         "\n",
1462         "mpl.figure.prototype.send_draw_message = function () {\n",
1463         "    if (!this.waiting) {\n",
1464         "        this.waiting = true;\n",
1465         "        this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n",
1466         "    }\n",
1467         "};\n",
1468         "\n",
1469         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
1470         "    var format_dropdown = fig.format_dropdown;\n",
1471         "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
1472         "    fig.ondownload(fig, format);\n",
1473         "};\n",
1474         "\n",
1475         "mpl.figure.prototype.handle_resize = function (fig, msg) {\n",
1476         "    var size = msg['size'];\n",
1477         "    if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n",
1478         "        fig._resize_canvas(size[0], size[1], msg['forward']);\n",
1479         "        fig.send_message('refresh', {});\n",
1480         "    }\n",
1481         "};\n",
1482         "\n",
1483         "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n",
1484         "    var x0 = msg['x0'] / fig.ratio;\n",
1485         "    var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n",
1486         "    var x1 = msg['x1'] / fig.ratio;\n",
1487         "    var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n",
1488         "    x0 = Math.floor(x0) + 0.5;\n",
1489         "    y0 = Math.floor(y0) + 0.5;\n",
1490         "    x1 = Math.floor(x1) + 0.5;\n",
1491         "    y1 = Math.floor(y1) + 0.5;\n",
1492         "    var min_x = Math.min(x0, x1);\n",
1493         "    var min_y = Math.min(y0, y1);\n",
1494         "    var width = Math.abs(x1 - x0);\n",
1495         "    var height = Math.abs(y1 - y0);\n",
1496         "\n",
1497         "    fig.rubberband_context.clearRect(\n",
1498         "        0,\n",
1499         "        0,\n",
1500         "        fig.canvas.width / fig.ratio,\n",
1501         "        fig.canvas.height / fig.ratio\n",
1502         "    );\n",
1503         "\n",
1504         "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
1505         "};\n",
1506         "\n",
1507         "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n",
1508         "    // Updates the figure title.\n",
1509         "    fig.header.textContent = msg['label'];\n",
1510         "};\n",
1511         "\n",
1512         "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n",
1513         "    var cursor = msg['cursor'];\n",
1514         "    switch (cursor) {\n",
1515         "        case 0:\n",
1516         "            cursor = 'pointer';\n",
1517         "            break;\n",
1518         "        case 1:\n",
1519         "            cursor = 'default';\n",
1520         "            break;\n",
1521         "        case 2:\n",
1522         "            cursor = 'crosshair';\n",
1523         "            break;\n",
1524         "        case 3:\n",
1525         "            cursor = 'move';\n",
1526         "            break;\n",
1527         "    }\n",
1528         "    fig.rubberband_canvas.style.cursor = cursor;\n",
1529         "};\n",
1530         "\n",
1531         "mpl.figure.prototype.handle_message = function (fig, msg) {\n",
1532         "    fig.message.textContent = msg['message'];\n",
1533         "};\n",
1534         "\n",
1535         "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n",
1536         "    // Request the server to send over a new figure.\n",
1537         "    fig.send_draw_message();\n",
1538         "};\n",
1539         "\n",
1540         "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n",
1541         "    fig.image_mode = msg['mode'];\n",
1542         "};\n",
1543         "\n",
1544         "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n",
1545         "    for (var key in msg) {\n",
1546         "        if (!(key in fig.buttons)) {\n",
1547         "            continue;\n",
1548         "        }\n",
1549         "        fig.buttons[key].disabled = !msg[key];\n",
1550         "        fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n",
1551         "    }\n",
1552         "};\n",
1553         "\n",
1554         "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n",
1555         "    if (msg['mode'] === 'PAN') {\n",
1556         "        fig.buttons['Pan'].classList.add('active');\n",
1557         "        fig.buttons['Zoom'].classList.remove('active');\n",
1558         "    } else if (msg['mode'] === 'ZOOM') {\n",
1559         "        fig.buttons['Pan'].classList.remove('active');\n",
1560         "        fig.buttons['Zoom'].classList.add('active');\n",
1561         "    } else {\n",
1562         "        fig.buttons['Pan'].classList.remove('active');\n",
1563         "        fig.buttons['Zoom'].classList.remove('active');\n",
1564         "    }\n",
1565         "};\n",
1566         "\n",
1567         "mpl.figure.prototype.updated_canvas_event = function () {\n",
1568         "    // Called whenever the canvas gets updated.\n",
1569         "    this.send_message('ack', {});\n",
1570         "};\n",
1571         "\n",
1572         "// A function to construct a web socket function for onmessage handling.\n",
1573         "// Called in the figure constructor.\n",
1574         "mpl.figure.prototype._make_on_message_function = function (fig) {\n",
1575         "    return function socket_on_message(evt) {\n",
1576         "        if (evt.data instanceof Blob) {\n",
1577         "            /* FIXME: We get \"Resource interpreted as Image but\n",
1578         "             * transferred with MIME type text/plain:\" errors on\n",
1579         "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
1580         "             * to be part of the websocket stream */\n",
1581         "            evt.data.type = 'image/png';\n",
1582         "\n",
1583         "            /* Free the memory for the previous frames */\n",
1584         "            if (fig.imageObj.src) {\n",
1585         "                (window.URL || window.webkitURL).revokeObjectURL(\n",
1586         "                    fig.imageObj.src\n",
1587         "                );\n",
1588         "            }\n",
1589         "\n",
1590         "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
1591         "                evt.data\n",
1592         "            );\n",
1593         "            fig.updated_canvas_event();\n",
1594         "            fig.waiting = false;\n",
1595         "            return;\n",
1596         "        } else if (\n",
1597         "            typeof evt.data === 'string' &&\n",
1598         "            evt.data.slice(0, 21) === 'data:image/png;base64'\n",
1599         "        ) {\n",
1600         "            fig.imageObj.src = evt.data;\n",
1601         "            fig.updated_canvas_event();\n",
1602         "            fig.waiting = false;\n",
1603         "            return;\n",
1604         "        }\n",
1605         "\n",
1606         "        var msg = JSON.parse(evt.data);\n",
1607         "        var msg_type = msg['type'];\n",
1608         "\n",
1609         "        // Call the  \"handle_{type}\" callback, which takes\n",
1610         "        // the figure and JSON message as its only arguments.\n",
1611         "        try {\n",
1612         "            var callback = fig['handle_' + msg_type];\n",
1613         "        } catch (e) {\n",
1614         "            console.log(\n",
1615         "                \"No handler for the '\" + msg_type + \"' message type: \",\n",
1616         "                msg\n",
1617         "            );\n",
1618         "            return;\n",
1619         "        }\n",
1620         "\n",
1621         "        if (callback) {\n",
1622         "            try {\n",
1623         "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
1624         "                callback(fig, msg);\n",
1625         "            } catch (e) {\n",
1626         "                console.log(\n",
1627         "                    \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n",
1628         "                    e,\n",
1629         "                    e.stack,\n",
1630         "                    msg\n",
1631         "                );\n",
1632         "            }\n",
1633         "        }\n",
1634         "    };\n",
1635         "};\n",
1636         "\n",
1637         "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
1638         "mpl.findpos = function (e) {\n",
1639         "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
1640         "    var targ;\n",
1641         "    if (!e) {\n",
1642         "        e = window.event;\n",
1643         "    }\n",
1644         "    if (e.target) {\n",
1645         "        targ = e.target;\n",
1646         "    } else if (e.srcElement) {\n",
1647         "        targ = e.srcElement;\n",
1648         "    }\n",
1649         "    if (targ.nodeType === 3) {\n",
1650         "        // defeat Safari bug\n",
1651         "        targ = targ.parentNode;\n",
1652         "    }\n",
1653         "\n",
1654         "    // pageX,Y are the mouse positions relative to the document\n",
1655         "    var boundingRect = targ.getBoundingClientRect();\n",
1656         "    var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n",
1657         "    var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n",
1658         "\n",
1659         "    return { x: x, y: y };\n",
1660         "};\n",
1661         "\n",
1662         "/*\n",
1663         " * return a copy of an object with only non-object keys\n",
1664         " * we need this to avoid circular references\n",
1665         " * http://stackoverflow.com/a/24161582/3208463\n",
1666         " */\n",
1667         "function simpleKeys(original) {\n",
1668         "    return Object.keys(original).reduce(function (obj, key) {\n",
1669         "        if (typeof original[key] !== 'object') {\n",
1670         "            obj[key] = original[key];\n",
1671         "        }\n",
1672         "        return obj;\n",
1673         "    }, {});\n",
1674         "}\n",
1675         "\n",
1676         "mpl.figure.prototype.mouse_event = function (event, name) {\n",
1677         "    var canvas_pos = mpl.findpos(event);\n",
1678         "\n",
1679         "    if (name === 'button_press') {\n",
1680         "        this.canvas.focus();\n",
1681         "        this.canvas_div.focus();\n",
1682         "    }\n",
1683         "\n",
1684         "    var x = canvas_pos.x * this.ratio;\n",
1685         "    var y = canvas_pos.y * this.ratio;\n",
1686         "\n",
1687         "    this.send_message(name, {\n",
1688         "        x: x,\n",
1689         "        y: y,\n",
1690         "        button: event.button,\n",
1691         "        step: event.step,\n",
1692         "        guiEvent: simpleKeys(event),\n",
1693         "    });\n",
1694         "\n",
1695         "    /* This prevents the web browser from automatically changing to\n",
1696         "     * the text insertion cursor when the button is pressed.  We want\n",
1697         "     * to control all of the cursor setting manually through the\n",
1698         "     * 'cursor' event from matplotlib */\n",
1699         "    event.preventDefault();\n",
1700         "    return false;\n",
1701         "};\n",
1702         "\n",
1703         "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n",
1704         "    // Handle any extra behaviour associated with a key event\n",
1705         "};\n",
1706         "\n",
1707         "mpl.figure.prototype.key_event = function (event, name) {\n",
1708         "    // Prevent repeat events\n",
1709         "    if (name === 'key_press') {\n",
1710         "        if (event.which === this._key) {\n",
1711         "            return;\n",
1712         "        } else {\n",
1713         "            this._key = event.which;\n",
1714         "        }\n",
1715         "    }\n",
1716         "    if (name === 'key_release') {\n",
1717         "        this._key = null;\n",
1718         "    }\n",
1719         "\n",
1720         "    var value = '';\n",
1721         "    if (event.ctrlKey && event.which !== 17) {\n",
1722         "        value += 'ctrl+';\n",
1723         "    }\n",
1724         "    if (event.altKey && event.which !== 18) {\n",
1725         "        value += 'alt+';\n",
1726         "    }\n",
1727         "    if (event.shiftKey && event.which !== 16) {\n",
1728         "        value += 'shift+';\n",
1729         "    }\n",
1730         "\n",
1731         "    value += 'k';\n",
1732         "    value += event.which.toString();\n",
1733         "\n",
1734         "    this._key_event_extra(event, name);\n",
1735         "\n",
1736         "    this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n",
1737         "    return false;\n",
1738         "};\n",
1739         "\n",
1740         "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n",
1741         "    if (name === 'download') {\n",
1742         "        this.handle_save(this, null);\n",
1743         "    } else {\n",
1744         "        this.send_message('toolbar_button', { name: name });\n",
1745         "    }\n",
1746         "};\n",
1747         "\n",
1748         "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n",
1749         "    this.message.textContent = tooltip;\n",
1750         "};\n",
1751         "\n",
1752         "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n",
1753         "// prettier-ignore\n",
1754         "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n",
1755         "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
1756         "\n",
1757         "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
1758         "\n",
1759         "mpl.default_extension = \"png\";/* global mpl */\n",
1760         "\n",
1761         "var comm_websocket_adapter = function (comm) {\n",
1762         "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
1763         "    // object with the appropriate methods. Currently this is a non binary\n",
1764         "    // socket, so there is still some room for performance tuning.\n",
1765         "    var ws = {};\n",
1766         "\n",
1767         "    ws.close = function () {\n",
1768         "        comm.close();\n",
1769         "    };\n",
1770         "    ws.send = function (m) {\n",
1771         "        //console.log('sending', m);\n",
1772         "        comm.send(m);\n",
1773         "    };\n",
1774         "    // Register the callback with on_msg.\n",
1775         "    comm.on_msg(function (msg) {\n",
1776         "        //console.log('receiving', msg['content']['data'], msg);\n",
1777         "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
1778         "        ws.onmessage(msg['content']['data']);\n",
1779         "    });\n",
1780         "    return ws;\n",
1781         "};\n",
1782         "\n",
1783         "mpl.mpl_figure_comm = function (comm, msg) {\n",
1784         "    // This is the function which gets called when the mpl process\n",
1785         "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
1786         "\n",
1787         "    var id = msg.content.data.id;\n",
1788         "    // Get hold of the div created by the display call when the Comm\n",
1789         "    // socket was opened in Python.\n",
1790         "    var element = document.getElementById(id);\n",
1791         "    var ws_proxy = comm_websocket_adapter(comm);\n",
1792         "\n",
1793         "    function ondownload(figure, _format) {\n",
1794         "        window.open(figure.canvas.toDataURL());\n",
1795         "    }\n",
1796         "\n",
1797         "    var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n",
1798         "\n",
1799         "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
1800         "    // web socket which is closed, not our websocket->open comm proxy.\n",
1801         "    ws_proxy.onopen();\n",
1802         "\n",
1803         "    fig.parent_element = element;\n",
1804         "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
1805         "    if (!fig.cell_info) {\n",
1806         "        console.error('Failed to find cell for figure', id, fig);\n",
1807         "        return;\n",
1808         "    }\n",
1809         "    fig.cell_info[0].output_area.element.on(\n",
1810         "        'cleared',\n",
1811         "        { fig: fig },\n",
1812         "        fig._remove_fig_handler\n",
1813         "    );\n",
1814         "};\n",
1815         "\n",
1816         "mpl.figure.prototype.handle_close = function (fig, msg) {\n",
1817         "    var width = fig.canvas.width / fig.ratio;\n",
1818         "    fig.cell_info[0].output_area.element.off(\n",
1819         "        'cleared',\n",
1820         "        fig._remove_fig_handler\n",
1821         "    );\n",
1822         "    fig.resizeObserverInstance.unobserve(fig.canvas_div);\n",
1823         "\n",
1824         "    // Update the output cell to use the data from the current canvas.\n",
1825         "    fig.push_to_output();\n",
1826         "    var dataURL = fig.canvas.toDataURL();\n",
1827         "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
1828         "    // the notebook keyboard shortcuts fail.\n",
1829         "    IPython.keyboard_manager.enable();\n",
1830         "    fig.parent_element.innerHTML =\n",
1831         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
1832         "    fig.close_ws(fig, msg);\n",
1833         "};\n",
1834         "\n",
1835         "mpl.figure.prototype.close_ws = function (fig, msg) {\n",
1836         "    fig.send_message('closing', msg);\n",
1837         "    // fig.ws.close()\n",
1838         "};\n",
1839         "\n",
1840         "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n",
1841         "    // Turn the data on the canvas into data in the output cell.\n",
1842         "    var width = this.canvas.width / this.ratio;\n",
1843         "    var dataURL = this.canvas.toDataURL();\n",
1844         "    this.cell_info[1]['text/html'] =\n",
1845         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
1846         "};\n",
1847         "\n",
1848         "mpl.figure.prototype.updated_canvas_event = function () {\n",
1849         "    // Tell IPython that the notebook contents must change.\n",
1850         "    IPython.notebook.set_dirty(true);\n",
1851         "    this.send_message('ack', {});\n",
1852         "    var fig = this;\n",
1853         "    // Wait a second, then push the new image to the DOM so\n",
1854         "    // that it is saved nicely (might be nice to debounce this).\n",
1855         "    setTimeout(function () {\n",
1856         "        fig.push_to_output();\n",
1857         "    }, 1000);\n",
1858         "};\n",
1859         "\n",
1860         "mpl.figure.prototype._init_toolbar = function () {\n",
1861         "    var fig = this;\n",
1862         "\n",
1863         "    var toolbar = document.createElement('div');\n",
1864         "    toolbar.classList = 'btn-toolbar';\n",
1865         "    this.root.appendChild(toolbar);\n",
1866         "\n",
1867         "    function on_click_closure(name) {\n",
1868         "        return function (_event) {\n",
1869         "            return fig.toolbar_button_onclick(name);\n",
1870         "        };\n",
1871         "    }\n",
1872         "\n",
1873         "    function on_mouseover_closure(tooltip) {\n",
1874         "        return function (event) {\n",
1875         "            if (!event.currentTarget.disabled) {\n",
1876         "                return fig.toolbar_button_onmouseover(tooltip);\n",
1877         "            }\n",
1878         "        };\n",
1879         "    }\n",
1880         "\n",
1881         "    fig.buttons = {};\n",
1882         "    var buttonGroup = document.createElement('div');\n",
1883         "    buttonGroup.classList = 'btn-group';\n",
1884         "    var button;\n",
1885         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
1886         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
1887         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
1888         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
1889         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
1890         "\n",
1891         "        if (!name) {\n",
1892         "            /* Instead of a spacer, we start a new button group. */\n",
1893         "            if (buttonGroup.hasChildNodes()) {\n",
1894         "                toolbar.appendChild(buttonGroup);\n",
1895         "            }\n",
1896         "            buttonGroup = document.createElement('div');\n",
1897         "            buttonGroup.classList = 'btn-group';\n",
1898         "            continue;\n",
1899         "        }\n",
1900         "\n",
1901         "        button = fig.buttons[name] = document.createElement('button');\n",
1902         "        button.classList = 'btn btn-default';\n",
1903         "        button.href = '#';\n",
1904         "        button.title = name;\n",
1905         "        button.innerHTML = '<i class=\"fa ' + image + ' fa-lg\"></i>';\n",
1906         "        button.addEventListener('click', on_click_closure(method_name));\n",
1907         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
1908         "        buttonGroup.appendChild(button);\n",
1909         "    }\n",
1910         "\n",
1911         "    if (buttonGroup.hasChildNodes()) {\n",
1912         "        toolbar.appendChild(buttonGroup);\n",
1913         "    }\n",
1914         "\n",
1915         "    // Add the status bar.\n",
1916         "    var status_bar = document.createElement('span');\n",
1917         "    status_bar.classList = 'mpl-message pull-right';\n",
1918         "    toolbar.appendChild(status_bar);\n",
1919         "    this.message = status_bar;\n",
1920         "\n",
1921         "    // Add the close button to the window.\n",
1922         "    var buttongrp = document.createElement('div');\n",
1923         "    buttongrp.classList = 'btn-group inline pull-right';\n",
1924         "    button = document.createElement('button');\n",
1925         "    button.classList = 'btn btn-mini btn-primary';\n",
1926         "    button.href = '#';\n",
1927         "    button.title = 'Stop Interaction';\n",
1928         "    button.innerHTML = '<i class=\"fa fa-power-off icon-remove icon-large\"></i>';\n",
1929         "    button.addEventListener('click', function (_evt) {\n",
1930         "        fig.handle_close(fig, {});\n",
1931         "    });\n",
1932         "    button.addEventListener(\n",
1933         "        'mouseover',\n",
1934         "        on_mouseover_closure('Stop Interaction')\n",
1935         "    );\n",
1936         "    buttongrp.appendChild(button);\n",
1937         "    var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n",
1938         "    titlebar.insertBefore(buttongrp, titlebar.firstChild);\n",
1939         "};\n",
1940         "\n",
1941         "mpl.figure.prototype._remove_fig_handler = function (event) {\n",
1942         "    var fig = event.data.fig;\n",
1943         "    if (event.target !== this) {\n",
1944         "        // Ignore bubbled events from children.\n",
1945         "        return;\n",
1946         "    }\n",
1947         "    fig.close_ws(fig, {});\n",
1948         "};\n",
1949         "\n",
1950         "mpl.figure.prototype._root_extra_style = function (el) {\n",
1951         "    el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n",
1952         "};\n",
1953         "\n",
1954         "mpl.figure.prototype._canvas_extra_style = function (el) {\n",
1955         "    // this is important to make the div 'focusable\n",
1956         "    el.setAttribute('tabindex', 0);\n",
1957         "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
1958         "    // off when our div gets focus\n",
1959         "\n",
1960         "    // location in version 3\n",
1961         "    if (IPython.notebook.keyboard_manager) {\n",
1962         "        IPython.notebook.keyboard_manager.register_events(el);\n",
1963         "    } else {\n",
1964         "        // location in version 2\n",
1965         "        IPython.keyboard_manager.register_events(el);\n",
1966         "    }\n",
1967         "};\n",
1968         "\n",
1969         "mpl.figure.prototype._key_event_extra = function (event, _name) {\n",
1970         "    var manager = IPython.notebook.keyboard_manager;\n",
1971         "    if (!manager) {\n",
1972         "        manager = IPython.keyboard_manager;\n",
1973         "    }\n",
1974         "\n",
1975         "    // Check for shift+enter\n",
1976         "    if (event.shiftKey && event.which === 13) {\n",
1977         "        this.canvas_div.blur();\n",
1978         "        // select the cell after this one\n",
1979         "        var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
1980         "        IPython.notebook.select(index + 1);\n",
1981         "    }\n",
1982         "};\n",
1983         "\n",
1984         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
1985         "    fig.ondownload(fig, null);\n",
1986         "};\n",
1987         "\n",
1988         "mpl.find_output_cell = function (html_output) {\n",
1989         "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
1990         "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
1991         "    // IPython event is triggered only after the cells have been serialised, which for\n",
1992         "    // our purposes (turning an active figure into a static one), is too late.\n",
1993         "    var cells = IPython.notebook.get_cells();\n",
1994         "    var ncells = cells.length;\n",
1995         "    for (var i = 0; i < ncells; i++) {\n",
1996         "        var cell = cells[i];\n",
1997         "        if (cell.cell_type === 'code') {\n",
1998         "            for (var j = 0; j < cell.output_area.outputs.length; j++) {\n",
1999         "                var data = cell.output_area.outputs[j];\n",
2000         "                if (data.data) {\n",
2001         "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
2002         "                    data = data.data;\n",
2003         "                }\n",
2004         "                if (data['text/html'] === html_output) {\n",
2005         "                    return [cell, data, j];\n",
2006         "                }\n",
2007         "            }\n",
2008         "        }\n",
2009         "    }\n",
2010         "};\n",
2011         "\n",
2012         "// Register the function which deals with the matplotlib target/channel.\n",
2013         "// The kernel may be null if the page has been refreshed.\n",
2014         "if (IPython.notebook.kernel !== null) {\n",
2015         "    IPython.notebook.kernel.comm_manager.register_target(\n",
2016         "        'matplotlib',\n",
2017         "        mpl.mpl_figure_comm\n",
2018         "    );\n",
2019         "}\n"
2020        ],
2021        "text/plain": [
2022         "<IPython.core.display.Javascript object>"
2023        ]
2024       },
2025       "metadata": {},
2026       "output_type": "display_data"
2027      },
2028      {
2029       "data": {
2030        "text/html": [
2031         "<div id='bda3b66e-054c-478e-af62-f9177c939cee'></div>"
2032        ],
2033        "text/plain": [
2034         "<IPython.core.display.HTML object>"
2035        ]
2036       },
2037       "metadata": {},
2038       "output_type": "display_data"
2039      },
2040      {
2041       "data": {
2042        "application/javascript": [
2043         "/* Put everything inside the global mpl namespace */\n",
2044         "/* global mpl */\n",
2045         "window.mpl = {};\n",
2046         "\n",
2047         "mpl.get_websocket_type = function () {\n",
2048         "    if (typeof WebSocket !== 'undefined') {\n",
2049         "        return WebSocket;\n",
2050         "    } else if (typeof MozWebSocket !== 'undefined') {\n",
2051         "        return MozWebSocket;\n",
2052         "    } else {\n",
2053         "        alert(\n",
2054         "            'Your browser does not have WebSocket support. ' +\n",
2055         "                'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
2056         "                'Firefox 4 and 5 are also supported but you ' +\n",
2057         "                'have to enable WebSockets in about:config.'\n",
2058         "        );\n",
2059         "    }\n",
2060         "};\n",
2061         "\n",
2062         "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n",
2063         "    this.id = figure_id;\n",
2064         "\n",
2065         "    this.ws = websocket;\n",
2066         "\n",
2067         "    this.supports_binary = this.ws.binaryType !== undefined;\n",
2068         "\n",
2069         "    if (!this.supports_binary) {\n",
2070         "        var warnings = document.getElementById('mpl-warnings');\n",
2071         "        if (warnings) {\n",
2072         "            warnings.style.display = 'block';\n",
2073         "            warnings.textContent =\n",
2074         "                'This browser does not support binary websocket messages. ' +\n",
2075         "                'Performance may be slow.';\n",
2076         "        }\n",
2077         "    }\n",
2078         "\n",
2079         "    this.imageObj = new Image();\n",
2080         "\n",
2081         "    this.context = undefined;\n",
2082         "    this.message = undefined;\n",
2083         "    this.canvas = undefined;\n",
2084         "    this.rubberband_canvas = undefined;\n",
2085         "    this.rubberband_context = undefined;\n",
2086         "    this.format_dropdown = undefined;\n",
2087         "\n",
2088         "    this.image_mode = 'full';\n",
2089         "\n",
2090         "    this.root = document.createElement('div');\n",
2091         "    this.root.setAttribute('style', 'display: inline-block');\n",
2092         "    this._root_extra_style(this.root);\n",
2093         "\n",
2094         "    parent_element.appendChild(this.root);\n",
2095         "\n",
2096         "    this._init_header(this);\n",
2097         "    this._init_canvas(this);\n",
2098         "    this._init_toolbar(this);\n",
2099         "\n",
2100         "    var fig = this;\n",
2101         "\n",
2102         "    this.waiting = false;\n",
2103         "\n",
2104         "    this.ws.onopen = function () {\n",
2105         "        fig.send_message('supports_binary', { value: fig.supports_binary });\n",
2106         "        fig.send_message('send_image_mode', {});\n",
2107         "        if (fig.ratio !== 1) {\n",
2108         "            fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n",
2109         "        }\n",
2110         "        fig.send_message('refresh', {});\n",
2111         "    };\n",
2112         "\n",
2113         "    this.imageObj.onload = function () {\n",
2114         "        if (fig.image_mode === 'full') {\n",
2115         "            // Full images could contain transparency (where diff images\n",
2116         "            // almost always do), so we need to clear the canvas so that\n",
2117         "            // there is no ghosting.\n",
2118         "            fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
2119         "        }\n",
2120         "        fig.context.drawImage(fig.imageObj, 0, 0);\n",
2121         "    };\n",
2122         "\n",
2123         "    this.imageObj.onunload = function () {\n",
2124         "        fig.ws.close();\n",
2125         "    };\n",
2126         "\n",
2127         "    this.ws.onmessage = this._make_on_message_function(this);\n",
2128         "\n",
2129         "    this.ondownload = ondownload;\n",
2130         "};\n",
2131         "\n",
2132         "mpl.figure.prototype._init_header = function () {\n",
2133         "    var titlebar = document.createElement('div');\n",
2134         "    titlebar.classList =\n",
2135         "        'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n",
2136         "    var titletext = document.createElement('div');\n",
2137         "    titletext.classList = 'ui-dialog-title';\n",
2138         "    titletext.setAttribute(\n",
2139         "        'style',\n",
2140         "        'width: 100%; text-align: center; padding: 3px;'\n",
2141         "    );\n",
2142         "    titlebar.appendChild(titletext);\n",
2143         "    this.root.appendChild(titlebar);\n",
2144         "    this.header = titletext;\n",
2145         "};\n",
2146         "\n",
2147         "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n",
2148         "\n",
2149         "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n",
2150         "\n",
2151         "mpl.figure.prototype._init_canvas = function () {\n",
2152         "    var fig = this;\n",
2153         "\n",
2154         "    var canvas_div = (this.canvas_div = document.createElement('div'));\n",
2155         "    canvas_div.setAttribute(\n",
2156         "        'style',\n",
2157         "        'border: 1px solid #ddd;' +\n",
2158         "            'box-sizing: content-box;' +\n",
2159         "            'clear: both;' +\n",
2160         "            'min-height: 1px;' +\n",
2161         "            'min-width: 1px;' +\n",
2162         "            'outline: 0;' +\n",
2163         "            'overflow: hidden;' +\n",
2164         "            'position: relative;' +\n",
2165         "            'resize: both;'\n",
2166         "    );\n",
2167         "\n",
2168         "    function on_keyboard_event_closure(name) {\n",
2169         "        return function (event) {\n",
2170         "            return fig.key_event(event, name);\n",
2171         "        };\n",
2172         "    }\n",
2173         "\n",
2174         "    canvas_div.addEventListener(\n",
2175         "        'keydown',\n",
2176         "        on_keyboard_event_closure('key_press')\n",
2177         "    );\n",
2178         "    canvas_div.addEventListener(\n",
2179         "        'keyup',\n",
2180         "        on_keyboard_event_closure('key_release')\n",
2181         "    );\n",
2182         "\n",
2183         "    this._canvas_extra_style(canvas_div);\n",
2184         "    this.root.appendChild(canvas_div);\n",
2185         "\n",
2186         "    var canvas = (this.canvas = document.createElement('canvas'));\n",
2187         "    canvas.classList.add('mpl-canvas');\n",
2188         "    canvas.setAttribute('style', 'box-sizing: content-box;');\n",
2189         "\n",
2190         "    this.context = canvas.getContext('2d');\n",
2191         "\n",
2192         "    var backingStore =\n",
2193         "        this.context.backingStorePixelRatio ||\n",
2194         "        this.context.webkitBackingStorePixelRatio ||\n",
2195         "        this.context.mozBackingStorePixelRatio ||\n",
2196         "        this.context.msBackingStorePixelRatio ||\n",
2197         "        this.context.oBackingStorePixelRatio ||\n",
2198         "        this.context.backingStorePixelRatio ||\n",
2199         "        1;\n",
2200         "\n",
2201         "    this.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
2202         "\n",
2203         "    var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n",
2204         "        'canvas'\n",
2205         "    ));\n",
2206         "    rubberband_canvas.setAttribute(\n",
2207         "        'style',\n",
2208         "        'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n",
2209         "    );\n",
2210         "\n",
2211         "    // Apply a ponyfill if ResizeObserver is not implemented by browser.\n",
2212         "    if (this.ResizeObserver === undefined) {\n",
2213         "        if (window.ResizeObserver !== undefined) {\n",
2214         "            this.ResizeObserver = window.ResizeObserver;\n",
2215         "        } else {\n",
2216         "            var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n",
2217         "            this.ResizeObserver = obs.ResizeObserver;\n",
2218         "        }\n",
2219         "    }\n",
2220         "\n",
2221         "    this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n",
2222         "        var nentries = entries.length;\n",
2223         "        for (var i = 0; i < nentries; i++) {\n",
2224         "            var entry = entries[i];\n",
2225         "            var width, height;\n",
2226         "            if (entry.contentBoxSize) {\n",
2227         "                if (entry.contentBoxSize instanceof Array) {\n",
2228         "                    // Chrome 84 implements new version of spec.\n",
2229         "                    width = entry.contentBoxSize[0].inlineSize;\n",
2230         "                    height = entry.contentBoxSize[0].blockSize;\n",
2231         "                } else {\n",
2232         "                    // Firefox implements old version of spec.\n",
2233         "                    width = entry.contentBoxSize.inlineSize;\n",
2234         "                    height = entry.contentBoxSize.blockSize;\n",
2235         "                }\n",
2236         "            } else {\n",
2237         "                // Chrome <84 implements even older version of spec.\n",
2238         "                width = entry.contentRect.width;\n",
2239         "                height = entry.contentRect.height;\n",
2240         "            }\n",
2241         "\n",
2242         "            // Keep the size of the canvas and rubber band canvas in sync with\n",
2243         "            // the canvas container.\n",
2244         "            if (entry.devicePixelContentBoxSize) {\n",
2245         "                // Chrome 84 implements new version of spec.\n",
2246         "                canvas.setAttribute(\n",
2247         "                    'width',\n",
2248         "                    entry.devicePixelContentBoxSize[0].inlineSize\n",
2249         "                );\n",
2250         "                canvas.setAttribute(\n",
2251         "                    'height',\n",
2252         "                    entry.devicePixelContentBoxSize[0].blockSize\n",
2253         "                );\n",
2254         "            } else {\n",
2255         "                canvas.setAttribute('width', width * fig.ratio);\n",
2256         "                canvas.setAttribute('height', height * fig.ratio);\n",
2257         "            }\n",
2258         "            canvas.setAttribute(\n",
2259         "                'style',\n",
2260         "                'width: ' + width + 'px; height: ' + height + 'px;'\n",
2261         "            );\n",
2262         "\n",
2263         "            rubberband_canvas.setAttribute('width', width);\n",
2264         "            rubberband_canvas.setAttribute('height', height);\n",
2265         "\n",
2266         "            // And update the size in Python. We ignore the initial 0/0 size\n",
2267         "            // that occurs as the element is placed into the DOM, which should\n",
2268         "            // otherwise not happen due to the minimum size styling.\n",
2269         "            if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n",
2270         "                fig.request_resize(width, height);\n",
2271         "            }\n",
2272         "        }\n",
2273         "    });\n",
2274         "    this.resizeObserverInstance.observe(canvas_div);\n",
2275         "\n",
2276         "    function on_mouse_event_closure(name) {\n",
2277         "        return function (event) {\n",
2278         "            return fig.mouse_event(event, name);\n",
2279         "        };\n",
2280         "    }\n",
2281         "\n",
2282         "    rubberband_canvas.addEventListener(\n",
2283         "        'mousedown',\n",
2284         "        on_mouse_event_closure('button_press')\n",
2285         "    );\n",
2286         "    rubberband_canvas.addEventListener(\n",
2287         "        'mouseup',\n",
2288         "        on_mouse_event_closure('button_release')\n",
2289         "    );\n",
2290         "    // Throttle sequential mouse events to 1 every 20ms.\n",
2291         "    rubberband_canvas.addEventListener(\n",
2292         "        'mousemove',\n",
2293         "        on_mouse_event_closure('motion_notify')\n",
2294         "    );\n",
2295         "\n",
2296         "    rubberband_canvas.addEventListener(\n",
2297         "        'mouseenter',\n",
2298         "        on_mouse_event_closure('figure_enter')\n",
2299         "    );\n",
2300         "    rubberband_canvas.addEventListener(\n",
2301         "        'mouseleave',\n",
2302         "        on_mouse_event_closure('figure_leave')\n",
2303         "    );\n",
2304         "\n",
2305         "    canvas_div.addEventListener('wheel', function (event) {\n",
2306         "        if (event.deltaY < 0) {\n",
2307         "            event.step = 1;\n",
2308         "        } else {\n",
2309         "            event.step = -1;\n",
2310         "        }\n",
2311         "        on_mouse_event_closure('scroll')(event);\n",
2312         "    });\n",
2313         "\n",
2314         "    canvas_div.appendChild(canvas);\n",
2315         "    canvas_div.appendChild(rubberband_canvas);\n",
2316         "\n",
2317         "    this.rubberband_context = rubberband_canvas.getContext('2d');\n",
2318         "    this.rubberband_context.strokeStyle = '#000000';\n",
2319         "\n",
2320         "    this._resize_canvas = function (width, height, forward) {\n",
2321         "        if (forward) {\n",
2322         "            canvas_div.style.width = width + 'px';\n",
2323         "            canvas_div.style.height = height + 'px';\n",
2324         "        }\n",
2325         "    };\n",
2326         "\n",
2327         "    // Disable right mouse context menu.\n",
2328         "    this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n",
2329         "        event.preventDefault();\n",
2330         "        return false;\n",
2331         "    });\n",
2332         "\n",
2333         "    function set_focus() {\n",
2334         "        canvas.focus();\n",
2335         "        canvas_div.focus();\n",
2336         "    }\n",
2337         "\n",
2338         "    window.setTimeout(set_focus, 100);\n",
2339         "};\n",
2340         "\n",
2341         "mpl.figure.prototype._init_toolbar = function () {\n",
2342         "    var fig = this;\n",
2343         "\n",
2344         "    var toolbar = document.createElement('div');\n",
2345         "    toolbar.classList = 'mpl-toolbar';\n",
2346         "    this.root.appendChild(toolbar);\n",
2347         "\n",
2348         "    function on_click_closure(name) {\n",
2349         "        return function (_event) {\n",
2350         "            return fig.toolbar_button_onclick(name);\n",
2351         "        };\n",
2352         "    }\n",
2353         "\n",
2354         "    function on_mouseover_closure(tooltip) {\n",
2355         "        return function (event) {\n",
2356         "            if (!event.currentTarget.disabled) {\n",
2357         "                return fig.toolbar_button_onmouseover(tooltip);\n",
2358         "            }\n",
2359         "        };\n",
2360         "    }\n",
2361         "\n",
2362         "    fig.buttons = {};\n",
2363         "    var buttonGroup = document.createElement('div');\n",
2364         "    buttonGroup.classList = 'mpl-button-group';\n",
2365         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
2366         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
2367         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
2368         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
2369         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
2370         "\n",
2371         "        if (!name) {\n",
2372         "            /* Instead of a spacer, we start a new button group. */\n",
2373         "            if (buttonGroup.hasChildNodes()) {\n",
2374         "                toolbar.appendChild(buttonGroup);\n",
2375         "            }\n",
2376         "            buttonGroup = document.createElement('div');\n",
2377         "            buttonGroup.classList = 'mpl-button-group';\n",
2378         "            continue;\n",
2379         "        }\n",
2380         "\n",
2381         "        var button = (fig.buttons[name] = document.createElement('button'));\n",
2382         "        button.classList = 'mpl-widget';\n",
2383         "        button.setAttribute('role', 'button');\n",
2384         "        button.setAttribute('aria-disabled', 'false');\n",
2385         "        button.addEventListener('click', on_click_closure(method_name));\n",
2386         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
2387         "\n",
2388         "        var icon_img = document.createElement('img');\n",
2389         "        icon_img.src = '_images/' + image + '.png';\n",
2390         "        icon_img.srcset = '_images/' + image + '_large.png 2x';\n",
2391         "        icon_img.alt = tooltip;\n",
2392         "        button.appendChild(icon_img);\n",
2393         "\n",
2394         "        buttonGroup.appendChild(button);\n",
2395         "    }\n",
2396         "\n",
2397         "    if (buttonGroup.hasChildNodes()) {\n",
2398         "        toolbar.appendChild(buttonGroup);\n",
2399         "    }\n",
2400         "\n",
2401         "    var fmt_picker = document.createElement('select');\n",
2402         "    fmt_picker.classList = 'mpl-widget';\n",
2403         "    toolbar.appendChild(fmt_picker);\n",
2404         "    this.format_dropdown = fmt_picker;\n",
2405         "\n",
2406         "    for (var ind in mpl.extensions) {\n",
2407         "        var fmt = mpl.extensions[ind];\n",
2408         "        var option = document.createElement('option');\n",
2409         "        option.selected = fmt === mpl.default_extension;\n",
2410         "        option.innerHTML = fmt;\n",
2411         "        fmt_picker.appendChild(option);\n",
2412         "    }\n",
2413         "\n",
2414         "    var status_bar = document.createElement('span');\n",
2415         "    status_bar.classList = 'mpl-message';\n",
2416         "    toolbar.appendChild(status_bar);\n",
2417         "    this.message = status_bar;\n",
2418         "};\n",
2419         "\n",
2420         "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n",
2421         "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
2422         "    // which will in turn request a refresh of the image.\n",
2423         "    this.send_message('resize', { width: x_pixels, height: y_pixels });\n",
2424         "};\n",
2425         "\n",
2426         "mpl.figure.prototype.send_message = function (type, properties) {\n",
2427         "    properties['type'] = type;\n",
2428         "    properties['figure_id'] = this.id;\n",
2429         "    this.ws.send(JSON.stringify(properties));\n",
2430         "};\n",
2431         "\n",
2432         "mpl.figure.prototype.send_draw_message = function () {\n",
2433         "    if (!this.waiting) {\n",
2434         "        this.waiting = true;\n",
2435         "        this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n",
2436         "    }\n",
2437         "};\n",
2438         "\n",
2439         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
2440         "    var format_dropdown = fig.format_dropdown;\n",
2441         "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
2442         "    fig.ondownload(fig, format);\n",
2443         "};\n",
2444         "\n",
2445         "mpl.figure.prototype.handle_resize = function (fig, msg) {\n",
2446         "    var size = msg['size'];\n",
2447         "    if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n",
2448         "        fig._resize_canvas(size[0], size[1], msg['forward']);\n",
2449         "        fig.send_message('refresh', {});\n",
2450         "    }\n",
2451         "};\n",
2452         "\n",
2453         "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n",
2454         "    var x0 = msg['x0'] / fig.ratio;\n",
2455         "    var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n",
2456         "    var x1 = msg['x1'] / fig.ratio;\n",
2457         "    var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n",
2458         "    x0 = Math.floor(x0) + 0.5;\n",
2459         "    y0 = Math.floor(y0) + 0.5;\n",
2460         "    x1 = Math.floor(x1) + 0.5;\n",
2461         "    y1 = Math.floor(y1) + 0.5;\n",
2462         "    var min_x = Math.min(x0, x1);\n",
2463         "    var min_y = Math.min(y0, y1);\n",
2464         "    var width = Math.abs(x1 - x0);\n",
2465         "    var height = Math.abs(y1 - y0);\n",
2466         "\n",
2467         "    fig.rubberband_context.clearRect(\n",
2468         "        0,\n",
2469         "        0,\n",
2470         "        fig.canvas.width / fig.ratio,\n",
2471         "        fig.canvas.height / fig.ratio\n",
2472         "    );\n",
2473         "\n",
2474         "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
2475         "};\n",
2476         "\n",
2477         "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n",
2478         "    // Updates the figure title.\n",
2479         "    fig.header.textContent = msg['label'];\n",
2480         "};\n",
2481         "\n",
2482         "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n",
2483         "    var cursor = msg['cursor'];\n",
2484         "    switch (cursor) {\n",
2485         "        case 0:\n",
2486         "            cursor = 'pointer';\n",
2487         "            break;\n",
2488         "        case 1:\n",
2489         "            cursor = 'default';\n",
2490         "            break;\n",
2491         "        case 2:\n",
2492         "            cursor = 'crosshair';\n",
2493         "            break;\n",
2494         "        case 3:\n",
2495         "            cursor = 'move';\n",
2496         "            break;\n",
2497         "    }\n",
2498         "    fig.rubberband_canvas.style.cursor = cursor;\n",
2499         "};\n",
2500         "\n",
2501         "mpl.figure.prototype.handle_message = function (fig, msg) {\n",
2502         "    fig.message.textContent = msg['message'];\n",
2503         "};\n",
2504         "\n",
2505         "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n",
2506         "    // Request the server to send over a new figure.\n",
2507         "    fig.send_draw_message();\n",
2508         "};\n",
2509         "\n",
2510         "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n",
2511         "    fig.image_mode = msg['mode'];\n",
2512         "};\n",
2513         "\n",
2514         "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n",
2515         "    for (var key in msg) {\n",
2516         "        if (!(key in fig.buttons)) {\n",
2517         "            continue;\n",
2518         "        }\n",
2519         "        fig.buttons[key].disabled = !msg[key];\n",
2520         "        fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n",
2521         "    }\n",
2522         "};\n",
2523         "\n",
2524         "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n",
2525         "    if (msg['mode'] === 'PAN') {\n",
2526         "        fig.buttons['Pan'].classList.add('active');\n",
2527         "        fig.buttons['Zoom'].classList.remove('active');\n",
2528         "    } else if (msg['mode'] === 'ZOOM') {\n",
2529         "        fig.buttons['Pan'].classList.remove('active');\n",
2530         "        fig.buttons['Zoom'].classList.add('active');\n",
2531         "    } else {\n",
2532         "        fig.buttons['Pan'].classList.remove('active');\n",
2533         "        fig.buttons['Zoom'].classList.remove('active');\n",
2534         "    }\n",
2535         "};\n",
2536         "\n",
2537         "mpl.figure.prototype.updated_canvas_event = function () {\n",
2538         "    // Called whenever the canvas gets updated.\n",
2539         "    this.send_message('ack', {});\n",
2540         "};\n",
2541         "\n",
2542         "// A function to construct a web socket function for onmessage handling.\n",
2543         "// Called in the figure constructor.\n",
2544         "mpl.figure.prototype._make_on_message_function = function (fig) {\n",
2545         "    return function socket_on_message(evt) {\n",
2546         "        if (evt.data instanceof Blob) {\n",
2547         "            /* FIXME: We get \"Resource interpreted as Image but\n",
2548         "             * transferred with MIME type text/plain:\" errors on\n",
2549         "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
2550         "             * to be part of the websocket stream */\n",
2551         "            evt.data.type = 'image/png';\n",
2552         "\n",
2553         "            /* Free the memory for the previous frames */\n",
2554         "            if (fig.imageObj.src) {\n",
2555         "                (window.URL || window.webkitURL).revokeObjectURL(\n",
2556         "                    fig.imageObj.src\n",
2557         "                );\n",
2558         "            }\n",
2559         "\n",
2560         "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
2561         "                evt.data\n",
2562         "            );\n",
2563         "            fig.updated_canvas_event();\n",
2564         "            fig.waiting = false;\n",
2565         "            return;\n",
2566         "        } else if (\n",
2567         "            typeof evt.data === 'string' &&\n",
2568         "            evt.data.slice(0, 21) === 'data:image/png;base64'\n",
2569         "        ) {\n",
2570         "            fig.imageObj.src = evt.data;\n",
2571         "            fig.updated_canvas_event();\n",
2572         "            fig.waiting = false;\n",
2573         "            return;\n",
2574         "        }\n",
2575         "\n",
2576         "        var msg = JSON.parse(evt.data);\n",
2577         "        var msg_type = msg['type'];\n",
2578         "\n",
2579         "        // Call the  \"handle_{type}\" callback, which takes\n",
2580         "        // the figure and JSON message as its only arguments.\n",
2581         "        try {\n",
2582         "            var callback = fig['handle_' + msg_type];\n",
2583         "        } catch (e) {\n",
2584         "            console.log(\n",
2585         "                \"No handler for the '\" + msg_type + \"' message type: \",\n",
2586         "                msg\n",
2587         "            );\n",
2588         "            return;\n",
2589         "        }\n",
2590         "\n",
2591         "        if (callback) {\n",
2592         "            try {\n",
2593         "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
2594         "                callback(fig, msg);\n",
2595         "            } catch (e) {\n",
2596         "                console.log(\n",
2597         "                    \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n",
2598         "                    e,\n",
2599         "                    e.stack,\n",
2600         "                    msg\n",
2601         "                );\n",
2602         "            }\n",
2603         "        }\n",
2604         "    };\n",
2605         "};\n",
2606         "\n",
2607         "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
2608         "mpl.findpos = function (e) {\n",
2609         "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
2610         "    var targ;\n",
2611         "    if (!e) {\n",
2612         "        e = window.event;\n",
2613         "    }\n",
2614         "    if (e.target) {\n",
2615         "        targ = e.target;\n",
2616         "    } else if (e.srcElement) {\n",
2617         "        targ = e.srcElement;\n",
2618         "    }\n",
2619         "    if (targ.nodeType === 3) {\n",
2620         "        // defeat Safari bug\n",
2621         "        targ = targ.parentNode;\n",
2622         "    }\n",
2623         "\n",
2624         "    // pageX,Y are the mouse positions relative to the document\n",
2625         "    var boundingRect = targ.getBoundingClientRect();\n",
2626         "    var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n",
2627         "    var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n",
2628         "\n",
2629         "    return { x: x, y: y };\n",
2630         "};\n",
2631         "\n",
2632         "/*\n",
2633         " * return a copy of an object with only non-object keys\n",
2634         " * we need this to avoid circular references\n",
2635         " * http://stackoverflow.com/a/24161582/3208463\n",
2636         " */\n",
2637         "function simpleKeys(original) {\n",
2638         "    return Object.keys(original).reduce(function (obj, key) {\n",
2639         "        if (typeof original[key] !== 'object') {\n",
2640         "            obj[key] = original[key];\n",
2641         "        }\n",
2642         "        return obj;\n",
2643         "    }, {});\n",
2644         "}\n",
2645         "\n",
2646         "mpl.figure.prototype.mouse_event = function (event, name) {\n",
2647         "    var canvas_pos = mpl.findpos(event);\n",
2648         "\n",
2649         "    if (name === 'button_press') {\n",
2650         "        this.canvas.focus();\n",
2651         "        this.canvas_div.focus();\n",
2652         "    }\n",
2653         "\n",
2654         "    var x = canvas_pos.x * this.ratio;\n",
2655         "    var y = canvas_pos.y * this.ratio;\n",
2656         "\n",
2657         "    this.send_message(name, {\n",
2658         "        x: x,\n",
2659         "        y: y,\n",
2660         "        button: event.button,\n",
2661         "        step: event.step,\n",
2662         "        guiEvent: simpleKeys(event),\n",
2663         "    });\n",
2664         "\n",
2665         "    /* This prevents the web browser from automatically changing to\n",
2666         "     * the text insertion cursor when the button is pressed.  We want\n",
2667         "     * to control all of the cursor setting manually through the\n",
2668         "     * 'cursor' event from matplotlib */\n",
2669         "    event.preventDefault();\n",
2670         "    return false;\n",
2671         "};\n",
2672         "\n",
2673         "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n",
2674         "    // Handle any extra behaviour associated with a key event\n",
2675         "};\n",
2676         "\n",
2677         "mpl.figure.prototype.key_event = function (event, name) {\n",
2678         "    // Prevent repeat events\n",
2679         "    if (name === 'key_press') {\n",
2680         "        if (event.which === this._key) {\n",
2681         "            return;\n",
2682         "        } else {\n",
2683         "            this._key = event.which;\n",
2684         "        }\n",
2685         "    }\n",
2686         "    if (name === 'key_release') {\n",
2687         "        this._key = null;\n",
2688         "    }\n",
2689         "\n",
2690         "    var value = '';\n",
2691         "    if (event.ctrlKey && event.which !== 17) {\n",
2692         "        value += 'ctrl+';\n",
2693         "    }\n",
2694         "    if (event.altKey && event.which !== 18) {\n",
2695         "        value += 'alt+';\n",
2696         "    }\n",
2697         "    if (event.shiftKey && event.which !== 16) {\n",
2698         "        value += 'shift+';\n",
2699         "    }\n",
2700         "\n",
2701         "    value += 'k';\n",
2702         "    value += event.which.toString();\n",
2703         "\n",
2704         "    this._key_event_extra(event, name);\n",
2705         "\n",
2706         "    this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n",
2707         "    return false;\n",
2708         "};\n",
2709         "\n",
2710         "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n",
2711         "    if (name === 'download') {\n",
2712         "        this.handle_save(this, null);\n",
2713         "    } else {\n",
2714         "        this.send_message('toolbar_button', { name: name });\n",
2715         "    }\n",
2716         "};\n",
2717         "\n",
2718         "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n",
2719         "    this.message.textContent = tooltip;\n",
2720         "};\n",
2721         "\n",
2722         "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n",
2723         "// prettier-ignore\n",
2724         "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n",
2725         "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
2726         "\n",
2727         "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
2728         "\n",
2729         "mpl.default_extension = \"png\";/* global mpl */\n",
2730         "\n",
2731         "var comm_websocket_adapter = function (comm) {\n",
2732         "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
2733         "    // object with the appropriate methods. Currently this is a non binary\n",
2734         "    // socket, so there is still some room for performance tuning.\n",
2735         "    var ws = {};\n",
2736         "\n",
2737         "    ws.close = function () {\n",
2738         "        comm.close();\n",
2739         "    };\n",
2740         "    ws.send = function (m) {\n",
2741         "        //console.log('sending', m);\n",
2742         "        comm.send(m);\n",
2743         "    };\n",
2744         "    // Register the callback with on_msg.\n",
2745         "    comm.on_msg(function (msg) {\n",
2746         "        //console.log('receiving', msg['content']['data'], msg);\n",
2747         "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
2748         "        ws.onmessage(msg['content']['data']);\n",
2749         "    });\n",
2750         "    return ws;\n",
2751         "};\n",
2752         "\n",
2753         "mpl.mpl_figure_comm = function (comm, msg) {\n",
2754         "    // This is the function which gets called when the mpl process\n",
2755         "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
2756         "\n",
2757         "    var id = msg.content.data.id;\n",
2758         "    // Get hold of the div created by the display call when the Comm\n",
2759         "    // socket was opened in Python.\n",
2760         "    var element = document.getElementById(id);\n",
2761         "    var ws_proxy = comm_websocket_adapter(comm);\n",
2762         "\n",
2763         "    function ondownload(figure, _format) {\n",
2764         "        window.open(figure.canvas.toDataURL());\n",
2765         "    }\n",
2766         "\n",
2767         "    var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n",
2768         "\n",
2769         "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
2770         "    // web socket which is closed, not our websocket->open comm proxy.\n",
2771         "    ws_proxy.onopen();\n",
2772         "\n",
2773         "    fig.parent_element = element;\n",
2774         "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
2775         "    if (!fig.cell_info) {\n",
2776         "        console.error('Failed to find cell for figure', id, fig);\n",
2777         "        return;\n",
2778         "    }\n",
2779         "    fig.cell_info[0].output_area.element.on(\n",
2780         "        'cleared',\n",
2781         "        { fig: fig },\n",
2782         "        fig._remove_fig_handler\n",
2783         "    );\n",
2784         "};\n",
2785         "\n",
2786         "mpl.figure.prototype.handle_close = function (fig, msg) {\n",
2787         "    var width = fig.canvas.width / fig.ratio;\n",
2788         "    fig.cell_info[0].output_area.element.off(\n",
2789         "        'cleared',\n",
2790         "        fig._remove_fig_handler\n",
2791         "    );\n",
2792         "    fig.resizeObserverInstance.unobserve(fig.canvas_div);\n",
2793         "\n",
2794         "    // Update the output cell to use the data from the current canvas.\n",
2795         "    fig.push_to_output();\n",
2796         "    var dataURL = fig.canvas.toDataURL();\n",
2797         "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
2798         "    // the notebook keyboard shortcuts fail.\n",
2799         "    IPython.keyboard_manager.enable();\n",
2800         "    fig.parent_element.innerHTML =\n",
2801         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
2802         "    fig.close_ws(fig, msg);\n",
2803         "};\n",
2804         "\n",
2805         "mpl.figure.prototype.close_ws = function (fig, msg) {\n",
2806         "    fig.send_message('closing', msg);\n",
2807         "    // fig.ws.close()\n",
2808         "};\n",
2809         "\n",
2810         "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n",
2811         "    // Turn the data on the canvas into data in the output cell.\n",
2812         "    var width = this.canvas.width / this.ratio;\n",
2813         "    var dataURL = this.canvas.toDataURL();\n",
2814         "    this.cell_info[1]['text/html'] =\n",
2815         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
2816         "};\n",
2817         "\n",
2818         "mpl.figure.prototype.updated_canvas_event = function () {\n",
2819         "    // Tell IPython that the notebook contents must change.\n",
2820         "    IPython.notebook.set_dirty(true);\n",
2821         "    this.send_message('ack', {});\n",
2822         "    var fig = this;\n",
2823         "    // Wait a second, then push the new image to the DOM so\n",
2824         "    // that it is saved nicely (might be nice to debounce this).\n",
2825         "    setTimeout(function () {\n",
2826         "        fig.push_to_output();\n",
2827         "    }, 1000);\n",
2828         "};\n",
2829         "\n",
2830         "mpl.figure.prototype._init_toolbar = function () {\n",
2831         "    var fig = this;\n",
2832         "\n",
2833         "    var toolbar = document.createElement('div');\n",
2834         "    toolbar.classList = 'btn-toolbar';\n",
2835         "    this.root.appendChild(toolbar);\n",
2836         "\n",
2837         "    function on_click_closure(name) {\n",
2838         "        return function (_event) {\n",
2839         "            return fig.toolbar_button_onclick(name);\n",
2840         "        };\n",
2841         "    }\n",
2842         "\n",
2843         "    function on_mouseover_closure(tooltip) {\n",
2844         "        return function (event) {\n",
2845         "            if (!event.currentTarget.disabled) {\n",
2846         "                return fig.toolbar_button_onmouseover(tooltip);\n",
2847         "            }\n",
2848         "        };\n",
2849         "    }\n",
2850         "\n",
2851         "    fig.buttons = {};\n",
2852         "    var buttonGroup = document.createElement('div');\n",
2853         "    buttonGroup.classList = 'btn-group';\n",
2854         "    var button;\n",
2855         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
2856         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
2857         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
2858         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
2859         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
2860         "\n",
2861         "        if (!name) {\n",
2862         "            /* Instead of a spacer, we start a new button group. */\n",
2863         "            if (buttonGroup.hasChildNodes()) {\n",
2864         "                toolbar.appendChild(buttonGroup);\n",
2865         "            }\n",
2866         "            buttonGroup = document.createElement('div');\n",
2867         "            buttonGroup.classList = 'btn-group';\n",
2868         "            continue;\n",
2869         "        }\n",
2870         "\n",
2871         "        button = fig.buttons[name] = document.createElement('button');\n",
2872         "        button.classList = 'btn btn-default';\n",
2873         "        button.href = '#';\n",
2874         "        button.title = name;\n",
2875         "        button.innerHTML = '<i class=\"fa ' + image + ' fa-lg\"></i>';\n",
2876         "        button.addEventListener('click', on_click_closure(method_name));\n",
2877         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
2878         "        buttonGroup.appendChild(button);\n",
2879         "    }\n",
2880         "\n",
2881         "    if (buttonGroup.hasChildNodes()) {\n",
2882         "        toolbar.appendChild(buttonGroup);\n",
2883         "    }\n",
2884         "\n",
2885         "    // Add the status bar.\n",
2886         "    var status_bar = document.createElement('span');\n",
2887         "    status_bar.classList = 'mpl-message pull-right';\n",
2888         "    toolbar.appendChild(status_bar);\n",
2889         "    this.message = status_bar;\n",
2890         "\n",
2891         "    // Add the close button to the window.\n",
2892         "    var buttongrp = document.createElement('div');\n",
2893         "    buttongrp.classList = 'btn-group inline pull-right';\n",
2894         "    button = document.createElement('button');\n",
2895         "    button.classList = 'btn btn-mini btn-primary';\n",
2896         "    button.href = '#';\n",
2897         "    button.title = 'Stop Interaction';\n",
2898         "    button.innerHTML = '<i class=\"fa fa-power-off icon-remove icon-large\"></i>';\n",
2899         "    button.addEventListener('click', function (_evt) {\n",
2900         "        fig.handle_close(fig, {});\n",
2901         "    });\n",
2902         "    button.addEventListener(\n",
2903         "        'mouseover',\n",
2904         "        on_mouseover_closure('Stop Interaction')\n",
2905         "    );\n",
2906         "    buttongrp.appendChild(button);\n",
2907         "    var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n",
2908         "    titlebar.insertBefore(buttongrp, titlebar.firstChild);\n",
2909         "};\n",
2910         "\n",
2911         "mpl.figure.prototype._remove_fig_handler = function (event) {\n",
2912         "    var fig = event.data.fig;\n",
2913         "    if (event.target !== this) {\n",
2914         "        // Ignore bubbled events from children.\n",
2915         "        return;\n",
2916         "    }\n",
2917         "    fig.close_ws(fig, {});\n",
2918         "};\n",
2919         "\n",
2920         "mpl.figure.prototype._root_extra_style = function (el) {\n",
2921         "    el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n",
2922         "};\n",
2923         "\n",
2924         "mpl.figure.prototype._canvas_extra_style = function (el) {\n",
2925         "    // this is important to make the div 'focusable\n",
2926         "    el.setAttribute('tabindex', 0);\n",
2927         "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
2928         "    // off when our div gets focus\n",
2929         "\n",
2930         "    // location in version 3\n",
2931         "    if (IPython.notebook.keyboard_manager) {\n",
2932         "        IPython.notebook.keyboard_manager.register_events(el);\n",
2933         "    } else {\n",
2934         "        // location in version 2\n",
2935         "        IPython.keyboard_manager.register_events(el);\n",
2936         "    }\n",
2937         "};\n",
2938         "\n",
2939         "mpl.figure.prototype._key_event_extra = function (event, _name) {\n",
2940         "    var manager = IPython.notebook.keyboard_manager;\n",
2941         "    if (!manager) {\n",
2942         "        manager = IPython.keyboard_manager;\n",
2943         "    }\n",
2944         "\n",
2945         "    // Check for shift+enter\n",
2946         "    if (event.shiftKey && event.which === 13) {\n",
2947         "        this.canvas_div.blur();\n",
2948         "        // select the cell after this one\n",
2949         "        var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
2950         "        IPython.notebook.select(index + 1);\n",
2951         "    }\n",
2952         "};\n",
2953         "\n",
2954         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
2955         "    fig.ondownload(fig, null);\n",
2956         "};\n",
2957         "\n",
2958         "mpl.find_output_cell = function (html_output) {\n",
2959         "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
2960         "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
2961         "    // IPython event is triggered only after the cells have been serialised, which for\n",
2962         "    // our purposes (turning an active figure into a static one), is too late.\n",
2963         "    var cells = IPython.notebook.get_cells();\n",
2964         "    var ncells = cells.length;\n",
2965         "    for (var i = 0; i < ncells; i++) {\n",
2966         "        var cell = cells[i];\n",
2967         "        if (cell.cell_type === 'code') {\n",
2968         "            for (var j = 0; j < cell.output_area.outputs.length; j++) {\n",
2969         "                var data = cell.output_area.outputs[j];\n",
2970         "                if (data.data) {\n",
2971         "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
2972         "                    data = data.data;\n",
2973         "                }\n",
2974         "                if (data['text/html'] === html_output) {\n",
2975         "                    return [cell, data, j];\n",
2976         "                }\n",
2977         "            }\n",
2978         "        }\n",
2979         "    }\n",
2980         "};\n",
2981         "\n",
2982         "// Register the function which deals with the matplotlib target/channel.\n",
2983         "// The kernel may be null if the page has been refreshed.\n",
2984         "if (IPython.notebook.kernel !== null) {\n",
2985         "    IPython.notebook.kernel.comm_manager.register_target(\n",
2986         "        'matplotlib',\n",
2987         "        mpl.mpl_figure_comm\n",
2988         "    );\n",
2989         "}\n"
2990        ],
2991        "text/plain": [
2992         "<IPython.core.display.Javascript object>"
2993        ]
2994       },
2995       "metadata": {},
2996       "output_type": "display_data"
2997      },
2998      {
2999       "data": {
3000        "text/html": [
3001         "<div id='95d27d01-6329-4454-a292-133d62c8976b'></div>"
3002        ],
3003        "text/plain": [
3004         "<IPython.core.display.HTML object>"
3005        ]
3006       },
3007       "metadata": {},
3008       "output_type": "display_data"
3009      },
3010      {
3011       "data": {
3012        "application/javascript": [
3013         "/* Put everything inside the global mpl namespace */\n",
3014         "/* global mpl */\n",
3015         "window.mpl = {};\n",
3016         "\n",
3017         "mpl.get_websocket_type = function () {\n",
3018         "    if (typeof WebSocket !== 'undefined') {\n",
3019         "        return WebSocket;\n",
3020         "    } else if (typeof MozWebSocket !== 'undefined') {\n",
3021         "        return MozWebSocket;\n",
3022         "    } else {\n",
3023         "        alert(\n",
3024         "            'Your browser does not have WebSocket support. ' +\n",
3025         "                'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
3026         "                'Firefox 4 and 5 are also supported but you ' +\n",
3027         "                'have to enable WebSockets in about:config.'\n",
3028         "        );\n",
3029         "    }\n",
3030         "};\n",
3031         "\n",
3032         "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n",
3033         "    this.id = figure_id;\n",
3034         "\n",
3035         "    this.ws = websocket;\n",
3036         "\n",
3037         "    this.supports_binary = this.ws.binaryType !== undefined;\n",
3038         "\n",
3039         "    if (!this.supports_binary) {\n",
3040         "        var warnings = document.getElementById('mpl-warnings');\n",
3041         "        if (warnings) {\n",
3042         "            warnings.style.display = 'block';\n",
3043         "            warnings.textContent =\n",
3044         "                'This browser does not support binary websocket messages. ' +\n",
3045         "                'Performance may be slow.';\n",
3046         "        }\n",
3047         "    }\n",
3048         "\n",
3049         "    this.imageObj = new Image();\n",
3050         "\n",
3051         "    this.context = undefined;\n",
3052         "    this.message = undefined;\n",
3053         "    this.canvas = undefined;\n",
3054         "    this.rubberband_canvas = undefined;\n",
3055         "    this.rubberband_context = undefined;\n",
3056         "    this.format_dropdown = undefined;\n",
3057         "\n",
3058         "    this.image_mode = 'full';\n",
3059         "\n",
3060         "    this.root = document.createElement('div');\n",
3061         "    this.root.setAttribute('style', 'display: inline-block');\n",
3062         "    this._root_extra_style(this.root);\n",
3063         "\n",
3064         "    parent_element.appendChild(this.root);\n",
3065         "\n",
3066         "    this._init_header(this);\n",
3067         "    this._init_canvas(this);\n",
3068         "    this._init_toolbar(this);\n",
3069         "\n",
3070         "    var fig = this;\n",
3071         "\n",
3072         "    this.waiting = false;\n",
3073         "\n",
3074         "    this.ws.onopen = function () {\n",
3075         "        fig.send_message('supports_binary', { value: fig.supports_binary });\n",
3076         "        fig.send_message('send_image_mode', {});\n",
3077         "        if (fig.ratio !== 1) {\n",
3078         "            fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n",
3079         "        }\n",
3080         "        fig.send_message('refresh', {});\n",
3081         "    };\n",
3082         "\n",
3083         "    this.imageObj.onload = function () {\n",
3084         "        if (fig.image_mode === 'full') {\n",
3085         "            // Full images could contain transparency (where diff images\n",
3086         "            // almost always do), so we need to clear the canvas so that\n",
3087         "            // there is no ghosting.\n",
3088         "            fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
3089         "        }\n",
3090         "        fig.context.drawImage(fig.imageObj, 0, 0);\n",
3091         "    };\n",
3092         "\n",
3093         "    this.imageObj.onunload = function () {\n",
3094         "        fig.ws.close();\n",
3095         "    };\n",
3096         "\n",
3097         "    this.ws.onmessage = this._make_on_message_function(this);\n",
3098         "\n",
3099         "    this.ondownload = ondownload;\n",
3100         "};\n",
3101         "\n",
3102         "mpl.figure.prototype._init_header = function () {\n",
3103         "    var titlebar = document.createElement('div');\n",
3104         "    titlebar.classList =\n",
3105         "        'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n",
3106         "    var titletext = document.createElement('div');\n",
3107         "    titletext.classList = 'ui-dialog-title';\n",
3108         "    titletext.setAttribute(\n",
3109         "        'style',\n",
3110         "        'width: 100%; text-align: center; padding: 3px;'\n",
3111         "    );\n",
3112         "    titlebar.appendChild(titletext);\n",
3113         "    this.root.appendChild(titlebar);\n",
3114         "    this.header = titletext;\n",
3115         "};\n",
3116         "\n",
3117         "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n",
3118         "\n",
3119         "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n",
3120         "\n",
3121         "mpl.figure.prototype._init_canvas = function () {\n",
3122         "    var fig = this;\n",
3123         "\n",
3124         "    var canvas_div = (this.canvas_div = document.createElement('div'));\n",
3125         "    canvas_div.setAttribute(\n",
3126         "        'style',\n",
3127         "        'border: 1px solid #ddd;' +\n",
3128         "            'box-sizing: content-box;' +\n",
3129         "            'clear: both;' +\n",
3130         "            'min-height: 1px;' +\n",
3131         "            'min-width: 1px;' +\n",
3132         "            'outline: 0;' +\n",
3133         "            'overflow: hidden;' +\n",
3134         "            'position: relative;' +\n",
3135         "            'resize: both;'\n",
3136         "    );\n",
3137         "\n",
3138         "    function on_keyboard_event_closure(name) {\n",
3139         "        return function (event) {\n",
3140         "            return fig.key_event(event, name);\n",
3141         "        };\n",
3142         "    }\n",
3143         "\n",
3144         "    canvas_div.addEventListener(\n",
3145         "        'keydown',\n",
3146         "        on_keyboard_event_closure('key_press')\n",
3147         "    );\n",
3148         "    canvas_div.addEventListener(\n",
3149         "        'keyup',\n",
3150         "        on_keyboard_event_closure('key_release')\n",
3151         "    );\n",
3152         "\n",
3153         "    this._canvas_extra_style(canvas_div);\n",
3154         "    this.root.appendChild(canvas_div);\n",
3155         "\n",
3156         "    var canvas = (this.canvas = document.createElement('canvas'));\n",
3157         "    canvas.classList.add('mpl-canvas');\n",
3158         "    canvas.setAttribute('style', 'box-sizing: content-box;');\n",
3159         "\n",
3160         "    this.context = canvas.getContext('2d');\n",
3161         "\n",
3162         "    var backingStore =\n",
3163         "        this.context.backingStorePixelRatio ||\n",
3164         "        this.context.webkitBackingStorePixelRatio ||\n",
3165         "        this.context.mozBackingStorePixelRatio ||\n",
3166         "        this.context.msBackingStorePixelRatio ||\n",
3167         "        this.context.oBackingStorePixelRatio ||\n",
3168         "        this.context.backingStorePixelRatio ||\n",
3169         "        1;\n",
3170         "\n",
3171         "    this.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
3172         "\n",
3173         "    var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n",
3174         "        'canvas'\n",
3175         "    ));\n",
3176         "    rubberband_canvas.setAttribute(\n",
3177         "        'style',\n",
3178         "        'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n",
3179         "    );\n",
3180         "\n",
3181         "    // Apply a ponyfill if ResizeObserver is not implemented by browser.\n",
3182         "    if (this.ResizeObserver === undefined) {\n",
3183         "        if (window.ResizeObserver !== undefined) {\n",
3184         "            this.ResizeObserver = window.ResizeObserver;\n",
3185         "        } else {\n",
3186         "            var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n",
3187         "            this.ResizeObserver = obs.ResizeObserver;\n",
3188         "        }\n",
3189         "    }\n",
3190         "\n",
3191         "    this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n",
3192         "        var nentries = entries.length;\n",
3193         "        for (var i = 0; i < nentries; i++) {\n",
3194         "            var entry = entries[i];\n",
3195         "            var width, height;\n",
3196         "            if (entry.contentBoxSize) {\n",
3197         "                if (entry.contentBoxSize instanceof Array) {\n",
3198         "                    // Chrome 84 implements new version of spec.\n",
3199         "                    width = entry.contentBoxSize[0].inlineSize;\n",
3200         "                    height = entry.contentBoxSize[0].blockSize;\n",
3201         "                } else {\n",
3202         "                    // Firefox implements old version of spec.\n",
3203         "                    width = entry.contentBoxSize.inlineSize;\n",
3204         "                    height = entry.contentBoxSize.blockSize;\n",
3205         "                }\n",
3206         "            } else {\n",
3207         "                // Chrome <84 implements even older version of spec.\n",
3208         "                width = entry.contentRect.width;\n",
3209         "                height = entry.contentRect.height;\n",
3210         "            }\n",
3211         "\n",
3212         "            // Keep the size of the canvas and rubber band canvas in sync with\n",
3213         "            // the canvas container.\n",
3214         "            if (entry.devicePixelContentBoxSize) {\n",
3215         "                // Chrome 84 implements new version of spec.\n",
3216         "                canvas.setAttribute(\n",
3217         "                    'width',\n",
3218         "                    entry.devicePixelContentBoxSize[0].inlineSize\n",
3219         "                );\n",
3220         "                canvas.setAttribute(\n",
3221         "                    'height',\n",
3222         "                    entry.devicePixelContentBoxSize[0].blockSize\n",
3223         "                );\n",
3224         "            } else {\n",
3225         "                canvas.setAttribute('width', width * fig.ratio);\n",
3226         "                canvas.setAttribute('height', height * fig.ratio);\n",
3227         "            }\n",
3228         "            canvas.setAttribute(\n",
3229         "                'style',\n",
3230         "                'width: ' + width + 'px; height: ' + height + 'px;'\n",
3231         "            );\n",
3232         "\n",
3233         "            rubberband_canvas.setAttribute('width', width);\n",
3234         "            rubberband_canvas.setAttribute('height', height);\n",
3235         "\n",
3236         "            // And update the size in Python. We ignore the initial 0/0 size\n",
3237         "            // that occurs as the element is placed into the DOM, which should\n",
3238         "            // otherwise not happen due to the minimum size styling.\n",
3239         "            if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n",
3240         "                fig.request_resize(width, height);\n",
3241         "            }\n",
3242         "        }\n",
3243         "    });\n",
3244         "    this.resizeObserverInstance.observe(canvas_div);\n",
3245         "\n",
3246         "    function on_mouse_event_closure(name) {\n",
3247         "        return function (event) {\n",
3248         "            return fig.mouse_event(event, name);\n",
3249         "        };\n",
3250         "    }\n",
3251         "\n",
3252         "    rubberband_canvas.addEventListener(\n",
3253         "        'mousedown',\n",
3254         "        on_mouse_event_closure('button_press')\n",
3255         "    );\n",
3256         "    rubberband_canvas.addEventListener(\n",
3257         "        'mouseup',\n",
3258         "        on_mouse_event_closure('button_release')\n",
3259         "    );\n",
3260         "    // Throttle sequential mouse events to 1 every 20ms.\n",
3261         "    rubberband_canvas.addEventListener(\n",
3262         "        'mousemove',\n",
3263         "        on_mouse_event_closure('motion_notify')\n",
3264         "    );\n",
3265         "\n",
3266         "    rubberband_canvas.addEventListener(\n",
3267         "        'mouseenter',\n",
3268         "        on_mouse_event_closure('figure_enter')\n",
3269         "    );\n",
3270         "    rubberband_canvas.addEventListener(\n",
3271         "        'mouseleave',\n",
3272         "        on_mouse_event_closure('figure_leave')\n",
3273         "    );\n",
3274         "\n",
3275         "    canvas_div.addEventListener('wheel', function (event) {\n",
3276         "        if (event.deltaY < 0) {\n",
3277         "            event.step = 1;\n",
3278         "        } else {\n",
3279         "            event.step = -1;\n",
3280         "        }\n",
3281         "        on_mouse_event_closure('scroll')(event);\n",
3282         "    });\n",
3283         "\n",
3284         "    canvas_div.appendChild(canvas);\n",
3285         "    canvas_div.appendChild(rubberband_canvas);\n",
3286         "\n",
3287         "    this.rubberband_context = rubberband_canvas.getContext('2d');\n",
3288         "    this.rubberband_context.strokeStyle = '#000000';\n",
3289         "\n",
3290         "    this._resize_canvas = function (width, height, forward) {\n",
3291         "        if (forward) {\n",
3292         "            canvas_div.style.width = width + 'px';\n",
3293         "            canvas_div.style.height = height + 'px';\n",
3294         "        }\n",
3295         "    };\n",
3296         "\n",
3297         "    // Disable right mouse context menu.\n",
3298         "    this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n",
3299         "        event.preventDefault();\n",
3300         "        return false;\n",
3301         "    });\n",
3302         "\n",
3303         "    function set_focus() {\n",
3304         "        canvas.focus();\n",
3305         "        canvas_div.focus();\n",
3306         "    }\n",
3307         "\n",
3308         "    window.setTimeout(set_focus, 100);\n",
3309         "};\n",
3310         "\n",
3311         "mpl.figure.prototype._init_toolbar = function () {\n",
3312         "    var fig = this;\n",
3313         "\n",
3314         "    var toolbar = document.createElement('div');\n",
3315         "    toolbar.classList = 'mpl-toolbar';\n",
3316         "    this.root.appendChild(toolbar);\n",
3317         "\n",
3318         "    function on_click_closure(name) {\n",
3319         "        return function (_event) {\n",
3320         "            return fig.toolbar_button_onclick(name);\n",
3321         "        };\n",
3322         "    }\n",
3323         "\n",
3324         "    function on_mouseover_closure(tooltip) {\n",
3325         "        return function (event) {\n",
3326         "            if (!event.currentTarget.disabled) {\n",
3327         "                return fig.toolbar_button_onmouseover(tooltip);\n",
3328         "            }\n",
3329         "        };\n",
3330         "    }\n",
3331         "\n",
3332         "    fig.buttons = {};\n",
3333         "    var buttonGroup = document.createElement('div');\n",
3334         "    buttonGroup.classList = 'mpl-button-group';\n",
3335         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
3336         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
3337         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
3338         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
3339         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
3340         "\n",
3341         "        if (!name) {\n",
3342         "            /* Instead of a spacer, we start a new button group. */\n",
3343         "            if (buttonGroup.hasChildNodes()) {\n",
3344         "                toolbar.appendChild(buttonGroup);\n",
3345         "            }\n",
3346         "            buttonGroup = document.createElement('div');\n",
3347         "            buttonGroup.classList = 'mpl-button-group';\n",
3348         "            continue;\n",
3349         "        }\n",
3350         "\n",
3351         "        var button = (fig.buttons[name] = document.createElement('button'));\n",
3352         "        button.classList = 'mpl-widget';\n",
3353         "        button.setAttribute('role', 'button');\n",
3354         "        button.setAttribute('aria-disabled', 'false');\n",
3355         "        button.addEventListener('click', on_click_closure(method_name));\n",
3356         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
3357         "\n",
3358         "        var icon_img = document.createElement('img');\n",
3359         "        icon_img.src = '_images/' + image + '.png';\n",
3360         "        icon_img.srcset = '_images/' + image + '_large.png 2x';\n",
3361         "        icon_img.alt = tooltip;\n",
3362         "        button.appendChild(icon_img);\n",
3363         "\n",
3364         "        buttonGroup.appendChild(button);\n",
3365         "    }\n",
3366         "\n",
3367         "    if (buttonGroup.hasChildNodes()) {\n",
3368         "        toolbar.appendChild(buttonGroup);\n",
3369         "    }\n",
3370         "\n",
3371         "    var fmt_picker = document.createElement('select');\n",
3372         "    fmt_picker.classList = 'mpl-widget';\n",
3373         "    toolbar.appendChild(fmt_picker);\n",
3374         "    this.format_dropdown = fmt_picker;\n",
3375         "\n",
3376         "    for (var ind in mpl.extensions) {\n",
3377         "        var fmt = mpl.extensions[ind];\n",
3378         "        var option = document.createElement('option');\n",
3379         "        option.selected = fmt === mpl.default_extension;\n",
3380         "        option.innerHTML = fmt;\n",
3381         "        fmt_picker.appendChild(option);\n",
3382         "    }\n",
3383         "\n",
3384         "    var status_bar = document.createElement('span');\n",
3385         "    status_bar.classList = 'mpl-message';\n",
3386         "    toolbar.appendChild(status_bar);\n",
3387         "    this.message = status_bar;\n",
3388         "};\n",
3389         "\n",
3390         "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n",
3391         "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
3392         "    // which will in turn request a refresh of the image.\n",
3393         "    this.send_message('resize', { width: x_pixels, height: y_pixels });\n",
3394         "};\n",
3395         "\n",
3396         "mpl.figure.prototype.send_message = function (type, properties) {\n",
3397         "    properties['type'] = type;\n",
3398         "    properties['figure_id'] = this.id;\n",
3399         "    this.ws.send(JSON.stringify(properties));\n",
3400         "};\n",
3401         "\n",
3402         "mpl.figure.prototype.send_draw_message = function () {\n",
3403         "    if (!this.waiting) {\n",
3404         "        this.waiting = true;\n",
3405         "        this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n",
3406         "    }\n",
3407         "};\n",
3408         "\n",
3409         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
3410         "    var format_dropdown = fig.format_dropdown;\n",
3411         "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
3412         "    fig.ondownload(fig, format);\n",
3413         "};\n",
3414         "\n",
3415         "mpl.figure.prototype.handle_resize = function (fig, msg) {\n",
3416         "    var size = msg['size'];\n",
3417         "    if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n",
3418         "        fig._resize_canvas(size[0], size[1], msg['forward']);\n",
3419         "        fig.send_message('refresh', {});\n",
3420         "    }\n",
3421         "};\n",
3422         "\n",
3423         "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n",
3424         "    var x0 = msg['x0'] / fig.ratio;\n",
3425         "    var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n",
3426         "    var x1 = msg['x1'] / fig.ratio;\n",
3427         "    var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n",
3428         "    x0 = Math.floor(x0) + 0.5;\n",
3429         "    y0 = Math.floor(y0) + 0.5;\n",
3430         "    x1 = Math.floor(x1) + 0.5;\n",
3431         "    y1 = Math.floor(y1) + 0.5;\n",
3432         "    var min_x = Math.min(x0, x1);\n",
3433         "    var min_y = Math.min(y0, y1);\n",
3434         "    var width = Math.abs(x1 - x0);\n",
3435         "    var height = Math.abs(y1 - y0);\n",
3436         "\n",
3437         "    fig.rubberband_context.clearRect(\n",
3438         "        0,\n",
3439         "        0,\n",
3440         "        fig.canvas.width / fig.ratio,\n",
3441         "        fig.canvas.height / fig.ratio\n",
3442         "    );\n",
3443         "\n",
3444         "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
3445         "};\n",
3446         "\n",
3447         "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n",
3448         "    // Updates the figure title.\n",
3449         "    fig.header.textContent = msg['label'];\n",
3450         "};\n",
3451         "\n",
3452         "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n",
3453         "    var cursor = msg['cursor'];\n",
3454         "    switch (cursor) {\n",
3455         "        case 0:\n",
3456         "            cursor = 'pointer';\n",
3457         "            break;\n",
3458         "        case 1:\n",
3459         "            cursor = 'default';\n",
3460         "            break;\n",
3461         "        case 2:\n",
3462         "            cursor = 'crosshair';\n",
3463         "            break;\n",
3464         "        case 3:\n",
3465         "            cursor = 'move';\n",
3466         "            break;\n",
3467         "    }\n",
3468         "    fig.rubberband_canvas.style.cursor = cursor;\n",
3469         "};\n",
3470         "\n",
3471         "mpl.figure.prototype.handle_message = function (fig, msg) {\n",
3472         "    fig.message.textContent = msg['message'];\n",
3473         "};\n",
3474         "\n",
3475         "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n",
3476         "    // Request the server to send over a new figure.\n",
3477         "    fig.send_draw_message();\n",
3478         "};\n",
3479         "\n",
3480         "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n",
3481         "    fig.image_mode = msg['mode'];\n",
3482         "};\n",
3483         "\n",
3484         "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n",
3485         "    for (var key in msg) {\n",
3486         "        if (!(key in fig.buttons)) {\n",
3487         "            continue;\n",
3488         "        }\n",
3489         "        fig.buttons[key].disabled = !msg[key];\n",
3490         "        fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n",
3491         "    }\n",
3492         "};\n",
3493         "\n",
3494         "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n",
3495         "    if (msg['mode'] === 'PAN') {\n",
3496         "        fig.buttons['Pan'].classList.add('active');\n",
3497         "        fig.buttons['Zoom'].classList.remove('active');\n",
3498         "    } else if (msg['mode'] === 'ZOOM') {\n",
3499         "        fig.buttons['Pan'].classList.remove('active');\n",
3500         "        fig.buttons['Zoom'].classList.add('active');\n",
3501         "    } else {\n",
3502         "        fig.buttons['Pan'].classList.remove('active');\n",
3503         "        fig.buttons['Zoom'].classList.remove('active');\n",
3504         "    }\n",
3505         "};\n",
3506         "\n",
3507         "mpl.figure.prototype.updated_canvas_event = function () {\n",
3508         "    // Called whenever the canvas gets updated.\n",
3509         "    this.send_message('ack', {});\n",
3510         "};\n",
3511         "\n",
3512         "// A function to construct a web socket function for onmessage handling.\n",
3513         "// Called in the figure constructor.\n",
3514         "mpl.figure.prototype._make_on_message_function = function (fig) {\n",
3515         "    return function socket_on_message(evt) {\n",
3516         "        if (evt.data instanceof Blob) {\n",
3517         "            /* FIXME: We get \"Resource interpreted as Image but\n",
3518         "             * transferred with MIME type text/plain:\" errors on\n",
3519         "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
3520         "             * to be part of the websocket stream */\n",
3521         "            evt.data.type = 'image/png';\n",
3522         "\n",
3523         "            /* Free the memory for the previous frames */\n",
3524         "            if (fig.imageObj.src) {\n",
3525         "                (window.URL || window.webkitURL).revokeObjectURL(\n",
3526         "                    fig.imageObj.src\n",
3527         "                );\n",
3528         "            }\n",
3529         "\n",
3530         "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
3531         "                evt.data\n",
3532         "            );\n",
3533         "            fig.updated_canvas_event();\n",
3534         "            fig.waiting = false;\n",
3535         "            return;\n",
3536         "        } else if (\n",
3537         "            typeof evt.data === 'string' &&\n",
3538         "            evt.data.slice(0, 21) === 'data:image/png;base64'\n",
3539         "        ) {\n",
3540         "            fig.imageObj.src = evt.data;\n",
3541         "            fig.updated_canvas_event();\n",
3542         "            fig.waiting = false;\n",
3543         "            return;\n",
3544         "        }\n",
3545         "\n",
3546         "        var msg = JSON.parse(evt.data);\n",
3547         "        var msg_type = msg['type'];\n",
3548         "\n",
3549         "        // Call the  \"handle_{type}\" callback, which takes\n",
3550         "        // the figure and JSON message as its only arguments.\n",
3551         "        try {\n",
3552         "            var callback = fig['handle_' + msg_type];\n",
3553         "        } catch (e) {\n",
3554         "            console.log(\n",
3555         "                \"No handler for the '\" + msg_type + \"' message type: \",\n",
3556         "                msg\n",
3557         "            );\n",
3558         "            return;\n",
3559         "        }\n",
3560         "\n",
3561         "        if (callback) {\n",
3562         "            try {\n",
3563         "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
3564         "                callback(fig, msg);\n",
3565         "            } catch (e) {\n",
3566         "                console.log(\n",
3567         "                    \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n",
3568         "                    e,\n",
3569         "                    e.stack,\n",
3570         "                    msg\n",
3571         "                );\n",
3572         "            }\n",
3573         "        }\n",
3574         "    };\n",
3575         "};\n",
3576         "\n",
3577         "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
3578         "mpl.findpos = function (e) {\n",
3579         "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
3580         "    var targ;\n",
3581         "    if (!e) {\n",
3582         "        e = window.event;\n",
3583         "    }\n",
3584         "    if (e.target) {\n",
3585         "        targ = e.target;\n",
3586         "    } else if (e.srcElement) {\n",
3587         "        targ = e.srcElement;\n",
3588         "    }\n",
3589         "    if (targ.nodeType === 3) {\n",
3590         "        // defeat Safari bug\n",
3591         "        targ = targ.parentNode;\n",
3592         "    }\n",
3593         "\n",
3594         "    // pageX,Y are the mouse positions relative to the document\n",
3595         "    var boundingRect = targ.getBoundingClientRect();\n",
3596         "    var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n",
3597         "    var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n",
3598         "\n",
3599         "    return { x: x, y: y };\n",
3600         "};\n",
3601         "\n",
3602         "/*\n",
3603         " * return a copy of an object with only non-object keys\n",
3604         " * we need this to avoid circular references\n",
3605         " * http://stackoverflow.com/a/24161582/3208463\n",
3606         " */\n",
3607         "function simpleKeys(original) {\n",
3608         "    return Object.keys(original).reduce(function (obj, key) {\n",
3609         "        if (typeof original[key] !== 'object') {\n",
3610         "            obj[key] = original[key];\n",
3611         "        }\n",
3612         "        return obj;\n",
3613         "    }, {});\n",
3614         "}\n",
3615         "\n",
3616         "mpl.figure.prototype.mouse_event = function (event, name) {\n",
3617         "    var canvas_pos = mpl.findpos(event);\n",
3618         "\n",
3619         "    if (name === 'button_press') {\n",
3620         "        this.canvas.focus();\n",
3621         "        this.canvas_div.focus();\n",
3622         "    }\n",
3623         "\n",
3624         "    var x = canvas_pos.x * this.ratio;\n",
3625         "    var y = canvas_pos.y * this.ratio;\n",
3626         "\n",
3627         "    this.send_message(name, {\n",
3628         "        x: x,\n",
3629         "        y: y,\n",
3630         "        button: event.button,\n",
3631         "        step: event.step,\n",
3632         "        guiEvent: simpleKeys(event),\n",
3633         "    });\n",
3634         "\n",
3635         "    /* This prevents the web browser from automatically changing to\n",
3636         "     * the text insertion cursor when the button is pressed.  We want\n",
3637         "     * to control all of the cursor setting manually through the\n",
3638         "     * 'cursor' event from matplotlib */\n",
3639         "    event.preventDefault();\n",
3640         "    return false;\n",
3641         "};\n",
3642         "\n",
3643         "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n",
3644         "    // Handle any extra behaviour associated with a key event\n",
3645         "};\n",
3646         "\n",
3647         "mpl.figure.prototype.key_event = function (event, name) {\n",
3648         "    // Prevent repeat events\n",
3649         "    if (name === 'key_press') {\n",
3650         "        if (event.which === this._key) {\n",
3651         "            return;\n",
3652         "        } else {\n",
3653         "            this._key = event.which;\n",
3654         "        }\n",
3655         "    }\n",
3656         "    if (name === 'key_release') {\n",
3657         "        this._key = null;\n",
3658         "    }\n",
3659         "\n",
3660         "    var value = '';\n",
3661         "    if (event.ctrlKey && event.which !== 17) {\n",
3662         "        value += 'ctrl+';\n",
3663         "    }\n",
3664         "    if (event.altKey && event.which !== 18) {\n",
3665         "        value += 'alt+';\n",
3666         "    }\n",
3667         "    if (event.shiftKey && event.which !== 16) {\n",
3668         "        value += 'shift+';\n",
3669         "    }\n",
3670         "\n",
3671         "    value += 'k';\n",
3672         "    value += event.which.toString();\n",
3673         "\n",
3674         "    this._key_event_extra(event, name);\n",
3675         "\n",
3676         "    this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n",
3677         "    return false;\n",
3678         "};\n",
3679         "\n",
3680         "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n",
3681         "    if (name === 'download') {\n",
3682         "        this.handle_save(this, null);\n",
3683         "    } else {\n",
3684         "        this.send_message('toolbar_button', { name: name });\n",
3685         "    }\n",
3686         "};\n",
3687         "\n",
3688         "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n",
3689         "    this.message.textContent = tooltip;\n",
3690         "};\n",
3691         "\n",
3692         "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n",
3693         "// prettier-ignore\n",
3694         "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n",
3695         "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
3696         "\n",
3697         "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
3698         "\n",
3699         "mpl.default_extension = \"png\";/* global mpl */\n",
3700         "\n",
3701         "var comm_websocket_adapter = function (comm) {\n",
3702         "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
3703         "    // object with the appropriate methods. Currently this is a non binary\n",
3704         "    // socket, so there is still some room for performance tuning.\n",
3705         "    var ws = {};\n",
3706         "\n",
3707         "    ws.close = function () {\n",
3708         "        comm.close();\n",
3709         "    };\n",
3710         "    ws.send = function (m) {\n",
3711         "        //console.log('sending', m);\n",
3712         "        comm.send(m);\n",
3713         "    };\n",
3714         "    // Register the callback with on_msg.\n",
3715         "    comm.on_msg(function (msg) {\n",
3716         "        //console.log('receiving', msg['content']['data'], msg);\n",
3717         "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
3718         "        ws.onmessage(msg['content']['data']);\n",
3719         "    });\n",
3720         "    return ws;\n",
3721         "};\n",
3722         "\n",
3723         "mpl.mpl_figure_comm = function (comm, msg) {\n",
3724         "    // This is the function which gets called when the mpl process\n",
3725         "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
3726         "\n",
3727         "    var id = msg.content.data.id;\n",
3728         "    // Get hold of the div created by the display call when the Comm\n",
3729         "    // socket was opened in Python.\n",
3730         "    var element = document.getElementById(id);\n",
3731         "    var ws_proxy = comm_websocket_adapter(comm);\n",
3732         "\n",
3733         "    function ondownload(figure, _format) {\n",
3734         "        window.open(figure.canvas.toDataURL());\n",
3735         "    }\n",
3736         "\n",
3737         "    var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n",
3738         "\n",
3739         "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
3740         "    // web socket which is closed, not our websocket->open comm proxy.\n",
3741         "    ws_proxy.onopen();\n",
3742         "\n",
3743         "    fig.parent_element = element;\n",
3744         "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
3745         "    if (!fig.cell_info) {\n",
3746         "        console.error('Failed to find cell for figure', id, fig);\n",
3747         "        return;\n",
3748         "    }\n",
3749         "    fig.cell_info[0].output_area.element.on(\n",
3750         "        'cleared',\n",
3751         "        { fig: fig },\n",
3752         "        fig._remove_fig_handler\n",
3753         "    );\n",
3754         "};\n",
3755         "\n",
3756         "mpl.figure.prototype.handle_close = function (fig, msg) {\n",
3757         "    var width = fig.canvas.width / fig.ratio;\n",
3758         "    fig.cell_info[0].output_area.element.off(\n",
3759         "        'cleared',\n",
3760         "        fig._remove_fig_handler\n",
3761         "    );\n",
3762         "    fig.resizeObserverInstance.unobserve(fig.canvas_div);\n",
3763         "\n",
3764         "    // Update the output cell to use the data from the current canvas.\n",
3765         "    fig.push_to_output();\n",
3766         "    var dataURL = fig.canvas.toDataURL();\n",
3767         "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
3768         "    // the notebook keyboard shortcuts fail.\n",
3769         "    IPython.keyboard_manager.enable();\n",
3770         "    fig.parent_element.innerHTML =\n",
3771         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
3772         "    fig.close_ws(fig, msg);\n",
3773         "};\n",
3774         "\n",
3775         "mpl.figure.prototype.close_ws = function (fig, msg) {\n",
3776         "    fig.send_message('closing', msg);\n",
3777         "    // fig.ws.close()\n",
3778         "};\n",
3779         "\n",
3780         "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n",
3781         "    // Turn the data on the canvas into data in the output cell.\n",
3782         "    var width = this.canvas.width / this.ratio;\n",
3783         "    var dataURL = this.canvas.toDataURL();\n",
3784         "    this.cell_info[1]['text/html'] =\n",
3785         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
3786         "};\n",
3787         "\n",
3788         "mpl.figure.prototype.updated_canvas_event = function () {\n",
3789         "    // Tell IPython that the notebook contents must change.\n",
3790         "    IPython.notebook.set_dirty(true);\n",
3791         "    this.send_message('ack', {});\n",
3792         "    var fig = this;\n",
3793         "    // Wait a second, then push the new image to the DOM so\n",
3794         "    // that it is saved nicely (might be nice to debounce this).\n",
3795         "    setTimeout(function () {\n",
3796         "        fig.push_to_output();\n",
3797         "    }, 1000);\n",
3798         "};\n",
3799         "\n",
3800         "mpl.figure.prototype._init_toolbar = function () {\n",
3801         "    var fig = this;\n",
3802         "\n",
3803         "    var toolbar = document.createElement('div');\n",
3804         "    toolbar.classList = 'btn-toolbar';\n",
3805         "    this.root.appendChild(toolbar);\n",
3806         "\n",
3807         "    function on_click_closure(name) {\n",
3808         "        return function (_event) {\n",
3809         "            return fig.toolbar_button_onclick(name);\n",
3810         "        };\n",
3811         "    }\n",
3812         "\n",
3813         "    function on_mouseover_closure(tooltip) {\n",
3814         "        return function (event) {\n",
3815         "            if (!event.currentTarget.disabled) {\n",
3816         "                return fig.toolbar_button_onmouseover(tooltip);\n",
3817         "            }\n",
3818         "        };\n",
3819         "    }\n",
3820         "\n",
3821         "    fig.buttons = {};\n",
3822         "    var buttonGroup = document.createElement('div');\n",
3823         "    buttonGroup.classList = 'btn-group';\n",
3824         "    var button;\n",
3825         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
3826         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
3827         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
3828         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
3829         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
3830         "\n",
3831         "        if (!name) {\n",
3832         "            /* Instead of a spacer, we start a new button group. */\n",
3833         "            if (buttonGroup.hasChildNodes()) {\n",
3834         "                toolbar.appendChild(buttonGroup);\n",
3835         "            }\n",
3836         "            buttonGroup = document.createElement('div');\n",
3837         "            buttonGroup.classList = 'btn-group';\n",
3838         "            continue;\n",
3839         "        }\n",
3840         "\n",
3841         "        button = fig.buttons[name] = document.createElement('button');\n",
3842         "        button.classList = 'btn btn-default';\n",
3843         "        button.href = '#';\n",
3844         "        button.title = name;\n",
3845         "        button.innerHTML = '<i class=\"fa ' + image + ' fa-lg\"></i>';\n",
3846         "        button.addEventListener('click', on_click_closure(method_name));\n",
3847         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
3848         "        buttonGroup.appendChild(button);\n",
3849         "    }\n",
3850         "\n",
3851         "    if (buttonGroup.hasChildNodes()) {\n",
3852         "        toolbar.appendChild(buttonGroup);\n",
3853         "    }\n",
3854         "\n",
3855         "    // Add the status bar.\n",
3856         "    var status_bar = document.createElement('span');\n",
3857         "    status_bar.classList = 'mpl-message pull-right';\n",
3858         "    toolbar.appendChild(status_bar);\n",
3859         "    this.message = status_bar;\n",
3860         "\n",
3861         "    // Add the close button to the window.\n",
3862         "    var buttongrp = document.createElement('div');\n",
3863         "    buttongrp.classList = 'btn-group inline pull-right';\n",
3864         "    button = document.createElement('button');\n",
3865         "    button.classList = 'btn btn-mini btn-primary';\n",
3866         "    button.href = '#';\n",
3867         "    button.title = 'Stop Interaction';\n",
3868         "    button.innerHTML = '<i class=\"fa fa-power-off icon-remove icon-large\"></i>';\n",
3869         "    button.addEventListener('click', function (_evt) {\n",
3870         "        fig.handle_close(fig, {});\n",
3871         "    });\n",
3872         "    button.addEventListener(\n",
3873         "        'mouseover',\n",
3874         "        on_mouseover_closure('Stop Interaction')\n",
3875         "    );\n",
3876         "    buttongrp.appendChild(button);\n",
3877         "    var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n",
3878         "    titlebar.insertBefore(buttongrp, titlebar.firstChild);\n",
3879         "};\n",
3880         "\n",
3881         "mpl.figure.prototype._remove_fig_handler = function (event) {\n",
3882         "    var fig = event.data.fig;\n",
3883         "    if (event.target !== this) {\n",
3884         "        // Ignore bubbled events from children.\n",
3885         "        return;\n",
3886         "    }\n",
3887         "    fig.close_ws(fig, {});\n",
3888         "};\n",
3889         "\n",
3890         "mpl.figure.prototype._root_extra_style = function (el) {\n",
3891         "    el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n",
3892         "};\n",
3893         "\n",
3894         "mpl.figure.prototype._canvas_extra_style = function (el) {\n",
3895         "    // this is important to make the div 'focusable\n",
3896         "    el.setAttribute('tabindex', 0);\n",
3897         "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
3898         "    // off when our div gets focus\n",
3899         "\n",
3900         "    // location in version 3\n",
3901         "    if (IPython.notebook.keyboard_manager) {\n",
3902         "        IPython.notebook.keyboard_manager.register_events(el);\n",
3903         "    } else {\n",
3904         "        // location in version 2\n",
3905         "        IPython.keyboard_manager.register_events(el);\n",
3906         "    }\n",
3907         "};\n",
3908         "\n",
3909         "mpl.figure.prototype._key_event_extra = function (event, _name) {\n",
3910         "    var manager = IPython.notebook.keyboard_manager;\n",
3911         "    if (!manager) {\n",
3912         "        manager = IPython.keyboard_manager;\n",
3913         "    }\n",
3914         "\n",
3915         "    // Check for shift+enter\n",
3916         "    if (event.shiftKey && event.which === 13) {\n",
3917         "        this.canvas_div.blur();\n",
3918         "        // select the cell after this one\n",
3919         "        var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
3920         "        IPython.notebook.select(index + 1);\n",
3921         "    }\n",
3922         "};\n",
3923         "\n",
3924         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
3925         "    fig.ondownload(fig, null);\n",
3926         "};\n",
3927         "\n",
3928         "mpl.find_output_cell = function (html_output) {\n",
3929         "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
3930         "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
3931         "    // IPython event is triggered only after the cells have been serialised, which for\n",
3932         "    // our purposes (turning an active figure into a static one), is too late.\n",
3933         "    var cells = IPython.notebook.get_cells();\n",
3934         "    var ncells = cells.length;\n",
3935         "    for (var i = 0; i < ncells; i++) {\n",
3936         "        var cell = cells[i];\n",
3937         "        if (cell.cell_type === 'code') {\n",
3938         "            for (var j = 0; j < cell.output_area.outputs.length; j++) {\n",
3939         "                var data = cell.output_area.outputs[j];\n",
3940         "                if (data.data) {\n",
3941         "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
3942         "                    data = data.data;\n",
3943         "                }\n",
3944         "                if (data['text/html'] === html_output) {\n",
3945         "                    return [cell, data, j];\n",
3946         "                }\n",
3947         "            }\n",
3948         "        }\n",
3949         "    }\n",
3950         "};\n",
3951         "\n",
3952         "// Register the function which deals with the matplotlib target/channel.\n",
3953         "// The kernel may be null if the page has been refreshed.\n",
3954         "if (IPython.notebook.kernel !== null) {\n",
3955         "    IPython.notebook.kernel.comm_manager.register_target(\n",
3956         "        'matplotlib',\n",
3957         "        mpl.mpl_figure_comm\n",
3958         "    );\n",
3959         "}\n"
3960        ],
3961        "text/plain": [
3962         "<IPython.core.display.Javascript object>"
3963        ]
3964       },
3965       "metadata": {},
3966       "output_type": "display_data"
3967      },
3968      {
3969       "data": {
3970        "text/html": [
3971         "<div id='fdd106db-abc6-48fd-9057-2a7436dda349'></div>"
3972        ],
3973        "text/plain": [
3974         "<IPython.core.display.HTML object>"
3975        ]
3976       },
3977       "metadata": {},
3978       "output_type": "display_data"
3979      }
3980     ],
3981     "source": [
3982      "from sklearn.datasets import make_classification, make_blobs\n",
3983      "from matplotlib.colors import ListedColormap\n",
3984      "from sklearn.datasets import load_breast_cancer\n",
3985      "from adspy_shared_utilities import load_crime_dataset\n",
3986      "\n",
3987      "cmap_bold = ListedColormap(['#FFFF00', '#00FF00', '#0000FF','#000000'])\n",
3988      "\n",
3989      "\n",
3990      "# synthetic dataset for simple regression\n",
3991      "from sklearn.datasets import make_regression\n",
3992      "plt.figure()\n",
3993      "plt.title('Sample regression problem with one input variable')\n",
3994      "X_R1, y_R1 = make_regression(n_samples = 100, n_features=1,\n",
3995      "                            n_informative=1, bias = 150.0,\n",
3996      "                            noise = 30, random_state=0)\n",
3997      "plt.scatter(X_R1, y_R1, marker= 'o', s=50)\n",
3998      "plt.show()\n",
3999      "\n",
4000      "\n",
4001      "# synthetic dataset for more complex regression\n",
4002      "from sklearn.datasets import make_friedman1\n",
4003      "plt.figure()\n",
4004      "plt.title('Complex regression problem with one input variable')\n",
4005      "X_F1, y_F1 = make_friedman1(n_samples = 100,\n",
4006      "                           n_features = 7, random_state=0)\n",
4007      "\n",
4008      "plt.scatter(X_F1[:, 2], y_F1, marker= 'o', s=50)\n",
4009      "plt.show()\n",
4010      "\n",
4011      "# synthetic dataset for classification (binary) \n",
4012      "plt.figure()\n",
4013      "plt.title('Sample binary classification problem with two informative features')\n",
4014      "X_C2, y_C2 = make_classification(n_samples = 100, n_features=2,\n",
4015      "                                n_redundant=0, n_informative=2,\n",
4016      "                                n_clusters_per_class=1, flip_y = 0.1,\n",
4017      "                                class_sep = 0.5, random_state=0)\n",
4018      "plt.scatter(X_C2[:, 0], X_C2[:, 1], c=y_C2,\n",
4019      "           marker= 'o', s=50, cmap=cmap_bold)\n",
4020      "plt.show()\n",
4021      "\n",
4022      "\n",
4023      "# more difficult synthetic dataset for classification (binary) \n",
4024      "# with classes that are not linearly separable\n",
4025      "X_D2, y_D2 = make_blobs(n_samples = 100, n_features = 2, centers = 8,\n",
4026      "                       cluster_std = 1.3, random_state = 4)\n",
4027      "y_D2 = y_D2 % 2\n",
4028      "plt.figure()\n",
4029      "plt.title('Sample binary classification problem with non-linearly separable classes')\n",
4030      "plt.scatter(X_D2[:,0], X_D2[:,1], c=y_D2,\n",
4031      "           marker= 'o', s=50, cmap=cmap_bold)\n",
4032      "plt.show()\n",
4033      "\n",
4034      "\n",
4035      "# Breast cancer dataset for classification\n",
4036      "cancer = load_breast_cancer()\n",
4037      "(X_cancer, y_cancer) = load_breast_cancer(return_X_y = True)\n",
4038      "\n",
4039      "\n",
4040      "# Communities and Crime dataset\n",
4041      "#(X_crime, y_crime) = load_crime_dataset()"
4042     ]
4043    },
4044    {
4045     "cell_type": "markdown",
4046     "metadata": {},
4047     "source": [
4048      "## K-Nearest Neighbors"
4049     ]
4050    },
4051    {
4052     "cell_type": "markdown",
4053     "metadata": {},
4054     "source": [
4055      "### Classification"
4056     ]
4057    },
4058    {
4059     "cell_type": "code",
4060     "execution_count": 3,
4061     "metadata": {
4062      "scrolled": false
4063     },
4064     "outputs": [
4065      {
4066       "data": {
4067        "application/javascript": [
4068         "/* Put everything inside the global mpl namespace */\n",
4069         "/* global mpl */\n",
4070         "window.mpl = {};\n",
4071         "\n",
4072         "mpl.get_websocket_type = function () {\n",
4073         "    if (typeof WebSocket !== 'undefined') {\n",
4074         "        return WebSocket;\n",
4075         "    } else if (typeof MozWebSocket !== 'undefined') {\n",
4076         "        return MozWebSocket;\n",
4077         "    } else {\n",
4078         "        alert(\n",
4079         "            'Your browser does not have WebSocket support. ' +\n",
4080         "                'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
4081         "                'Firefox 4 and 5 are also supported but you ' +\n",
4082         "                'have to enable WebSockets in about:config.'\n",
4083         "        );\n",
4084         "    }\n",
4085         "};\n",
4086         "\n",
4087         "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n",
4088         "    this.id = figure_id;\n",
4089         "\n",
4090         "    this.ws = websocket;\n",
4091         "\n",
4092         "    this.supports_binary = this.ws.binaryType !== undefined;\n",
4093         "\n",
4094         "    if (!this.supports_binary) {\n",
4095         "        var warnings = document.getElementById('mpl-warnings');\n",
4096         "        if (warnings) {\n",
4097         "            warnings.style.display = 'block';\n",
4098         "            warnings.textContent =\n",
4099         "                'This browser does not support binary websocket messages. ' +\n",
4100         "                'Performance may be slow.';\n",
4101         "        }\n",
4102         "    }\n",
4103         "\n",
4104         "    this.imageObj = new Image();\n",
4105         "\n",
4106         "    this.context = undefined;\n",
4107         "    this.message = undefined;\n",
4108         "    this.canvas = undefined;\n",
4109         "    this.rubberband_canvas = undefined;\n",
4110         "    this.rubberband_context = undefined;\n",
4111         "    this.format_dropdown = undefined;\n",
4112         "\n",
4113         "    this.image_mode = 'full';\n",
4114         "\n",
4115         "    this.root = document.createElement('div');\n",
4116         "    this.root.setAttribute('style', 'display: inline-block');\n",
4117         "    this._root_extra_style(this.root);\n",
4118         "\n",
4119         "    parent_element.appendChild(this.root);\n",
4120         "\n",
4121         "    this._init_header(this);\n",
4122         "    this._init_canvas(this);\n",
4123         "    this._init_toolbar(this);\n",
4124         "\n",
4125         "    var fig = this;\n",
4126         "\n",
4127         "    this.waiting = false;\n",
4128         "\n",
4129         "    this.ws.onopen = function () {\n",
4130         "        fig.send_message('supports_binary', { value: fig.supports_binary });\n",
4131         "        fig.send_message('send_image_mode', {});\n",
4132         "        if (fig.ratio !== 1) {\n",
4133         "            fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n",
4134         "        }\n",
4135         "        fig.send_message('refresh', {});\n",
4136         "    };\n",
4137         "\n",
4138         "    this.imageObj.onload = function () {\n",
4139         "        if (fig.image_mode === 'full') {\n",
4140         "            // Full images could contain transparency (where diff images\n",
4141         "            // almost always do), so we need to clear the canvas so that\n",
4142         "            // there is no ghosting.\n",
4143         "            fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
4144         "        }\n",
4145         "        fig.context.drawImage(fig.imageObj, 0, 0);\n",
4146         "    };\n",
4147         "\n",
4148         "    this.imageObj.onunload = function () {\n",
4149         "        fig.ws.close();\n",
4150         "    };\n",
4151         "\n",
4152         "    this.ws.onmessage = this._make_on_message_function(this);\n",
4153         "\n",
4154         "    this.ondownload = ondownload;\n",
4155         "};\n",
4156         "\n",
4157         "mpl.figure.prototype._init_header = function () {\n",
4158         "    var titlebar = document.createElement('div');\n",
4159         "    titlebar.classList =\n",
4160         "        'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n",
4161         "    var titletext = document.createElement('div');\n",
4162         "    titletext.classList = 'ui-dialog-title';\n",
4163         "    titletext.setAttribute(\n",
4164         "        'style',\n",
4165         "        'width: 100%; text-align: center; padding: 3px;'\n",
4166         "    );\n",
4167         "    titlebar.appendChild(titletext);\n",
4168         "    this.root.appendChild(titlebar);\n",
4169         "    this.header = titletext;\n",
4170         "};\n",
4171         "\n",
4172         "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n",
4173         "\n",
4174         "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n",
4175         "\n",
4176         "mpl.figure.prototype._init_canvas = function () {\n",
4177         "    var fig = this;\n",
4178         "\n",
4179         "    var canvas_div = (this.canvas_div = document.createElement('div'));\n",
4180         "    canvas_div.setAttribute(\n",
4181         "        'style',\n",
4182         "        'border: 1px solid #ddd;' +\n",
4183         "            'box-sizing: content-box;' +\n",
4184         "            'clear: both;' +\n",
4185         "            'min-height: 1px;' +\n",
4186         "            'min-width: 1px;' +\n",
4187         "            'outline: 0;' +\n",
4188         "            'overflow: hidden;' +\n",
4189         "            'position: relative;' +\n",
4190         "            'resize: both;'\n",
4191         "    );\n",
4192         "\n",
4193         "    function on_keyboard_event_closure(name) {\n",
4194         "        return function (event) {\n",
4195         "            return fig.key_event(event, name);\n",
4196         "        };\n",
4197         "    }\n",
4198         "\n",
4199         "    canvas_div.addEventListener(\n",
4200         "        'keydown',\n",
4201         "        on_keyboard_event_closure('key_press')\n",
4202         "    );\n",
4203         "    canvas_div.addEventListener(\n",
4204         "        'keyup',\n",
4205         "        on_keyboard_event_closure('key_release')\n",
4206         "    );\n",
4207         "\n",
4208         "    this._canvas_extra_style(canvas_div);\n",
4209         "    this.root.appendChild(canvas_div);\n",
4210         "\n",
4211         "    var canvas = (this.canvas = document.createElement('canvas'));\n",
4212         "    canvas.classList.add('mpl-canvas');\n",
4213         "    canvas.setAttribute('style', 'box-sizing: content-box;');\n",
4214         "\n",
4215         "    this.context = canvas.getContext('2d');\n",
4216         "\n",
4217         "    var backingStore =\n",
4218         "        this.context.backingStorePixelRatio ||\n",
4219         "        this.context.webkitBackingStorePixelRatio ||\n",
4220         "        this.context.mozBackingStorePixelRatio ||\n",
4221         "        this.context.msBackingStorePixelRatio ||\n",
4222         "        this.context.oBackingStorePixelRatio ||\n",
4223         "        this.context.backingStorePixelRatio ||\n",
4224         "        1;\n",
4225         "\n",
4226         "    this.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
4227         "\n",
4228         "    var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n",
4229         "        'canvas'\n",
4230         "    ));\n",
4231         "    rubberband_canvas.setAttribute(\n",
4232         "        'style',\n",
4233         "        'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n",
4234         "    );\n",
4235         "\n",
4236         "    // Apply a ponyfill if ResizeObserver is not implemented by browser.\n",
4237         "    if (this.ResizeObserver === undefined) {\n",
4238         "        if (window.ResizeObserver !== undefined) {\n",
4239         "            this.ResizeObserver = window.ResizeObserver;\n",
4240         "        } else {\n",
4241         "            var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n",
4242         "            this.ResizeObserver = obs.ResizeObserver;\n",
4243         "        }\n",
4244         "    }\n",
4245         "\n",
4246         "    this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n",
4247         "        var nentries = entries.length;\n",
4248         "        for (var i = 0; i < nentries; i++) {\n",
4249         "            var entry = entries[i];\n",
4250         "            var width, height;\n",
4251         "            if (entry.contentBoxSize) {\n",
4252         "                if (entry.contentBoxSize instanceof Array) {\n",
4253         "                    // Chrome 84 implements new version of spec.\n",
4254         "                    width = entry.contentBoxSize[0].inlineSize;\n",
4255         "                    height = entry.contentBoxSize[0].blockSize;\n",
4256         "                } else {\n",
4257         "                    // Firefox implements old version of spec.\n",
4258         "                    width = entry.contentBoxSize.inlineSize;\n",
4259         "                    height = entry.contentBoxSize.blockSize;\n",
4260         "                }\n",
4261         "            } else {\n",
4262         "                // Chrome <84 implements even older version of spec.\n",
4263         "                width = entry.contentRect.width;\n",
4264         "                height = entry.contentRect.height;\n",
4265         "            }\n",
4266         "\n",
4267         "            // Keep the size of the canvas and rubber band canvas in sync with\n",
4268         "            // the canvas container.\n",
4269         "            if (entry.devicePixelContentBoxSize) {\n",
4270         "                // Chrome 84 implements new version of spec.\n",
4271         "                canvas.setAttribute(\n",
4272         "                    'width',\n",
4273         "                    entry.devicePixelContentBoxSize[0].inlineSize\n",
4274         "                );\n",
4275         "                canvas.setAttribute(\n",
4276         "                    'height',\n",
4277         "                    entry.devicePixelContentBoxSize[0].blockSize\n",
4278         "                );\n",
4279         "            } else {\n",
4280         "                canvas.setAttribute('width', width * fig.ratio);\n",
4281         "                canvas.setAttribute('height', height * fig.ratio);\n",
4282         "            }\n",
4283         "            canvas.setAttribute(\n",
4284         "                'style',\n",
4285         "                'width: ' + width + 'px; height: ' + height + 'px;'\n",
4286         "            );\n",
4287         "\n",
4288         "            rubberband_canvas.setAttribute('width', width);\n",
4289         "            rubberband_canvas.setAttribute('height', height);\n",
4290         "\n",
4291         "            // And update the size in Python. We ignore the initial 0/0 size\n",
4292         "            // that occurs as the element is placed into the DOM, which should\n",
4293         "            // otherwise not happen due to the minimum size styling.\n",
4294         "            if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n",
4295         "                fig.request_resize(width, height);\n",
4296         "            }\n",
4297         "        }\n",
4298         "    });\n",
4299         "    this.resizeObserverInstance.observe(canvas_div);\n",
4300         "\n",
4301         "    function on_mouse_event_closure(name) {\n",
4302         "        return function (event) {\n",
4303         "            return fig.mouse_event(event, name);\n",
4304         "        };\n",
4305         "    }\n",
4306         "\n",
4307         "    rubberband_canvas.addEventListener(\n",
4308         "        'mousedown',\n",
4309         "        on_mouse_event_closure('button_press')\n",
4310         "    );\n",
4311         "    rubberband_canvas.addEventListener(\n",
4312         "        'mouseup',\n",
4313         "        on_mouse_event_closure('button_release')\n",
4314         "    );\n",
4315         "    // Throttle sequential mouse events to 1 every 20ms.\n",
4316         "    rubberband_canvas.addEventListener(\n",
4317         "        'mousemove',\n",
4318         "        on_mouse_event_closure('motion_notify')\n",
4319         "    );\n",
4320         "\n",
4321         "    rubberband_canvas.addEventListener(\n",
4322         "        'mouseenter',\n",
4323         "        on_mouse_event_closure('figure_enter')\n",
4324         "    );\n",
4325         "    rubberband_canvas.addEventListener(\n",
4326         "        'mouseleave',\n",
4327         "        on_mouse_event_closure('figure_leave')\n",
4328         "    );\n",
4329         "\n",
4330         "    canvas_div.addEventListener('wheel', function (event) {\n",
4331         "        if (event.deltaY < 0) {\n",
4332         "            event.step = 1;\n",
4333         "        } else {\n",
4334         "            event.step = -1;\n",
4335         "        }\n",
4336         "        on_mouse_event_closure('scroll')(event);\n",
4337         "    });\n",
4338         "\n",
4339         "    canvas_div.appendChild(canvas);\n",
4340         "    canvas_div.appendChild(rubberband_canvas);\n",
4341         "\n",
4342         "    this.rubberband_context = rubberband_canvas.getContext('2d');\n",
4343         "    this.rubberband_context.strokeStyle = '#000000';\n",
4344         "\n",
4345         "    this._resize_canvas = function (width, height, forward) {\n",
4346         "        if (forward) {\n",
4347         "            canvas_div.style.width = width + 'px';\n",
4348         "            canvas_div.style.height = height + 'px';\n",
4349         "        }\n",
4350         "    };\n",
4351         "\n",
4352         "    // Disable right mouse context menu.\n",
4353         "    this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n",
4354         "        event.preventDefault();\n",
4355         "        return false;\n",
4356         "    });\n",
4357         "\n",
4358         "    function set_focus() {\n",
4359         "        canvas.focus();\n",
4360         "        canvas_div.focus();\n",
4361         "    }\n",
4362         "\n",
4363         "    window.setTimeout(set_focus, 100);\n",
4364         "};\n",
4365         "\n",
4366         "mpl.figure.prototype._init_toolbar = function () {\n",
4367         "    var fig = this;\n",
4368         "\n",
4369         "    var toolbar = document.createElement('div');\n",
4370         "    toolbar.classList = 'mpl-toolbar';\n",
4371         "    this.root.appendChild(toolbar);\n",
4372         "\n",
4373         "    function on_click_closure(name) {\n",
4374         "        return function (_event) {\n",
4375         "            return fig.toolbar_button_onclick(name);\n",
4376         "        };\n",
4377         "    }\n",
4378         "\n",
4379         "    function on_mouseover_closure(tooltip) {\n",
4380         "        return function (event) {\n",
4381         "            if (!event.currentTarget.disabled) {\n",
4382         "                return fig.toolbar_button_onmouseover(tooltip);\n",
4383         "            }\n",
4384         "        };\n",
4385         "    }\n",
4386         "\n",
4387         "    fig.buttons = {};\n",
4388         "    var buttonGroup = document.createElement('div');\n",
4389         "    buttonGroup.classList = 'mpl-button-group';\n",
4390         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
4391         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
4392         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
4393         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
4394         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
4395         "\n",
4396         "        if (!name) {\n",
4397         "            /* Instead of a spacer, we start a new button group. */\n",
4398         "            if (buttonGroup.hasChildNodes()) {\n",
4399         "                toolbar.appendChild(buttonGroup);\n",
4400         "            }\n",
4401         "            buttonGroup = document.createElement('div');\n",
4402         "            buttonGroup.classList = 'mpl-button-group';\n",
4403         "            continue;\n",
4404         "        }\n",
4405         "\n",
4406         "        var button = (fig.buttons[name] = document.createElement('button'));\n",
4407         "        button.classList = 'mpl-widget';\n",
4408         "        button.setAttribute('role', 'button');\n",
4409         "        button.setAttribute('aria-disabled', 'false');\n",
4410         "        button.addEventListener('click', on_click_closure(method_name));\n",
4411         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
4412         "\n",
4413         "        var icon_img = document.createElement('img');\n",
4414         "        icon_img.src = '_images/' + image + '.png';\n",
4415         "        icon_img.srcset = '_images/' + image + '_large.png 2x';\n",
4416         "        icon_img.alt = tooltip;\n",
4417         "        button.appendChild(icon_img);\n",
4418         "\n",
4419         "        buttonGroup.appendChild(button);\n",
4420         "    }\n",
4421         "\n",
4422         "    if (buttonGroup.hasChildNodes()) {\n",
4423         "        toolbar.appendChild(buttonGroup);\n",
4424         "    }\n",
4425         "\n",
4426         "    var fmt_picker = document.createElement('select');\n",
4427         "    fmt_picker.classList = 'mpl-widget';\n",
4428         "    toolbar.appendChild(fmt_picker);\n",
4429         "    this.format_dropdown = fmt_picker;\n",
4430         "\n",
4431         "    for (var ind in mpl.extensions) {\n",
4432         "        var fmt = mpl.extensions[ind];\n",
4433         "        var option = document.createElement('option');\n",
4434         "        option.selected = fmt === mpl.default_extension;\n",
4435         "        option.innerHTML = fmt;\n",
4436         "        fmt_picker.appendChild(option);\n",
4437         "    }\n",
4438         "\n",
4439         "    var status_bar = document.createElement('span');\n",
4440         "    status_bar.classList = 'mpl-message';\n",
4441         "    toolbar.appendChild(status_bar);\n",
4442         "    this.message = status_bar;\n",
4443         "};\n",
4444         "\n",
4445         "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n",
4446         "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
4447         "    // which will in turn request a refresh of the image.\n",
4448         "    this.send_message('resize', { width: x_pixels, height: y_pixels });\n",
4449         "};\n",
4450         "\n",
4451         "mpl.figure.prototype.send_message = function (type, properties) {\n",
4452         "    properties['type'] = type;\n",
4453         "    properties['figure_id'] = this.id;\n",
4454         "    this.ws.send(JSON.stringify(properties));\n",
4455         "};\n",
4456         "\n",
4457         "mpl.figure.prototype.send_draw_message = function () {\n",
4458         "    if (!this.waiting) {\n",
4459         "        this.waiting = true;\n",
4460         "        this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n",
4461         "    }\n",
4462         "};\n",
4463         "\n",
4464         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
4465         "    var format_dropdown = fig.format_dropdown;\n",
4466         "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
4467         "    fig.ondownload(fig, format);\n",
4468         "};\n",
4469         "\n",
4470         "mpl.figure.prototype.handle_resize = function (fig, msg) {\n",
4471         "    var size = msg['size'];\n",
4472         "    if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n",
4473         "        fig._resize_canvas(size[0], size[1], msg['forward']);\n",
4474         "        fig.send_message('refresh', {});\n",
4475         "    }\n",
4476         "};\n",
4477         "\n",
4478         "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n",
4479         "    var x0 = msg['x0'] / fig.ratio;\n",
4480         "    var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n",
4481         "    var x1 = msg['x1'] / fig.ratio;\n",
4482         "    var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n",
4483         "    x0 = Math.floor(x0) + 0.5;\n",
4484         "    y0 = Math.floor(y0) + 0.5;\n",
4485         "    x1 = Math.floor(x1) + 0.5;\n",
4486         "    y1 = Math.floor(y1) + 0.5;\n",
4487         "    var min_x = Math.min(x0, x1);\n",
4488         "    var min_y = Math.min(y0, y1);\n",
4489         "    var width = Math.abs(x1 - x0);\n",
4490         "    var height = Math.abs(y1 - y0);\n",
4491         "\n",
4492         "    fig.rubberband_context.clearRect(\n",
4493         "        0,\n",
4494         "        0,\n",
4495         "        fig.canvas.width / fig.ratio,\n",
4496         "        fig.canvas.height / fig.ratio\n",
4497         "    );\n",
4498         "\n",
4499         "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
4500         "};\n",
4501         "\n",
4502         "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n",
4503         "    // Updates the figure title.\n",
4504         "    fig.header.textContent = msg['label'];\n",
4505         "};\n",
4506         "\n",
4507         "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n",
4508         "    var cursor = msg['cursor'];\n",
4509         "    switch (cursor) {\n",
4510         "        case 0:\n",
4511         "            cursor = 'pointer';\n",
4512         "            break;\n",
4513         "        case 1:\n",
4514         "            cursor = 'default';\n",
4515         "            break;\n",
4516         "        case 2:\n",
4517         "            cursor = 'crosshair';\n",
4518         "            break;\n",
4519         "        case 3:\n",
4520         "            cursor = 'move';\n",
4521         "            break;\n",
4522         "    }\n",
4523         "    fig.rubberband_canvas.style.cursor = cursor;\n",
4524         "};\n",
4525         "\n",
4526         "mpl.figure.prototype.handle_message = function (fig, msg) {\n",
4527         "    fig.message.textContent = msg['message'];\n",
4528         "};\n",
4529         "\n",
4530         "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n",
4531         "    // Request the server to send over a new figure.\n",
4532         "    fig.send_draw_message();\n",
4533         "};\n",
4534         "\n",
4535         "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n",
4536         "    fig.image_mode = msg['mode'];\n",
4537         "};\n",
4538         "\n",
4539         "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n",
4540         "    for (var key in msg) {\n",
4541         "        if (!(key in fig.buttons)) {\n",
4542         "            continue;\n",
4543         "        }\n",
4544         "        fig.buttons[key].disabled = !msg[key];\n",
4545         "        fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n",
4546         "    }\n",
4547         "};\n",
4548         "\n",
4549         "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n",
4550         "    if (msg['mode'] === 'PAN') {\n",
4551         "        fig.buttons['Pan'].classList.add('active');\n",
4552         "        fig.buttons['Zoom'].classList.remove('active');\n",
4553         "    } else if (msg['mode'] === 'ZOOM') {\n",
4554         "        fig.buttons['Pan'].classList.remove('active');\n",
4555         "        fig.buttons['Zoom'].classList.add('active');\n",
4556         "    } else {\n",
4557         "        fig.buttons['Pan'].classList.remove('active');\n",
4558         "        fig.buttons['Zoom'].classList.remove('active');\n",
4559         "    }\n",
4560         "};\n",
4561         "\n",
4562         "mpl.figure.prototype.updated_canvas_event = function () {\n",
4563         "    // Called whenever the canvas gets updated.\n",
4564         "    this.send_message('ack', {});\n",
4565         "};\n",
4566         "\n",
4567         "// A function to construct a web socket function for onmessage handling.\n",
4568         "// Called in the figure constructor.\n",
4569         "mpl.figure.prototype._make_on_message_function = function (fig) {\n",
4570         "    return function socket_on_message(evt) {\n",
4571         "        if (evt.data instanceof Blob) {\n",
4572         "            /* FIXME: We get \"Resource interpreted as Image but\n",
4573         "             * transferred with MIME type text/plain:\" errors on\n",
4574         "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
4575         "             * to be part of the websocket stream */\n",
4576         "            evt.data.type = 'image/png';\n",
4577         "\n",
4578         "            /* Free the memory for the previous frames */\n",
4579         "            if (fig.imageObj.src) {\n",
4580         "                (window.URL || window.webkitURL).revokeObjectURL(\n",
4581         "                    fig.imageObj.src\n",
4582         "                );\n",
4583         "            }\n",
4584         "\n",
4585         "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
4586         "                evt.data\n",
4587         "            );\n",
4588         "            fig.updated_canvas_event();\n",
4589         "            fig.waiting = false;\n",
4590         "            return;\n",
4591         "        } else if (\n",
4592         "            typeof evt.data === 'string' &&\n",
4593         "            evt.data.slice(0, 21) === 'data:image/png;base64'\n",
4594         "        ) {\n",
4595         "            fig.imageObj.src = evt.data;\n",
4596         "            fig.updated_canvas_event();\n",
4597         "            fig.waiting = false;\n",
4598         "            return;\n",
4599         "        }\n",
4600         "\n",
4601         "        var msg = JSON.parse(evt.data);\n",
4602         "        var msg_type = msg['type'];\n",
4603         "\n",
4604         "        // Call the  \"handle_{type}\" callback, which takes\n",
4605         "        // the figure and JSON message as its only arguments.\n",
4606         "        try {\n",
4607         "            var callback = fig['handle_' + msg_type];\n",
4608         "        } catch (e) {\n",
4609         "            console.log(\n",
4610         "                \"No handler for the '\" + msg_type + \"' message type: \",\n",
4611         "                msg\n",
4612         "            );\n",
4613         "            return;\n",
4614         "        }\n",
4615         "\n",
4616         "        if (callback) {\n",
4617         "            try {\n",
4618         "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
4619         "                callback(fig, msg);\n",
4620         "            } catch (e) {\n",
4621         "                console.log(\n",
4622         "                    \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n",
4623         "                    e,\n",
4624         "                    e.stack,\n",
4625         "                    msg\n",
4626         "                );\n",
4627         "            }\n",
4628         "        }\n",
4629         "    };\n",
4630         "};\n",
4631         "\n",
4632         "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
4633         "mpl.findpos = function (e) {\n",
4634         "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
4635         "    var targ;\n",
4636         "    if (!e) {\n",
4637         "        e = window.event;\n",
4638         "    }\n",
4639         "    if (e.target) {\n",
4640         "        targ = e.target;\n",
4641         "    } else if (e.srcElement) {\n",
4642         "        targ = e.srcElement;\n",
4643         "    }\n",
4644         "    if (targ.nodeType === 3) {\n",
4645         "        // defeat Safari bug\n",
4646         "        targ = targ.parentNode;\n",
4647         "    }\n",
4648         "\n",
4649         "    // pageX,Y are the mouse positions relative to the document\n",
4650         "    var boundingRect = targ.getBoundingClientRect();\n",
4651         "    var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n",
4652         "    var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n",
4653         "\n",
4654         "    return { x: x, y: y };\n",
4655         "};\n",
4656         "\n",
4657         "/*\n",
4658         " * return a copy of an object with only non-object keys\n",
4659         " * we need this to avoid circular references\n",
4660         " * http://stackoverflow.com/a/24161582/3208463\n",
4661         " */\n",
4662         "function simpleKeys(original) {\n",
4663         "    return Object.keys(original).reduce(function (obj, key) {\n",
4664         "        if (typeof original[key] !== 'object') {\n",
4665         "            obj[key] = original[key];\n",
4666         "        }\n",
4667         "        return obj;\n",
4668         "    }, {});\n",
4669         "}\n",
4670         "\n",
4671         "mpl.figure.prototype.mouse_event = function (event, name) {\n",
4672         "    var canvas_pos = mpl.findpos(event);\n",
4673         "\n",
4674         "    if (name === 'button_press') {\n",
4675         "        this.canvas.focus();\n",
4676         "        this.canvas_div.focus();\n",
4677         "    }\n",
4678         "\n",
4679         "    var x = canvas_pos.x * this.ratio;\n",
4680         "    var y = canvas_pos.y * this.ratio;\n",
4681         "\n",
4682         "    this.send_message(name, {\n",
4683         "        x: x,\n",
4684         "        y: y,\n",
4685         "        button: event.button,\n",
4686         "        step: event.step,\n",
4687         "        guiEvent: simpleKeys(event),\n",
4688         "    });\n",
4689         "\n",
4690         "    /* This prevents the web browser from automatically changing to\n",
4691         "     * the text insertion cursor when the button is pressed.  We want\n",
4692         "     * to control all of the cursor setting manually through the\n",
4693         "     * 'cursor' event from matplotlib */\n",
4694         "    event.preventDefault();\n",
4695         "    return false;\n",
4696         "};\n",
4697         "\n",
4698         "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n",
4699         "    // Handle any extra behaviour associated with a key event\n",
4700         "};\n",
4701         "\n",
4702         "mpl.figure.prototype.key_event = function (event, name) {\n",
4703         "    // Prevent repeat events\n",
4704         "    if (name === 'key_press') {\n",
4705         "        if (event.which === this._key) {\n",
4706         "            return;\n",
4707         "        } else {\n",
4708         "            this._key = event.which;\n",
4709         "        }\n",
4710         "    }\n",
4711         "    if (name === 'key_release') {\n",
4712         "        this._key = null;\n",
4713         "    }\n",
4714         "\n",
4715         "    var value = '';\n",
4716         "    if (event.ctrlKey && event.which !== 17) {\n",
4717         "        value += 'ctrl+';\n",
4718         "    }\n",
4719         "    if (event.altKey && event.which !== 18) {\n",
4720         "        value += 'alt+';\n",
4721         "    }\n",
4722         "    if (event.shiftKey && event.which !== 16) {\n",
4723         "        value += 'shift+';\n",
4724         "    }\n",
4725         "\n",
4726         "    value += 'k';\n",
4727         "    value += event.which.toString();\n",
4728         "\n",
4729         "    this._key_event_extra(event, name);\n",
4730         "\n",
4731         "    this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n",
4732         "    return false;\n",
4733         "};\n",
4734         "\n",
4735         "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n",
4736         "    if (name === 'download') {\n",
4737         "        this.handle_save(this, null);\n",
4738         "    } else {\n",
4739         "        this.send_message('toolbar_button', { name: name });\n",
4740         "    }\n",
4741         "};\n",
4742         "\n",
4743         "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n",
4744         "    this.message.textContent = tooltip;\n",
4745         "};\n",
4746         "\n",
4747         "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n",
4748         "// prettier-ignore\n",
4749         "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n",
4750         "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
4751         "\n",
4752         "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
4753         "\n",
4754         "mpl.default_extension = \"png\";/* global mpl */\n",
4755         "\n",
4756         "var comm_websocket_adapter = function (comm) {\n",
4757         "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
4758         "    // object with the appropriate methods. Currently this is a non binary\n",
4759         "    // socket, so there is still some room for performance tuning.\n",
4760         "    var ws = {};\n",
4761         "\n",
4762         "    ws.close = function () {\n",
4763         "        comm.close();\n",
4764         "    };\n",
4765         "    ws.send = function (m) {\n",
4766         "        //console.log('sending', m);\n",
4767         "        comm.send(m);\n",
4768         "    };\n",
4769         "    // Register the callback with on_msg.\n",
4770         "    comm.on_msg(function (msg) {\n",
4771         "        //console.log('receiving', msg['content']['data'], msg);\n",
4772         "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
4773         "        ws.onmessage(msg['content']['data']);\n",
4774         "    });\n",
4775         "    return ws;\n",
4776         "};\n",
4777         "\n",
4778         "mpl.mpl_figure_comm = function (comm, msg) {\n",
4779         "    // This is the function which gets called when the mpl process\n",
4780         "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
4781         "\n",
4782         "    var id = msg.content.data.id;\n",
4783         "    // Get hold of the div created by the display call when the Comm\n",
4784         "    // socket was opened in Python.\n",
4785         "    var element = document.getElementById(id);\n",
4786         "    var ws_proxy = comm_websocket_adapter(comm);\n",
4787         "\n",
4788         "    function ondownload(figure, _format) {\n",
4789         "        window.open(figure.canvas.toDataURL());\n",
4790         "    }\n",
4791         "\n",
4792         "    var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n",
4793         "\n",
4794         "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
4795         "    // web socket which is closed, not our websocket->open comm proxy.\n",
4796         "    ws_proxy.onopen();\n",
4797         "\n",
4798         "    fig.parent_element = element;\n",
4799         "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
4800         "    if (!fig.cell_info) {\n",
4801         "        console.error('Failed to find cell for figure', id, fig);\n",
4802         "        return;\n",
4803         "    }\n",
4804         "    fig.cell_info[0].output_area.element.on(\n",
4805         "        'cleared',\n",
4806         "        { fig: fig },\n",
4807         "        fig._remove_fig_handler\n",
4808         "    );\n",
4809         "};\n",
4810         "\n",
4811         "mpl.figure.prototype.handle_close = function (fig, msg) {\n",
4812         "    var width = fig.canvas.width / fig.ratio;\n",
4813         "    fig.cell_info[0].output_area.element.off(\n",
4814         "        'cleared',\n",
4815         "        fig._remove_fig_handler\n",
4816         "    );\n",
4817         "    fig.resizeObserverInstance.unobserve(fig.canvas_div);\n",
4818         "\n",
4819         "    // Update the output cell to use the data from the current canvas.\n",
4820         "    fig.push_to_output();\n",
4821         "    var dataURL = fig.canvas.toDataURL();\n",
4822         "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
4823         "    // the notebook keyboard shortcuts fail.\n",
4824         "    IPython.keyboard_manager.enable();\n",
4825         "    fig.parent_element.innerHTML =\n",
4826         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
4827         "    fig.close_ws(fig, msg);\n",
4828         "};\n",
4829         "\n",
4830         "mpl.figure.prototype.close_ws = function (fig, msg) {\n",
4831         "    fig.send_message('closing', msg);\n",
4832         "    // fig.ws.close()\n",
4833         "};\n",
4834         "\n",
4835         "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n",
4836         "    // Turn the data on the canvas into data in the output cell.\n",
4837         "    var width = this.canvas.width / this.ratio;\n",
4838         "    var dataURL = this.canvas.toDataURL();\n",
4839         "    this.cell_info[1]['text/html'] =\n",
4840         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
4841         "};\n",
4842         "\n",
4843         "mpl.figure.prototype.updated_canvas_event = function () {\n",
4844         "    // Tell IPython that the notebook contents must change.\n",
4845         "    IPython.notebook.set_dirty(true);\n",
4846         "    this.send_message('ack', {});\n",
4847         "    var fig = this;\n",
4848         "    // Wait a second, then push the new image to the DOM so\n",
4849         "    // that it is saved nicely (might be nice to debounce this).\n",
4850         "    setTimeout(function () {\n",
4851         "        fig.push_to_output();\n",
4852         "    }, 1000);\n",
4853         "};\n",
4854         "\n",
4855         "mpl.figure.prototype._init_toolbar = function () {\n",
4856         "    var fig = this;\n",
4857         "\n",
4858         "    var toolbar = document.createElement('div');\n",
4859         "    toolbar.classList = 'btn-toolbar';\n",
4860         "    this.root.appendChild(toolbar);\n",
4861         "\n",
4862         "    function on_click_closure(name) {\n",
4863         "        return function (_event) {\n",
4864         "            return fig.toolbar_button_onclick(name);\n",
4865         "        };\n",
4866         "    }\n",
4867         "\n",
4868         "    function on_mouseover_closure(tooltip) {\n",
4869         "        return function (event) {\n",
4870         "            if (!event.currentTarget.disabled) {\n",
4871         "                return fig.toolbar_button_onmouseover(tooltip);\n",
4872         "            }\n",
4873         "        };\n",
4874         "    }\n",
4875         "\n",
4876         "    fig.buttons = {};\n",
4877         "    var buttonGroup = document.createElement('div');\n",
4878         "    buttonGroup.classList = 'btn-group';\n",
4879         "    var button;\n",
4880         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
4881         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
4882         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
4883         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
4884         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
4885         "\n",
4886         "        if (!name) {\n",
4887         "            /* Instead of a spacer, we start a new button group. */\n",
4888         "            if (buttonGroup.hasChildNodes()) {\n",
4889         "                toolbar.appendChild(buttonGroup);\n",
4890         "            }\n",
4891         "            buttonGroup = document.createElement('div');\n",
4892         "            buttonGroup.classList = 'btn-group';\n",
4893         "            continue;\n",
4894         "        }\n",
4895         "\n",
4896         "        button = fig.buttons[name] = document.createElement('button');\n",
4897         "        button.classList = 'btn btn-default';\n",
4898         "        button.href = '#';\n",
4899         "        button.title = name;\n",
4900         "        button.innerHTML = '<i class=\"fa ' + image + ' fa-lg\"></i>';\n",
4901         "        button.addEventListener('click', on_click_closure(method_name));\n",
4902         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
4903         "        buttonGroup.appendChild(button);\n",
4904         "    }\n",
4905         "\n",
4906         "    if (buttonGroup.hasChildNodes()) {\n",
4907         "        toolbar.appendChild(buttonGroup);\n",
4908         "    }\n",
4909         "\n",
4910         "    // Add the status bar.\n",
4911         "    var status_bar = document.createElement('span');\n",
4912         "    status_bar.classList = 'mpl-message pull-right';\n",
4913         "    toolbar.appendChild(status_bar);\n",
4914         "    this.message = status_bar;\n",
4915         "\n",
4916         "    // Add the close button to the window.\n",
4917         "    var buttongrp = document.createElement('div');\n",
4918         "    buttongrp.classList = 'btn-group inline pull-right';\n",
4919         "    button = document.createElement('button');\n",
4920         "    button.classList = 'btn btn-mini btn-primary';\n",
4921         "    button.href = '#';\n",
4922         "    button.title = 'Stop Interaction';\n",
4923         "    button.innerHTML = '<i class=\"fa fa-power-off icon-remove icon-large\"></i>';\n",
4924         "    button.addEventListener('click', function (_evt) {\n",
4925         "        fig.handle_close(fig, {});\n",
4926         "    });\n",
4927         "    button.addEventListener(\n",
4928         "        'mouseover',\n",
4929         "        on_mouseover_closure('Stop Interaction')\n",
4930         "    );\n",
4931         "    buttongrp.appendChild(button);\n",
4932         "    var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n",
4933         "    titlebar.insertBefore(buttongrp, titlebar.firstChild);\n",
4934         "};\n",
4935         "\n",
4936         "mpl.figure.prototype._remove_fig_handler = function (event) {\n",
4937         "    var fig = event.data.fig;\n",
4938         "    if (event.target !== this) {\n",
4939         "        // Ignore bubbled events from children.\n",
4940         "        return;\n",
4941         "    }\n",
4942         "    fig.close_ws(fig, {});\n",
4943         "};\n",
4944         "\n",
4945         "mpl.figure.prototype._root_extra_style = function (el) {\n",
4946         "    el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n",
4947         "};\n",
4948         "\n",
4949         "mpl.figure.prototype._canvas_extra_style = function (el) {\n",
4950         "    // this is important to make the div 'focusable\n",
4951         "    el.setAttribute('tabindex', 0);\n",
4952         "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
4953         "    // off when our div gets focus\n",
4954         "\n",
4955         "    // location in version 3\n",
4956         "    if (IPython.notebook.keyboard_manager) {\n",
4957         "        IPython.notebook.keyboard_manager.register_events(el);\n",
4958         "    } else {\n",
4959         "        // location in version 2\n",
4960         "        IPython.keyboard_manager.register_events(el);\n",
4961         "    }\n",
4962         "};\n",
4963         "\n",
4964         "mpl.figure.prototype._key_event_extra = function (event, _name) {\n",
4965         "    var manager = IPython.notebook.keyboard_manager;\n",
4966         "    if (!manager) {\n",
4967         "        manager = IPython.keyboard_manager;\n",
4968         "    }\n",
4969         "\n",
4970         "    // Check for shift+enter\n",
4971         "    if (event.shiftKey && event.which === 13) {\n",
4972         "        this.canvas_div.blur();\n",
4973         "        // select the cell after this one\n",
4974         "        var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
4975         "        IPython.notebook.select(index + 1);\n",
4976         "    }\n",
4977         "};\n",
4978         "\n",
4979         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
4980         "    fig.ondownload(fig, null);\n",
4981         "};\n",
4982         "\n",
4983         "mpl.find_output_cell = function (html_output) {\n",
4984         "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
4985         "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
4986         "    // IPython event is triggered only after the cells have been serialised, which for\n",
4987         "    // our purposes (turning an active figure into a static one), is too late.\n",
4988         "    var cells = IPython.notebook.get_cells();\n",
4989         "    var ncells = cells.length;\n",
4990         "    for (var i = 0; i < ncells; i++) {\n",
4991         "        var cell = cells[i];\n",
4992         "        if (cell.cell_type === 'code') {\n",
4993         "            for (var j = 0; j < cell.output_area.outputs.length; j++) {\n",
4994         "                var data = cell.output_area.outputs[j];\n",
4995         "                if (data.data) {\n",
4996         "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
4997         "                    data = data.data;\n",
4998         "                }\n",
4999         "                if (data['text/html'] === html_output) {\n",
5000         "                    return [cell, data, j];\n",
5001         "                }\n",
5002         "            }\n",
5003         "        }\n",
5004         "    }\n",
5005         "};\n",
5006         "\n",
5007         "// Register the function which deals with the matplotlib target/channel.\n",
5008         "// The kernel may be null if the page has been refreshed.\n",
5009         "if (IPython.notebook.kernel !== null) {\n",
5010         "    IPython.notebook.kernel.comm_manager.register_target(\n",
5011         "        'matplotlib',\n",
5012         "        mpl.mpl_figure_comm\n",
5013         "    );\n",
5014         "}\n"
5015        ],
5016        "text/plain": [
5017         "<IPython.core.display.Javascript object>"
5018        ]
5019       },
5020       "metadata": {},
5021       "output_type": "display_data"
5022      },
5023      {
5024       "data": {
5025        "text/html": [
5026         "<div id='09269aeb-686f-480c-b161-46a688c80c85'></div>"
5027        ],
5028        "text/plain": [
5029         "<IPython.core.display.HTML object>"
5030        ]
5031       },
5032       "metadata": {},
5033       "output_type": "display_data"
5034      },
5035      {
5036       "name": "stderr",
5037       "output_type": "stream",
5038       "text": [
5039        "C:\\Users\\PC\\Pytho\\Applied-Machine-Learning-in-Python-master\\Source\\readonly\\adspy_shared_utilities.py:242: MatplotlibDeprecationWarning: shading='flat' when X and Y have the same dimensions as C is deprecated since 3.3.  Either specify the corners of the quadrilaterals with X and Y, or pass shading='auto', 'nearest' or 'gouraud', or set rcParams['pcolor.shading'].  This will become an error two minor releases later.\n",
5040        "  plt.pcolormesh(xx, yy, Z, cmap=cmap_light)\n"
5041       ]
5042      },
5043      {
5044       "data": {
5045        "application/javascript": [
5046         "/* Put everything inside the global mpl namespace */\n",
5047         "/* global mpl */\n",
5048         "window.mpl = {};\n",
5049         "\n",
5050         "mpl.get_websocket_type = function () {\n",
5051         "    if (typeof WebSocket !== 'undefined') {\n",
5052         "        return WebSocket;\n",
5053         "    } else if (typeof MozWebSocket !== 'undefined') {\n",
5054         "        return MozWebSocket;\n",
5055         "    } else {\n",
5056         "        alert(\n",
5057         "            'Your browser does not have WebSocket support. ' +\n",
5058         "                'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
5059         "                'Firefox 4 and 5 are also supported but you ' +\n",
5060         "                'have to enable WebSockets in about:config.'\n",
5061         "        );\n",
5062         "    }\n",
5063         "};\n",
5064         "\n",
5065         "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n",
5066         "    this.id = figure_id;\n",
5067         "\n",
5068         "    this.ws = websocket;\n",
5069         "\n",
5070         "    this.supports_binary = this.ws.binaryType !== undefined;\n",
5071         "\n",
5072         "    if (!this.supports_binary) {\n",
5073         "        var warnings = document.getElementById('mpl-warnings');\n",
5074         "        if (warnings) {\n",
5075         "            warnings.style.display = 'block';\n",
5076         "            warnings.textContent =\n",
5077         "                'This browser does not support binary websocket messages. ' +\n",
5078         "                'Performance may be slow.';\n",
5079         "        }\n",
5080         "    }\n",
5081         "\n",
5082         "    this.imageObj = new Image();\n",
5083         "\n",
5084         "    this.context = undefined;\n",
5085         "    this.message = undefined;\n",
5086         "    this.canvas = undefined;\n",
5087         "    this.rubberband_canvas = undefined;\n",
5088         "    this.rubberband_context = undefined;\n",
5089         "    this.format_dropdown = undefined;\n",
5090         "\n",
5091         "    this.image_mode = 'full';\n",
5092         "\n",
5093         "    this.root = document.createElement('div');\n",
5094         "    this.root.setAttribute('style', 'display: inline-block');\n",
5095         "    this._root_extra_style(this.root);\n",
5096         "\n",
5097         "    parent_element.appendChild(this.root);\n",
5098         "\n",
5099         "    this._init_header(this);\n",
5100         "    this._init_canvas(this);\n",
5101         "    this._init_toolbar(this);\n",
5102         "\n",
5103         "    var fig = this;\n",
5104         "\n",
5105         "    this.waiting = false;\n",
5106         "\n",
5107         "    this.ws.onopen = function () {\n",
5108         "        fig.send_message('supports_binary', { value: fig.supports_binary });\n",
5109         "        fig.send_message('send_image_mode', {});\n",
5110         "        if (fig.ratio !== 1) {\n",
5111         "            fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n",
5112         "        }\n",
5113         "        fig.send_message('refresh', {});\n",
5114         "    };\n",
5115         "\n",
5116         "    this.imageObj.onload = function () {\n",
5117         "        if (fig.image_mode === 'full') {\n",
5118         "            // Full images could contain transparency (where diff images\n",
5119         "            // almost always do), so we need to clear the canvas so that\n",
5120         "            // there is no ghosting.\n",
5121         "            fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
5122         "        }\n",
5123         "        fig.context.drawImage(fig.imageObj, 0, 0);\n",
5124         "    };\n",
5125         "\n",
5126         "    this.imageObj.onunload = function () {\n",
5127         "        fig.ws.close();\n",
5128         "    };\n",
5129         "\n",
5130         "    this.ws.onmessage = this._make_on_message_function(this);\n",
5131         "\n",
5132         "    this.ondownload = ondownload;\n",
5133         "};\n",
5134         "\n",
5135         "mpl.figure.prototype._init_header = function () {\n",
5136         "    var titlebar = document.createElement('div');\n",
5137         "    titlebar.classList =\n",
5138         "        'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n",
5139         "    var titletext = document.createElement('div');\n",
5140         "    titletext.classList = 'ui-dialog-title';\n",
5141         "    titletext.setAttribute(\n",
5142         "        'style',\n",
5143         "        'width: 100%; text-align: center; padding: 3px;'\n",
5144         "    );\n",
5145         "    titlebar.appendChild(titletext);\n",
5146         "    this.root.appendChild(titlebar);\n",
5147         "    this.header = titletext;\n",
5148         "};\n",
5149         "\n",
5150         "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n",
5151         "\n",
5152         "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n",
5153         "\n",
5154         "mpl.figure.prototype._init_canvas = function () {\n",
5155         "    var fig = this;\n",
5156         "\n",
5157         "    var canvas_div = (this.canvas_div = document.createElement('div'));\n",
5158         "    canvas_div.setAttribute(\n",
5159         "        'style',\n",
5160         "        'border: 1px solid #ddd;' +\n",
5161         "            'box-sizing: content-box;' +\n",
5162         "            'clear: both;' +\n",
5163         "            'min-height: 1px;' +\n",
5164         "            'min-width: 1px;' +\n",
5165         "            'outline: 0;' +\n",
5166         "            'overflow: hidden;' +\n",
5167         "            'position: relative;' +\n",
5168         "            'resize: both;'\n",
5169         "    );\n",
5170         "\n",
5171         "    function on_keyboard_event_closure(name) {\n",
5172         "        return function (event) {\n",
5173         "            return fig.key_event(event, name);\n",
5174         "        };\n",
5175         "    }\n",
5176         "\n",
5177         "    canvas_div.addEventListener(\n",
5178         "        'keydown',\n",
5179         "        on_keyboard_event_closure('key_press')\n",
5180         "    );\n",
5181         "    canvas_div.addEventListener(\n",
5182         "        'keyup',\n",
5183         "        on_keyboard_event_closure('key_release')\n",
5184         "    );\n",
5185         "\n",
5186         "    this._canvas_extra_style(canvas_div);\n",
5187         "    this.root.appendChild(canvas_div);\n",
5188         "\n",
5189         "    var canvas = (this.canvas = document.createElement('canvas'));\n",
5190         "    canvas.classList.add('mpl-canvas');\n",
5191         "    canvas.setAttribute('style', 'box-sizing: content-box;');\n",
5192         "\n",
5193         "    this.context = canvas.getContext('2d');\n",
5194         "\n",
5195         "    var backingStore =\n",
5196         "        this.context.backingStorePixelRatio ||\n",
5197         "        this.context.webkitBackingStorePixelRatio ||\n",
5198         "        this.context.mozBackingStorePixelRatio ||\n",
5199         "        this.context.msBackingStorePixelRatio ||\n",
5200         "        this.context.oBackingStorePixelRatio ||\n",
5201         "        this.context.backingStorePixelRatio ||\n",
5202         "        1;\n",
5203         "\n",
5204         "    this.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
5205         "\n",
5206         "    var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n",
5207         "        'canvas'\n",
5208         "    ));\n",
5209         "    rubberband_canvas.setAttribute(\n",
5210         "        'style',\n",
5211         "        'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n",
5212         "    );\n",
5213         "\n",
5214         "    // Apply a ponyfill if ResizeObserver is not implemented by browser.\n",
5215         "    if (this.ResizeObserver === undefined) {\n",
5216         "        if (window.ResizeObserver !== undefined) {\n",
5217         "            this.ResizeObserver = window.ResizeObserver;\n",
5218         "        } else {\n",
5219         "            var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n",
5220         "            this.ResizeObserver = obs.ResizeObserver;\n",
5221         "        }\n",
5222         "    }\n",
5223         "\n",
5224         "    this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n",
5225         "        var nentries = entries.length;\n",
5226         "        for (var i = 0; i < nentries; i++) {\n",
5227         "            var entry = entries[i];\n",
5228         "            var width, height;\n",
5229         "            if (entry.contentBoxSize) {\n",
5230         "                if (entry.contentBoxSize instanceof Array) {\n",
5231         "                    // Chrome 84 implements new version of spec.\n",
5232         "                    width = entry.contentBoxSize[0].inlineSize;\n",
5233         "                    height = entry.contentBoxSize[0].blockSize;\n",
5234         "                } else {\n",
5235         "                    // Firefox implements old version of spec.\n",
5236         "                    width = entry.contentBoxSize.inlineSize;\n",
5237         "                    height = entry.contentBoxSize.blockSize;\n",
5238         "                }\n",
5239         "            } else {\n",
5240         "                // Chrome <84 implements even older version of spec.\n",
5241         "                width = entry.contentRect.width;\n",
5242         "                height = entry.contentRect.height;\n",
5243         "            }\n",
5244         "\n",
5245         "            // Keep the size of the canvas and rubber band canvas in sync with\n",
5246         "            // the canvas container.\n",
5247         "            if (entry.devicePixelContentBoxSize) {\n",
5248         "                // Chrome 84 implements new version of spec.\n",
5249         "                canvas.setAttribute(\n",
5250         "                    'width',\n",
5251         "                    entry.devicePixelContentBoxSize[0].inlineSize\n",
5252         "                );\n",
5253         "                canvas.setAttribute(\n",
5254         "                    'height',\n",
5255         "                    entry.devicePixelContentBoxSize[0].blockSize\n",
5256         "                );\n",
5257         "            } else {\n",
5258         "                canvas.setAttribute('width', width * fig.ratio);\n",
5259         "                canvas.setAttribute('height', height * fig.ratio);\n",
5260         "            }\n",
5261         "            canvas.setAttribute(\n",
5262         "                'style',\n",
5263         "                'width: ' + width + 'px; height: ' + height + 'px;'\n",
5264         "            );\n",
5265         "\n",
5266         "            rubberband_canvas.setAttribute('width', width);\n",
5267         "            rubberband_canvas.setAttribute('height', height);\n",
5268         "\n",
5269         "            // And update the size in Python. We ignore the initial 0/0 size\n",
5270         "            // that occurs as the element is placed into the DOM, which should\n",
5271         "            // otherwise not happen due to the minimum size styling.\n",
5272         "            if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n",
5273         "                fig.request_resize(width, height);\n",
5274         "            }\n",
5275         "        }\n",
5276         "    });\n",
5277         "    this.resizeObserverInstance.observe(canvas_div);\n",
5278         "\n",
5279         "    function on_mouse_event_closure(name) {\n",
5280         "        return function (event) {\n",
5281         "            return fig.mouse_event(event, name);\n",
5282         "        };\n",
5283         "    }\n",
5284         "\n",
5285         "    rubberband_canvas.addEventListener(\n",
5286         "        'mousedown',\n",
5287         "        on_mouse_event_closure('button_press')\n",
5288         "    );\n",
5289         "    rubberband_canvas.addEventListener(\n",
5290         "        'mouseup',\n",
5291         "        on_mouse_event_closure('button_release')\n",
5292         "    );\n",
5293         "    // Throttle sequential mouse events to 1 every 20ms.\n",
5294         "    rubberband_canvas.addEventListener(\n",
5295         "        'mousemove',\n",
5296         "        on_mouse_event_closure('motion_notify')\n",
5297         "    );\n",
5298         "\n",
5299         "    rubberband_canvas.addEventListener(\n",
5300         "        'mouseenter',\n",
5301         "        on_mouse_event_closure('figure_enter')\n",
5302         "    );\n",
5303         "    rubberband_canvas.addEventListener(\n",
5304         "        'mouseleave',\n",
5305         "        on_mouse_event_closure('figure_leave')\n",
5306         "    );\n",
5307         "\n",
5308         "    canvas_div.addEventListener('wheel', function (event) {\n",
5309         "        if (event.deltaY < 0) {\n",
5310         "            event.step = 1;\n",
5311         "        } else {\n",
5312         "            event.step = -1;\n",
5313         "        }\n",
5314         "        on_mouse_event_closure('scroll')(event);\n",
5315         "    });\n",
5316         "\n",
5317         "    canvas_div.appendChild(canvas);\n",
5318         "    canvas_div.appendChild(rubberband_canvas);\n",
5319         "\n",
5320         "    this.rubberband_context = rubberband_canvas.getContext('2d');\n",
5321         "    this.rubberband_context.strokeStyle = '#000000';\n",
5322         "\n",
5323         "    this._resize_canvas = function (width, height, forward) {\n",
5324         "        if (forward) {\n",
5325         "            canvas_div.style.width = width + 'px';\n",
5326         "            canvas_div.style.height = height + 'px';\n",
5327         "        }\n",
5328         "    };\n",
5329         "\n",
5330         "    // Disable right mouse context menu.\n",
5331         "    this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n",
5332         "        event.preventDefault();\n",
5333         "        return false;\n",
5334         "    });\n",
5335         "\n",
5336         "    function set_focus() {\n",
5337         "        canvas.focus();\n",
5338         "        canvas_div.focus();\n",
5339         "    }\n",
5340         "\n",
5341         "    window.setTimeout(set_focus, 100);\n",
5342         "};\n",
5343         "\n",
5344         "mpl.figure.prototype._init_toolbar = function () {\n",
5345         "    var fig = this;\n",
5346         "\n",
5347         "    var toolbar = document.createElement('div');\n",
5348         "    toolbar.classList = 'mpl-toolbar';\n",
5349         "    this.root.appendChild(toolbar);\n",
5350         "\n",
5351         "    function on_click_closure(name) {\n",
5352         "        return function (_event) {\n",
5353         "            return fig.toolbar_button_onclick(name);\n",
5354         "        };\n",
5355         "    }\n",
5356         "\n",
5357         "    function on_mouseover_closure(tooltip) {\n",
5358         "        return function (event) {\n",
5359         "            if (!event.currentTarget.disabled) {\n",
5360         "                return fig.toolbar_button_onmouseover(tooltip);\n",
5361         "            }\n",
5362         "        };\n",
5363         "    }\n",
5364         "\n",
5365         "    fig.buttons = {};\n",
5366         "    var buttonGroup = document.createElement('div');\n",
5367         "    buttonGroup.classList = 'mpl-button-group';\n",
5368         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
5369         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
5370         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
5371         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
5372         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
5373         "\n",
5374         "        if (!name) {\n",
5375         "            /* Instead of a spacer, we start a new button group. */\n",
5376         "            if (buttonGroup.hasChildNodes()) {\n",
5377         "                toolbar.appendChild(buttonGroup);\n",
5378         "            }\n",
5379         "            buttonGroup = document.createElement('div');\n",
5380         "            buttonGroup.classList = 'mpl-button-group';\n",
5381         "            continue;\n",
5382         "        }\n",
5383         "\n",
5384         "        var button = (fig.buttons[name] = document.createElement('button'));\n",
5385         "        button.classList = 'mpl-widget';\n",
5386         "        button.setAttribute('role', 'button');\n",
5387         "        button.setAttribute('aria-disabled', 'false');\n",
5388         "        button.addEventListener('click', on_click_closure(method_name));\n",
5389         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
5390         "\n",
5391         "        var icon_img = document.createElement('img');\n",
5392         "        icon_img.src = '_images/' + image + '.png';\n",
5393         "        icon_img.srcset = '_images/' + image + '_large.png 2x';\n",
5394         "        icon_img.alt = tooltip;\n",
5395         "        button.appendChild(icon_img);\n",
5396         "\n",
5397         "        buttonGroup.appendChild(button);\n",
5398         "    }\n",
5399         "\n",
5400         "    if (buttonGroup.hasChildNodes()) {\n",
5401         "        toolbar.appendChild(buttonGroup);\n",
5402         "    }\n",
5403         "\n",
5404         "    var fmt_picker = document.createElement('select');\n",
5405         "    fmt_picker.classList = 'mpl-widget';\n",
5406         "    toolbar.appendChild(fmt_picker);\n",
5407         "    this.format_dropdown = fmt_picker;\n",
5408         "\n",
5409         "    for (var ind in mpl.extensions) {\n",
5410         "        var fmt = mpl.extensions[ind];\n",
5411         "        var option = document.createElement('option');\n",
5412         "        option.selected = fmt === mpl.default_extension;\n",
5413         "        option.innerHTML = fmt;\n",
5414         "        fmt_picker.appendChild(option);\n",
5415         "    }\n",
5416         "\n",
5417         "    var status_bar = document.createElement('span');\n",
5418         "    status_bar.classList = 'mpl-message';\n",
5419         "    toolbar.appendChild(status_bar);\n",
5420         "    this.message = status_bar;\n",
5421         "};\n",
5422         "\n",
5423         "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n",
5424         "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
5425         "    // which will in turn request a refresh of the image.\n",
5426         "    this.send_message('resize', { width: x_pixels, height: y_pixels });\n",
5427         "};\n",
5428         "\n",
5429         "mpl.figure.prototype.send_message = function (type, properties) {\n",
5430         "    properties['type'] = type;\n",
5431         "    properties['figure_id'] = this.id;\n",
5432         "    this.ws.send(JSON.stringify(properties));\n",
5433         "};\n",
5434         "\n",
5435         "mpl.figure.prototype.send_draw_message = function () {\n",
5436         "    if (!this.waiting) {\n",
5437         "        this.waiting = true;\n",
5438         "        this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n",
5439         "    }\n",
5440         "};\n",
5441         "\n",
5442         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
5443         "    var format_dropdown = fig.format_dropdown;\n",
5444         "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
5445         "    fig.ondownload(fig, format);\n",
5446         "};\n",
5447         "\n",
5448         "mpl.figure.prototype.handle_resize = function (fig, msg) {\n",
5449         "    var size = msg['size'];\n",
5450         "    if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n",
5451         "        fig._resize_canvas(size[0], size[1], msg['forward']);\n",
5452         "        fig.send_message('refresh', {});\n",
5453         "    }\n",
5454         "};\n",
5455         "\n",
5456         "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n",
5457         "    var x0 = msg['x0'] / fig.ratio;\n",
5458         "    var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n",
5459         "    var x1 = msg['x1'] / fig.ratio;\n",
5460         "    var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n",
5461         "    x0 = Math.floor(x0) + 0.5;\n",
5462         "    y0 = Math.floor(y0) + 0.5;\n",
5463         "    x1 = Math.floor(x1) + 0.5;\n",
5464         "    y1 = Math.floor(y1) + 0.5;\n",
5465         "    var min_x = Math.min(x0, x1);\n",
5466         "    var min_y = Math.min(y0, y1);\n",
5467         "    var width = Math.abs(x1 - x0);\n",
5468         "    var height = Math.abs(y1 - y0);\n",
5469         "\n",
5470         "    fig.rubberband_context.clearRect(\n",
5471         "        0,\n",
5472         "        0,\n",
5473         "        fig.canvas.width / fig.ratio,\n",
5474         "        fig.canvas.height / fig.ratio\n",
5475         "    );\n",
5476         "\n",
5477         "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
5478         "};\n",
5479         "\n",
5480         "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n",
5481         "    // Updates the figure title.\n",
5482         "    fig.header.textContent = msg['label'];\n",
5483         "};\n",
5484         "\n",
5485         "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n",
5486         "    var cursor = msg['cursor'];\n",
5487         "    switch (cursor) {\n",
5488         "        case 0:\n",
5489         "            cursor = 'pointer';\n",
5490         "            break;\n",
5491         "        case 1:\n",
5492         "            cursor = 'default';\n",
5493         "            break;\n",
5494         "        case 2:\n",
5495         "            cursor = 'crosshair';\n",
5496         "            break;\n",
5497         "        case 3:\n",
5498         "            cursor = 'move';\n",
5499         "            break;\n",
5500         "    }\n",
5501         "    fig.rubberband_canvas.style.cursor = cursor;\n",
5502         "};\n",
5503         "\n",
5504         "mpl.figure.prototype.handle_message = function (fig, msg) {\n",
5505         "    fig.message.textContent = msg['message'];\n",
5506         "};\n",
5507         "\n",
5508         "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n",
5509         "    // Request the server to send over a new figure.\n",
5510         "    fig.send_draw_message();\n",
5511         "};\n",
5512         "\n",
5513         "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n",
5514         "    fig.image_mode = msg['mode'];\n",
5515         "};\n",
5516         "\n",
5517         "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n",
5518         "    for (var key in msg) {\n",
5519         "        if (!(key in fig.buttons)) {\n",
5520         "            continue;\n",
5521         "        }\n",
5522         "        fig.buttons[key].disabled = !msg[key];\n",
5523         "        fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n",
5524         "    }\n",
5525         "};\n",
5526         "\n",
5527         "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n",
5528         "    if (msg['mode'] === 'PAN') {\n",
5529         "        fig.buttons['Pan'].classList.add('active');\n",
5530         "        fig.buttons['Zoom'].classList.remove('active');\n",
5531         "    } else if (msg['mode'] === 'ZOOM') {\n",
5532         "        fig.buttons['Pan'].classList.remove('active');\n",
5533         "        fig.buttons['Zoom'].classList.add('active');\n",
5534         "    } else {\n",
5535         "        fig.buttons['Pan'].classList.remove('active');\n",
5536         "        fig.buttons['Zoom'].classList.remove('active');\n",
5537         "    }\n",
5538         "};\n",
5539         "\n",
5540         "mpl.figure.prototype.updated_canvas_event = function () {\n",
5541         "    // Called whenever the canvas gets updated.\n",
5542         "    this.send_message('ack', {});\n",
5543         "};\n",
5544         "\n",
5545         "// A function to construct a web socket function for onmessage handling.\n",
5546         "// Called in the figure constructor.\n",
5547         "mpl.figure.prototype._make_on_message_function = function (fig) {\n",
5548         "    return function socket_on_message(evt) {\n",
5549         "        if (evt.data instanceof Blob) {\n",
5550         "            /* FIXME: We get \"Resource interpreted as Image but\n",
5551         "             * transferred with MIME type text/plain:\" errors on\n",
5552         "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
5553         "             * to be part of the websocket stream */\n",
5554         "            evt.data.type = 'image/png';\n",
5555         "\n",
5556         "            /* Free the memory for the previous frames */\n",
5557         "            if (fig.imageObj.src) {\n",
5558         "                (window.URL || window.webkitURL).revokeObjectURL(\n",
5559         "                    fig.imageObj.src\n",
5560         "                );\n",
5561         "            }\n",
5562         "\n",
5563         "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
5564         "                evt.data\n",
5565         "            );\n",
5566         "            fig.updated_canvas_event();\n",
5567         "            fig.waiting = false;\n",
5568         "            return;\n",
5569         "        } else if (\n",
5570         "            typeof evt.data === 'string' &&\n",
5571         "            evt.data.slice(0, 21) === 'data:image/png;base64'\n",
5572         "        ) {\n",
5573         "            fig.imageObj.src = evt.data;\n",
5574         "            fig.updated_canvas_event();\n",
5575         "            fig.waiting = false;\n",
5576         "            return;\n",
5577         "        }\n",
5578         "\n",
5579         "        var msg = JSON.parse(evt.data);\n",
5580         "        var msg_type = msg['type'];\n",
5581         "\n",
5582         "        // Call the  \"handle_{type}\" callback, which takes\n",
5583         "        // the figure and JSON message as its only arguments.\n",
5584         "        try {\n",
5585         "            var callback = fig['handle_' + msg_type];\n",
5586         "        } catch (e) {\n",
5587         "            console.log(\n",
5588         "                \"No handler for the '\" + msg_type + \"' message type: \",\n",
5589         "                msg\n",
5590         "            );\n",
5591         "            return;\n",
5592         "        }\n",
5593         "\n",
5594         "        if (callback) {\n",
5595         "            try {\n",
5596         "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
5597         "                callback(fig, msg);\n",
5598         "            } catch (e) {\n",
5599         "                console.log(\n",
5600         "                    \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n",
5601         "                    e,\n",
5602         "                    e.stack,\n",
5603         "                    msg\n",
5604         "                );\n",
5605         "            }\n",
5606         "        }\n",
5607         "    };\n",
5608         "};\n",
5609         "\n",
5610         "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
5611         "mpl.findpos = function (e) {\n",
5612         "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
5613         "    var targ;\n",
5614         "    if (!e) {\n",
5615         "        e = window.event;\n",
5616         "    }\n",
5617         "    if (e.target) {\n",
5618         "        targ = e.target;\n",
5619         "    } else if (e.srcElement) {\n",
5620         "        targ = e.srcElement;\n",
5621         "    }\n",
5622         "    if (targ.nodeType === 3) {\n",
5623         "        // defeat Safari bug\n",
5624         "        targ = targ.parentNode;\n",
5625         "    }\n",
5626         "\n",
5627         "    // pageX,Y are the mouse positions relative to the document\n",
5628         "    var boundingRect = targ.getBoundingClientRect();\n",
5629         "    var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n",
5630         "    var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n",
5631         "\n",
5632         "    return { x: x, y: y };\n",
5633         "};\n",
5634         "\n",
5635         "/*\n",
5636         " * return a copy of an object with only non-object keys\n",
5637         " * we need this to avoid circular references\n",
5638         " * http://stackoverflow.com/a/24161582/3208463\n",
5639         " */\n",
5640         "function simpleKeys(original) {\n",
5641         "    return Object.keys(original).reduce(function (obj, key) {\n",
5642         "        if (typeof original[key] !== 'object') {\n",
5643         "            obj[key] = original[key];\n",
5644         "        }\n",
5645         "        return obj;\n",
5646         "    }, {});\n",
5647         "}\n",
5648         "\n",
5649         "mpl.figure.prototype.mouse_event = function (event, name) {\n",
5650         "    var canvas_pos = mpl.findpos(event);\n",
5651         "\n",
5652         "    if (name === 'button_press') {\n",
5653         "        this.canvas.focus();\n",
5654         "        this.canvas_div.focus();\n",
5655         "    }\n",
5656         "\n",
5657         "    var x = canvas_pos.x * this.ratio;\n",
5658         "    var y = canvas_pos.y * this.ratio;\n",
5659         "\n",
5660         "    this.send_message(name, {\n",
5661         "        x: x,\n",
5662         "        y: y,\n",
5663         "        button: event.button,\n",
5664         "        step: event.step,\n",
5665         "        guiEvent: simpleKeys(event),\n",
5666         "    });\n",
5667         "\n",
5668         "    /* This prevents the web browser from automatically changing to\n",
5669         "     * the text insertion cursor when the button is pressed.  We want\n",
5670         "     * to control all of the cursor setting manually through the\n",
5671         "     * 'cursor' event from matplotlib */\n",
5672         "    event.preventDefault();\n",
5673         "    return false;\n",
5674         "};\n",
5675         "\n",
5676         "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n",
5677         "    // Handle any extra behaviour associated with a key event\n",
5678         "};\n",
5679         "\n",
5680         "mpl.figure.prototype.key_event = function (event, name) {\n",
5681         "    // Prevent repeat events\n",
5682         "    if (name === 'key_press') {\n",
5683         "        if (event.which === this._key) {\n",
5684         "            return;\n",
5685         "        } else {\n",
5686         "            this._key = event.which;\n",
5687         "        }\n",
5688         "    }\n",
5689         "    if (name === 'key_release') {\n",
5690         "        this._key = null;\n",
5691         "    }\n",
5692         "\n",
5693         "    var value = '';\n",
5694         "    if (event.ctrlKey && event.which !== 17) {\n",
5695         "        value += 'ctrl+';\n",
5696         "    }\n",
5697         "    if (event.altKey && event.which !== 18) {\n",
5698         "        value += 'alt+';\n",
5699         "    }\n",
5700         "    if (event.shiftKey && event.which !== 16) {\n",
5701         "        value += 'shift+';\n",
5702         "    }\n",
5703         "\n",
5704         "    value += 'k';\n",
5705         "    value += event.which.toString();\n",
5706         "\n",
5707         "    this._key_event_extra(event, name);\n",
5708         "\n",
5709         "    this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n",
5710         "    return false;\n",
5711         "};\n",
5712         "\n",
5713         "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n",
5714         "    if (name === 'download') {\n",
5715         "        this.handle_save(this, null);\n",
5716         "    } else {\n",
5717         "        this.send_message('toolbar_button', { name: name });\n",
5718         "    }\n",
5719         "};\n",
5720         "\n",
5721         "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n",
5722         "    this.message.textContent = tooltip;\n",
5723         "};\n",
5724         "\n",
5725         "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n",
5726         "// prettier-ignore\n",
5727         "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n",
5728         "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
5729         "\n",
5730         "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
5731         "\n",
5732         "mpl.default_extension = \"png\";/* global mpl */\n",
5733         "\n",
5734         "var comm_websocket_adapter = function (comm) {\n",
5735         "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
5736         "    // object with the appropriate methods. Currently this is a non binary\n",
5737         "    // socket, so there is still some room for performance tuning.\n",
5738         "    var ws = {};\n",
5739         "\n",
5740         "    ws.close = function () {\n",
5741         "        comm.close();\n",
5742         "    };\n",
5743         "    ws.send = function (m) {\n",
5744         "        //console.log('sending', m);\n",
5745         "        comm.send(m);\n",
5746         "    };\n",
5747         "    // Register the callback with on_msg.\n",
5748         "    comm.on_msg(function (msg) {\n",
5749         "        //console.log('receiving', msg['content']['data'], msg);\n",
5750         "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
5751         "        ws.onmessage(msg['content']['data']);\n",
5752         "    });\n",
5753         "    return ws;\n",
5754         "};\n",
5755         "\n",
5756         "mpl.mpl_figure_comm = function (comm, msg) {\n",
5757         "    // This is the function which gets called when the mpl process\n",
5758         "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
5759         "\n",
5760         "    var id = msg.content.data.id;\n",
5761         "    // Get hold of the div created by the display call when the Comm\n",
5762         "    // socket was opened in Python.\n",
5763         "    var element = document.getElementById(id);\n",
5764         "    var ws_proxy = comm_websocket_adapter(comm);\n",
5765         "\n",
5766         "    function ondownload(figure, _format) {\n",
5767         "        window.open(figure.canvas.toDataURL());\n",
5768         "    }\n",
5769         "\n",
5770         "    var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n",
5771         "\n",
5772         "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
5773         "    // web socket which is closed, not our websocket->open comm proxy.\n",
5774         "    ws_proxy.onopen();\n",
5775         "\n",
5776         "    fig.parent_element = element;\n",
5777         "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
5778         "    if (!fig.cell_info) {\n",
5779         "        console.error('Failed to find cell for figure', id, fig);\n",
5780         "        return;\n",
5781         "    }\n",
5782         "    fig.cell_info[0].output_area.element.on(\n",
5783         "        'cleared',\n",
5784         "        { fig: fig },\n",
5785         "        fig._remove_fig_handler\n",
5786         "    );\n",
5787         "};\n",
5788         "\n",
5789         "mpl.figure.prototype.handle_close = function (fig, msg) {\n",
5790         "    var width = fig.canvas.width / fig.ratio;\n",
5791         "    fig.cell_info[0].output_area.element.off(\n",
5792         "        'cleared',\n",
5793         "        fig._remove_fig_handler\n",
5794         "    );\n",
5795         "    fig.resizeObserverInstance.unobserve(fig.canvas_div);\n",
5796         "\n",
5797         "    // Update the output cell to use the data from the current canvas.\n",
5798         "    fig.push_to_output();\n",
5799         "    var dataURL = fig.canvas.toDataURL();\n",
5800         "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
5801         "    // the notebook keyboard shortcuts fail.\n",
5802         "    IPython.keyboard_manager.enable();\n",
5803         "    fig.parent_element.innerHTML =\n",
5804         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
5805         "    fig.close_ws(fig, msg);\n",
5806         "};\n",
5807         "\n",
5808         "mpl.figure.prototype.close_ws = function (fig, msg) {\n",
5809         "    fig.send_message('closing', msg);\n",
5810         "    // fig.ws.close()\n",
5811         "};\n",
5812         "\n",
5813         "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n",
5814         "    // Turn the data on the canvas into data in the output cell.\n",
5815         "    var width = this.canvas.width / this.ratio;\n",
5816         "    var dataURL = this.canvas.toDataURL();\n",
5817         "    this.cell_info[1]['text/html'] =\n",
5818         "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
5819         "};\n",
5820         "\n",
5821         "mpl.figure.prototype.updated_canvas_event = function () {\n",
5822         "    // Tell IPython that the notebook contents must change.\n",
5823         "    IPython.notebook.set_dirty(true);\n",
5824         "    this.send_message('ack', {});\n",
5825         "    var fig = this;\n",
5826         "    // Wait a second, then push the new image to the DOM so\n",
5827         "    // that it is saved nicely (might be nice to debounce this).\n",
5828         "    setTimeout(function () {\n",
5829         "        fig.push_to_output();\n",
5830         "    }, 1000);\n",
5831         "};\n",
5832         "\n",
5833         "mpl.figure.prototype._init_toolbar = function () {\n",
5834         "    var fig = this;\n",
5835         "\n",
5836         "    var toolbar = document.createElement('div');\n",
5837         "    toolbar.classList = 'btn-toolbar';\n",
5838         "    this.root.appendChild(toolbar);\n",
5839         "\n",
5840         "    function on_click_closure(name) {\n",
5841         "        return function (_event) {\n",
5842         "            return fig.toolbar_button_onclick(name);\n",
5843         "        };\n",
5844         "    }\n",
5845         "\n",
5846         "    function on_mouseover_closure(tooltip) {\n",
5847         "        return function (event) {\n",
5848         "            if (!event.currentTarget.disabled) {\n",
5849         "                return fig.toolbar_button_onmouseover(tooltip);\n",
5850         "            }\n",
5851         "        };\n",
5852         "    }\n",
5853         "\n",
5854         "    fig.buttons = {};\n",
5855         "    var buttonGroup = document.createElement('div');\n",
5856         "    buttonGroup.classList = 'btn-group';\n",
5857         "    var button;\n",
5858         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
5859         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
5860         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
5861         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
5862         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
5863         "\n",
5864         "        if (!name) {\n",
5865         "            /* Instead of a spacer, we start a new button group. */\n",
5866         "            if (buttonGroup.hasChildNodes()) {\n",
5867         "                toolbar.appendChild(buttonGroup);\n",
5868         "            }\n",
5869         "            buttonGroup = document.createElement('div');\n",
5870         "            buttonGroup.classList = 'btn-group';\n",
5871         "            continue;\n",
5872         "        }\n",
5873         "\n",
5874         "        button = fig.buttons[name] = document.createElement('button');\n",
5875         "        button.classList = 'btn btn-default';\n",
5876         "        button.href = '#';\n",
5877         "        button.title = name;\n",
5878         "        button.innerHTML = '<i class=\"fa ' + image + ' fa-lg\"></i>';\n",
5879         "        button.addEventListener('click', on_click_closure(method_name));\n",
5880         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
5881         "        buttonGroup.appendChild(button);\n",
5882         "    }\n",
5883         "\n",
5884         "    if (buttonGroup.hasChildNodes()) {\n",
5885         "        toolbar.appendChild(buttonGroup);\n",
5886         "    }\n",
5887         "\n",
5888         "    // Add the status bar.\n",
5889         "    var status_bar = document.createElement('span');\n",
5890         "    status_bar.classList = 'mpl-message pull-right';\n",
5891         "    toolbar.appendChild(status_bar);\n",
5892         "    this.message = status_bar;\n",
5893         "\n",
5894         "    // Add the close button to the window.\n",
5895         "    var buttongrp = document.createElement('div');\n",
5896         "    buttongrp.classList = 'btn-group inline pull-right';\n",
5897         "    button = document.createElement('button');\n",
5898         "    button.classList = 'btn btn-mini btn-primary';\n",
5899         "    button.href = '#';\n",
5900         "    button.title = 'Stop Interaction';\n",
5901         "    button.innerHTML = '<i class=\"fa fa-power-off icon-remove icon-large\"></i>';\n",
5902         "    button.addEventListener('click', function (_evt) {\n",
5903         "        fig.handle_close(fig, {});\n",
5904         "    });\n",
5905         "    button.addEventListener(\n",
5906         "        'mouseover',\n",
5907         "        on_mouseover_closure('Stop Interaction')\n",
5908         "    );\n",
5909         "    buttongrp.appendChild(button);\n",
5910         "    var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n",
5911         "    titlebar.insertBefore(buttongrp, titlebar.firstChild);\n",
5912         "};\n",
5913         "\n",
5914         "mpl.figure.prototype._remove_fig_handler = function (event) {\n",
5915         "    var fig = event.data.fig;\n",
5916         "    if (event.target !== this) {\n",
5917         "        // Ignore bubbled events from children.\n",
5918         "        return;\n",
5919         "    }\n",
5920         "    fig.close_ws(fig, {});\n",
5921         "};\n",
5922         "\n",
5923         "mpl.figure.prototype._root_extra_style = function (el) {\n",
5924         "    el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n",
5925         "};\n",
5926         "\n",
5927         "mpl.figure.prototype._canvas_extra_style = function (el) {\n",
5928         "    // this is important to make the div 'focusable\n",
5929         "    el.setAttribute('tabindex', 0);\n",
5930         "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
5931         "    // off when our div gets focus\n",
5932         "\n",
5933         "    // location in version 3\n",
5934         "    if (IPython.notebook.keyboard_manager) {\n",
5935         "        IPython.notebook.keyboard_manager.register_events(el);\n",
5936         "    } else {\n",
5937         "        // location in version 2\n",
5938         "        IPython.keyboard_manager.register_events(el);\n",
5939         "    }\n",
5940         "};\n",
5941         "\n",
5942         "mpl.figure.prototype._key_event_extra = function (event, _name) {\n",
5943         "    var manager = IPython.notebook.keyboard_manager;\n",
5944         "    if (!manager) {\n",
5945         "        manager = IPython.keyboard_manager;\n",
5946         "    }\n",
5947         "\n",
5948         "    // Check for shift+enter\n",
5949         "    if (event.shiftKey && event.which === 13) {\n",
5950         "        this.canvas_div.blur();\n",
5951         "        // select the cell after this one\n",
5952         "        var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
5953         "        IPython.notebook.select(index + 1);\n",
5954         "    }\n",
5955         "};\n",
5956         "\n",
5957         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
5958         "    fig.ondownload(fig, null);\n",
5959         "};\n",
5960         "\n",
5961         "mpl.find_output_cell = function (html_output) {\n",
5962         "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
5963         "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
5964         "    // IPython event is triggered only after the cells have been serialised, which for\n",
5965         "    // our purposes (turning an active figure into a static one), is too late.\n",
5966         "    var cells = IPython.notebook.get_cells();\n",
5967         "    var ncells = cells.length;\n",
5968         "    for (var i = 0; i < ncells; i++) {\n",
5969         "        var cell = cells[i];\n",
5970         "        if (cell.cell_type === 'code') {\n",
5971         "            for (var j = 0; j < cell.output_area.outputs.length; j++) {\n",
5972         "                var data = cell.output_area.outputs[j];\n",
5973         "                if (data.data) {\n",
5974         "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
5975         "                    data = data.data;\n",
5976         "                }\n",
5977         "                if (data['text/html'] === html_output) {\n",
5978         "                    return [cell, data, j];\n",
5979         "                }\n",
5980         "            }\n",
5981         "        }\n",
5982         "    }\n",
5983         "};\n",
5984         "\n",
5985         "// Register the function which deals with the matplotlib target/channel.\n",
5986         "// The kernel may be null if the page has been refreshed.\n",
5987         "if (IPython.notebook.kernel !== null) {\n",
5988         "    IPython.notebook.kernel.comm_manager.register_target(\n",
5989         "        'matplotlib',\n",
5990         "        mpl.mpl_figure_comm\n",
5991         "    );\n",
5992         "}\n"
5993        ],
5994        "text/plain": [
5995         "<IPython.core.display.Javascript object>"
5996        ]
5997       },
5998       "metadata": {},
5999       "output_type": "display_data"
6000      },
6001      {
6002       "data": {
6003        "text/html": [
6004         "<div id='e9903399-4037-40b0-9050-e42627f7ad74'></div>"
6005        ],
6006        "text/plain": [
6007         "<IPython.core.display.HTML object>"
6008        ]
6009       },
6010       "metadata": {},
6011       "output_type": "display_data"
6012      },
6013      {
6014       "name": "stderr",
6015       "output_type": "stream",
6016       "text": [
6017        "C:\\Users\\PC\\Pytho\\Applied-Machine-Learning-in-Python-master\\Source\\readonly\\adspy_shared_utilities.py:242: MatplotlibDeprecationWarning: shading='flat' when X and Y have the same dimensions as C is deprecated since 3.3.  Either specify the corners of the quadrilaterals with X and Y, or pass shading='auto', 'nearest' or 'gouraud', or set rcParams['pcolor.shading'].  This will become an error two minor releases later.\n",
6018        "  plt.pcolormesh(xx, yy, Z, cmap=cmap_light)\n"
6019       ]
6020      },
6021      {
6022       "data": {
6023        "application/javascript": [
6024         "/* Put everything inside the global mpl namespace */\n",
6025         "/* global mpl */\n",
6026         "window.mpl = {};\n",
6027         "\n",
6028         "mpl.get_websocket_type = function () {\n",
6029         "    if (typeof WebSocket !== 'undefined') {\n",
6030         "        return WebSocket;\n",
6031         "    } else if (typeof MozWebSocket !== 'undefined') {\n",
6032         "        return MozWebSocket;\n",
6033         "    } else {\n",
6034         "        alert(\n",
6035         "            'Your browser does not have WebSocket support. ' +\n",
6036         "                'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
6037         "                'Firefox 4 and 5 are also supported but you ' +\n",
6038         "                'have to enable WebSockets in about:config.'\n",
6039         "        );\n",
6040         "    }\n",
6041         "};\n",
6042         "\n",
6043         "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n",
6044         "    this.id = figure_id;\n",
6045         "\n",
6046         "    this.ws = websocket;\n",
6047         "\n",
6048         "    this.supports_binary = this.ws.binaryType !== undefined;\n",
6049         "\n",
6050         "    if (!this.supports_binary) {\n",
6051         "        var warnings = document.getElementById('mpl-warnings');\n",
6052         "        if (warnings) {\n",
6053         "            warnings.style.display = 'block';\n",
6054         "            warnings.textContent =\n",
6055         "                'This browser does not support binary websocket messages. ' +\n",
6056         "                'Performance may be slow.';\n",
6057         "        }\n",
6058         "    }\n",
6059         "\n",
6060         "    this.imageObj = new Image();\n",
6061         "\n",
6062         "    this.context = undefined;\n",
6063         "    this.message = undefined;\n",
6064         "    this.canvas = undefined;\n",
6065         "    this.rubberband_canvas = undefined;\n",
6066         "    this.rubberband_context = undefined;\n",
6067         "    this.format_dropdown = undefined;\n",
6068         "\n",
6069         "    this.image_mode = 'full';\n",
6070         "\n",
6071         "    this.root = document.createElement('div');\n",
6072         "    this.root.setAttribute('style', 'display: inline-block');\n",
6073         "    this._root_extra_style(this.root);\n",
6074         "\n",
6075         "    parent_element.appendChild(this.root);\n",
6076         "\n",
6077         "    this._init_header(this);\n",
6078         "    this._init_canvas(this);\n",
6079         "    this._init_toolbar(this);\n",
6080         "\n",
6081         "    var fig = this;\n",
6082         "\n",
6083         "    this.waiting = false;\n",
6084         "\n",
6085         "    this.ws.onopen = function () {\n",
6086         "        fig.send_message('supports_binary', { value: fig.supports_binary });\n",
6087         "        fig.send_message('send_image_mode', {});\n",
6088         "        if (fig.ratio !== 1) {\n",
6089         "            fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n",
6090         "        }\n",
6091         "        fig.send_message('refresh', {});\n",
6092         "    };\n",
6093         "\n",
6094         "    this.imageObj.onload = function () {\n",
6095         "        if (fig.image_mode === 'full') {\n",
6096         "            // Full images could contain transparency (where diff images\n",
6097         "            // almost always do), so we need to clear the canvas so that\n",
6098         "            // there is no ghosting.\n",
6099         "            fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
6100         "        }\n",
6101         "        fig.context.drawImage(fig.imageObj, 0, 0);\n",
6102         "    };\n",
6103         "\n",
6104         "    this.imageObj.onunload = function () {\n",
6105         "        fig.ws.close();\n",
6106         "    };\n",
6107         "\n",
6108         "    this.ws.onmessage = this._make_on_message_function(this);\n",
6109         "\n",
6110         "    this.ondownload = ondownload;\n",
6111         "};\n",
6112         "\n",
6113         "mpl.figure.prototype._init_header = function () {\n",
6114         "    var titlebar = document.createElement('div');\n",
6115         "    titlebar.classList =\n",
6116         "        'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n",
6117         "    var titletext = document.createElement('div');\n",
6118         "    titletext.classList = 'ui-dialog-title';\n",
6119         "    titletext.setAttribute(\n",
6120         "        'style',\n",
6121         "        'width: 100%; text-align: center; padding: 3px;'\n",
6122         "    );\n",
6123         "    titlebar.appendChild(titletext);\n",
6124         "    this.root.appendChild(titlebar);\n",
6125         "    this.header = titletext;\n",
6126         "};\n",
6127         "\n",
6128         "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n",
6129         "\n",
6130         "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n",
6131         "\n",
6132         "mpl.figure.prototype._init_canvas = function () {\n",
6133         "    var fig = this;\n",
6134         "\n",
6135         "    var canvas_div = (this.canvas_div = document.createElement('div'));\n",
6136         "    canvas_div.setAttribute(\n",
6137         "        'style',\n",
6138         "        'border: 1px solid #ddd;' +\n",
6139         "            'box-sizing: content-box;' +\n",
6140         "            'clear: both;' +\n",
6141         "            'min-height: 1px;' +\n",
6142         "            'min-width: 1px;' +\n",
6143         "            'outline: 0;' +\n",
6144         "            'overflow: hidden;' +\n",
6145         "            'position: relative;' +\n",
6146         "            'resize: both;'\n",
6147         "    );\n",
6148         "\n",
6149         "    function on_keyboard_event_closure(name) {\n",
6150         "        return function (event) {\n",
6151         "            return fig.key_event(event, name);\n",
6152         "        };\n",
6153         "    }\n",
6154         "\n",
6155         "    canvas_div.addEventListener(\n",
6156         "        'keydown',\n",
6157         "        on_keyboard_event_closure('key_press')\n",
6158         "    );\n",
6159         "    canvas_div.addEventListener(\n",
6160         "        'keyup',\n",
6161         "        on_keyboard_event_closure('key_release')\n",
6162         "    );\n",
6163         "\n",
6164         "    this._canvas_extra_style(canvas_div);\n",
6165         "    this.root.appendChild(canvas_div);\n",
6166         "\n",
6167         "    var canvas = (this.canvas = document.createElement('canvas'));\n",
6168         "    canvas.classList.add('mpl-canvas');\n",
6169         "    canvas.setAttribute('style', 'box-sizing: content-box;');\n",
6170         "\n",
6171         "    this.context = canvas.getContext('2d');\n",
6172         "\n",
6173         "    var backingStore =\n",
6174         "        this.context.backingStorePixelRatio ||\n",
6175         "        this.context.webkitBackingStorePixelRatio ||\n",
6176         "        this.context.mozBackingStorePixelRatio ||\n",
6177         "        this.context.msBackingStorePixelRatio ||\n",
6178         "        this.context.oBackingStorePixelRatio ||\n",
6179         "        this.context.backingStorePixelRatio ||\n",
6180         "        1;\n",
6181         "\n",
6182         "    this.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
6183         "\n",
6184         "    var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n",
6185         "        'canvas'\n",
6186         "    ));\n",
6187         "    rubberband_canvas.setAttribute(\n",
6188         "        'style',\n",
6189         "        'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n",
6190         "    );\n",
6191         "\n",
6192         "    // Apply a ponyfill if ResizeObserver is not implemented by browser.\n",
6193         "    if (this.ResizeObserver === undefined) {\n",
6194         "        if (window.ResizeObserver !== undefined) {\n",
6195         "            this.ResizeObserver = window.ResizeObserver;\n",
6196         "        } else {\n",
6197         "            var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n",
6198         "            this.ResizeObserver = obs.ResizeObserver;\n",
6199         "        }\n",
6200         "    }\n",
6201         "\n",
6202         "    this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n",
6203         "        var nentries = entries.length;\n",
6204         "        for (var i = 0; i < nentries; i++) {\n",
6205         "            var entry = entries[i];\n",
6206         "            var width, height;\n",
6207         "            if (entry.contentBoxSize) {\n",
6208         "                if (entry.contentBoxSize instanceof Array) {\n",
6209         "                    // Chrome 84 implements new version of spec.\n",
6210         "                    width = entry.contentBoxSize[0].inlineSize;\n",
6211         "                    height = entry.contentBoxSize[0].blockSize;\n",
6212         "                } else {\n",
6213         "                    // Firefox implements old version of spec.\n",
6214         "                    width = entry.contentBoxSize.inlineSize;\n",
6215         "                    height = entry.contentBoxSize.blockSize;\n",
6216         "                }\n",
6217         "            } else {\n",
6218         "                // Chrome <84 implements even older version of spec.\n",
6219         "                width = entry.contentRect.width;\n",
6220         "                height = entry.contentRect.height;\n",
6221         "            }\n",
6222         "\n",
6223         "            // Keep the size of the canvas and rubber band canvas in sync with\n",
6224         "            // the canvas container.\n",
6225         "            if (entry.devicePixelContentBoxSize) {\n",
6226         "                // Chrome 84 implements new version of spec.\n",
6227         "                canvas.setAttribute(\n",
6228         "                    'width',\n",
6229         "                    entry.devicePixelContentBoxSize[0].inlineSize\n",
6230         "                );\n",
6231         "                canvas.setAttribute(\n",
6232         "                    'height',\n",
6233         "                    entry.devicePixelContentBoxSize[0].blockSize\n",
6234         "                );\n",
6235         "            } else {\n",
6236         "                canvas.setAttribute('width', width * fig.ratio);\n",
6237         "                canvas.setAttribute('height', height * fig.ratio);\n",
6238         "            }\n",
6239         "            canvas.setAttribute(\n",
6240         "                'style',\n",
6241         "                'width: ' + width + 'px; height: ' + height + 'px;'\n",
6242         "            );\n",
6243         "\n",
6244         "            rubberband_canvas.setAttribute('width', width);\n",
6245         "            rubberband_canvas.setAttribute('height', height);\n",
6246         "\n",
6247         "            // And update the size in Python. We ignore the initial 0/0 size\n",
6248         "            // that occurs as the element is placed into the DOM, which should\n",
6249         "            // otherwise not happen due to the minimum size styling.\n",
6250         "            if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n",
6251         "                fig.request_resize(width, height);\n",
6252         "            }\n",
6253         "        }\n",
6254         "    });\n",
6255         "    this.resizeObserverInstance.observe(canvas_div);\n",
6256         "\n",
6257         "    function on_mouse_event_closure(name) {\n",
6258         "        return function (event) {\n",
6259         "            return fig.mouse_event(event, name);\n",
6260         "        };\n",
6261         "    }\n",
6262         "\n",
6263         "    rubberband_canvas.addEventListener(\n",
6264         "        'mousedown',\n",
6265         "        on_mouse_event_closure('button_press')\n",
6266         "    );\n",
6267         "    rubberband_canvas.addEventListener(\n",
6268         "        'mouseup',\n",
6269         "        on_mouse_event_closure('button_release')\n",
6270         "    );\n",
6271         "    // Throttle sequential mouse events to 1 every 20ms.\n",
6272         "    rubberband_canvas.addEventListener(\n",
6273         "        'mousemove',\n",
6274         "        on_mouse_event_closure('motion_notify')\n",
6275         "    );\n",
6276         "\n",
6277         "    rubberband_canvas.addEventListener(\n",
6278         "        'mouseenter',\n",
6279         "        on_mouse_event_closure('figure_enter')\n",
6280         "    );\n",
6281         "    rubberband_canvas.addEventListener(\n",
6282         "        'mouseleave',\n",
6283         "        on_mouse_event_closure('figure_leave')\n",
6284         "    );\n",
6285         "\n",
6286         "    canvas_div.addEventListener('wheel', function (event) {\n",
6287         "        if (event.deltaY < 0) {\n",
6288         "            event.step = 1;\n",
6289         "        } else {\n",
6290         "            event.step = -1;\n",
6291         "        }\n",
6292         "        on_mouse_event_closure('scroll')(event);\n",
6293         "    });\n",
6294         "\n",
6295         "    canvas_div.appendChild(canvas);\n",
6296         "    canvas_div.appendChild(rubberband_canvas);\n",
6297         "\n",
6298         "    this.rubberband_context = rubberband_canvas.getContext('2d');\n",
6299         "    this.rubberband_context.strokeStyle = '#000000';\n",
6300         "\n",
6301         "    this._resize_canvas = function (width, height, forward) {\n",
6302         "        if (forward) {\n",
6303         "            canvas_div.style.width = width + 'px';\n",
6304         "            canvas_div.style.height = height + 'px';\n",
6305         "        }\n",
6306         "    };\n",
6307         "\n",
6308         "    // Disable right mouse context menu.\n",
6309         "    this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n",
6310         "        event.preventDefault();\n",
6311         "        return false;\n",
6312         "    });\n",
6313         "\n",
6314         "    function set_focus() {\n",
6315         "        canvas.focus();\n",
6316         "        canvas_div.focus();\n",
6317         "    }\n",
6318         "\n",
6319         "    window.setTimeout(set_focus, 100);\n",
6320         "};\n",
6321         "\n",
6322         "mpl.figure.prototype._init_toolbar = function () {\n",
6323         "    var fig = this;\n",
6324         "\n",
6325         "    var toolbar = document.createElement('div');\n",
6326         "    toolbar.classList = 'mpl-toolbar';\n",
6327         "    this.root.appendChild(toolbar);\n",
6328         "\n",
6329         "    function on_click_closure(name) {\n",
6330         "        return function (_event) {\n",
6331         "            return fig.toolbar_button_onclick(name);\n",
6332         "        };\n",
6333         "    }\n",
6334         "\n",
6335         "    function on_mouseover_closure(tooltip) {\n",
6336         "        return function (event) {\n",
6337         "            if (!event.currentTarget.disabled) {\n",
6338         "                return fig.toolbar_button_onmouseover(tooltip);\n",
6339         "            }\n",
6340         "        };\n",
6341         "    }\n",
6342         "\n",
6343         "    fig.buttons = {};\n",
6344         "    var buttonGroup = document.createElement('div');\n",
6345         "    buttonGroup.classList = 'mpl-button-group';\n",
6346         "    for (var toolbar_ind in mpl.toolbar_items) {\n",
6347         "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
6348         "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
6349         "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
6350         "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
6351         "\n",
6352         "        if (!name) {\n",
6353         "            /* Instead of a spacer, we start a new button group. */\n",
6354         "            if (buttonGroup.hasChildNodes()) {\n",
6355         "                toolbar.appendChild(buttonGroup);\n",
6356         "            }\n",
6357         "            buttonGroup = document.createElement('div');\n",
6358         "            buttonGroup.classList = 'mpl-button-group';\n",
6359         "            continue;\n",
6360         "        }\n",
6361         "\n",
6362         "        var button = (fig.buttons[name] = document.createElement('button'));\n",
6363         "        button.classList = 'mpl-widget';\n",
6364         "        button.setAttribute('role', 'button');\n",
6365         "        button.setAttribute('aria-disabled', 'false');\n",
6366         "        button.addEventListener('click', on_click_closure(method_name));\n",
6367         "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
6368         "\n",
6369         "        var icon_img = document.createElement('img');\n",
6370         "        icon_img.src = '_images/' + image + '.png';\n",
6371         "        icon_img.srcset = '_images/' + image + '_large.png 2x';\n",
6372         "        icon_img.alt = tooltip;\n",
6373         "        button.appendChild(icon_img);\n",
6374         "\n",
6375         "        buttonGroup.appendChild(button);\n",
6376         "    }\n",
6377         "\n",
6378         "    if (buttonGroup.hasChildNodes()) {\n",
6379         "        toolbar.appendChild(buttonGroup);\n",
6380         "    }\n",
6381         "\n",
6382         "    var fmt_picker = document.createElement('select');\n",
6383         "    fmt_picker.classList = 'mpl-widget';\n",
6384         "    toolbar.appendChild(fmt_picker);\n",
6385         "    this.format_dropdown = fmt_picker;\n",
6386         "\n",
6387         "    for (var ind in mpl.extensions) {\n",
6388         "        var fmt = mpl.extensions[ind];\n",
6389         "        var option = document.createElement('option');\n",
6390         "        option.selected = fmt === mpl.default_extension;\n",
6391         "        option.innerHTML = fmt;\n",
6392         "        fmt_picker.appendChild(option);\n",
6393         "    }\n",
6394         "\n",
6395         "    var status_bar = document.createElement('span');\n",
6396         "    status_bar.classList = 'mpl-message';\n",
6397         "    toolbar.appendChild(status_bar);\n",
6398         "    this.message = status_bar;\n",
6399         "};\n",
6400         "\n",
6401         "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n",
6402         "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
6403         "    // which will in turn request a refresh of the image.\n",
6404         "    this.send_message('resize', { width: x_pixels, height: y_pixels });\n",
6405         "};\n",
6406         "\n",
6407         "mpl.figure.prototype.send_message = function (type, properties) {\n",
6408         "    properties['type'] = type;\n",
6409         "    properties['figure_id'] = this.id;\n",
6410         "    this.ws.send(JSON.stringify(properties));\n",
6411         "};\n",
6412         "\n",
6413         "mpl.figure.prototype.send_draw_message = function () {\n",
6414         "    if (!this.waiting) {\n",
6415         "        this.waiting = true;\n",
6416         "        this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n",
6417         "    }\n",
6418         "};\n",
6419         "\n",
6420         "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
6421         "    var format_dropdown = fig.format_dropdown;\n",
6422         "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
6423         "    fig.ondownload(fig, format);\n",
6424         "};\n",
6425         "\n",
6426         "mpl.figure.prototype.handle_resize = function (fig, msg) {\n",
6427         "    var size = msg['size'];\n",
6428         "    if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n",
6429         "        fig._resize_canvas(size[0], size[1], msg['forward']);\n",
6430         "        fig.send_message('refresh', {});\n",
6431         "    }\n",
6432         "};\n",
6433         "\n",
6434         "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n",
6435         "    var x0 = msg['x0'] / fig.ratio;\n",
6436         "    var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n",
6437         "    var x1 = msg['x1'] / fig.ratio;\n",
6438         "    var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n",
6439         "    x0 = Math.floor(x0) + 0.5;\n",
6440         "    y0 = Math.floor(y0) + 0.5;\n",
6441         "    x1 = Math.floor(x1) + 0.5;\n",
6442         "    y1 = Math.floor(y1) + 0.5;\n",
6443         "    var min_x = Math.min(x0, x1);\n",
6444         "    var min_y = Math.min(y0, y1);\n",
6445         "    var width = Math.abs(x1 - x0);\n",
6446         "    var height = Math.abs(y1 - y0);\n",
6447         "\n",
6448         "    fig.rubberband_context.clearRect(\n",
6449         "        0,\n",
6450         "        0,\n",
6451         "        fig.canvas.width / fig.ratio,\n",
6452         "        fig.canvas.height / fig.ratio\n",
6453         "    );\n",
6454         "\n",
6455         "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
6456         "};\n",
6457         "\n",
6458         "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n",
6459         "    // Updates the figure title.\n",
6460         "    fig.header.textContent = msg['label'];\n",
6461         "};\n",
6462         "\n",
6463         "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n",
6464         "    var cursor = msg['cursor'];\n",
6465         "    switch (cursor) {\n",
6466         "        case 0:\n",
6467         "            cursor = 'pointer';\n",
6468         "            break;\n",
6469         "        case 1:\n",
6470         "            cursor = 'default';\n",
6471         "            break;\n",
6472         "        case 2:\n",
6473         "            cursor = 'crosshair';\n",
6474         "            break;\n",
6475         "        case 3:\n",
6476         "            cursor = 'move';\n",
6477         "            break;\n",
6478         "    }\n",
6479         "    fig.rubberband_canvas.style.cursor = cursor;\n",
6480         "};\n",
6481         "\n",
6482         "mpl.figure.prototype.handle_message = function (fig, msg) {\n",
6483         "    fig.message.textContent = msg['message'];\n",
6484         "};\n",
6485         "\n",
6486         "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n",
6487         "    // Request the server to send over a new figure.\n",
6488         "    fig.send_draw_message();\n",
6489         "};\n",
6490         "\n",
6491         "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n",
6492         "    fig.image_mode = msg['mode'];\n",
6493         "};\n",
6494         "\n",
6495         "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n",
6496         "    for (var key in msg) {\n",
6497         "        if (!(key in fig.buttons)) {\n",
6498         "            continue;\n",
6499         "        }\n",
6500         "        fig.buttons[key].disabled = !msg[key];\n",
6501         "        fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n",
6502         "    }\n",
6503         "};\n",
6504         "\n",
6505         "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n",
6506         "    if (msg['mode'] === 'PAN') {\n",
6507         "        fig.buttons['Pan'].classList.add('active');\n",
6508         "        fig.buttons['Zoom'].classList.remove('active');\n",
6509         "    } else if (msg['mode'] === 'ZOOM') {\n",
6510         "        fig.buttons['Pan'].classList.remove('active');\n",
6511         "        fig.buttons['Zoom'].classList.add('active');\n",
6512         "    } else {\n",
6513         "        fig.buttons['Pan'].classList.remove('active');\n",
6514         "        fig.buttons['Zoom'].classList.remove('active');\n",
6515         "    }\n",
6516         "};\n",
6517         "\n",
6518         "mpl.figure.prototype.updated_canvas_event = function () {\n",
6519         "    // Called whenever the canvas gets updated.\n",
6520         "    this.send_message('ack', {});\n",
6521         "};\n",
6522         "\n",
6523         "// A function to construct a web socket function for onmessage handling.\n",
6524         "// Called in the figure constructor.\n",
6525         "mpl.figure.prototype._make_on_message_function = function (fig) {\n",
6526         "    return function socket_on_message(evt) {\n",
6527         "        if (evt.data instanceof Blob) {\n",
6528         "            /* FIXME: We get \"Resource interpreted as Image but\n",
6529         "             * transferred with MIME type text/plain:\" errors on\n",
6530         "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
6531         "             * to be part of the websocket stream */\n",
6532         "            evt.data.type = 'image/png';\n",
6533         "\n",
6534         "            /* Free the memory for the previous frames */\n",
6535         "            if (fig.imageObj.src) {\n",
6536         "                (window.URL || window.webkitURL).revokeObjectURL(\n",
6537         "                    fig.imageObj.src\n",
6538         "                );\n",
6539         "            }\n",
6540         "\n",
6541         "            fig.imageObj.src = (window.URL ||