diff --git a/01-Introduction to Matplotlib.ipynb b/01-Introduction to Matplotlib.ipynb index 566d27f..ca0ae83 100644 --- a/01-Introduction to Matplotlib.ipynb +++ b/01-Introduction to Matplotlib.ipynb @@ -30,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "id": "surgical-forty", "metadata": {}, "outputs": [], @@ -41,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "id": "fifty-consortium", "metadata": {}, "outputs": [], @@ -59,7 +59,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "id": "centered-range", "metadata": {}, "outputs": [], @@ -69,961 +69,13 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 6, "id": "recent-defense", "metadata": {}, "outputs": [ { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n", - " }\n", - " fig.send_message('refresh', {});\n", - " };\n", - "\n", - " this.imageObj.onload = function () {\n", - " if (fig.image_mode === 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function () {\n", - " fig.ws.close();\n", - " };\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "};\n", - "\n", - "mpl.figure.prototype._init_header = function () {\n", - " var titlebar = document.createElement('div');\n", - " titlebar.classList =\n", - " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", - " var titletext = document.createElement('div');\n", - " titletext.classList = 'ui-dialog-title';\n", - " titletext.setAttribute(\n", - " 'style',\n", - " 'width: 100%; text-align: center; padding: 3px;'\n", - " );\n", - " titlebar.appendChild(titletext);\n", - " this.root.appendChild(titlebar);\n", - " this.header = titletext;\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._init_canvas = function () {\n", - " var fig = this;\n", - "\n", - " var canvas_div = (this.canvas_div = document.createElement('div'));\n", - " canvas_div.setAttribute(\n", - " 'style',\n", - " 'border: 1px solid #ddd;' +\n", - " 'box-sizing: content-box;' +\n", - " 'clear: both;' +\n", - " 'min-height: 1px;' +\n", - " 'min-width: 1px;' +\n", - " 'outline: 0;' +\n", - " 'overflow: hidden;' +\n", - " 'position: relative;' +\n", - " 'resize: both;'\n", - " );\n", - "\n", - " function on_keyboard_event_closure(name) {\n", - " return function (event) {\n", - " return fig.key_event(event, name);\n", - " };\n", - " }\n", - "\n", - " canvas_div.addEventListener(\n", - " 'keydown',\n", - " on_keyboard_event_closure('key_press')\n", - " );\n", - " canvas_div.addEventListener(\n", - " 'keyup',\n", - " on_keyboard_event_closure('key_release')\n", - " );\n", - "\n", - " this._canvas_extra_style(canvas_div);\n", - " this.root.appendChild(canvas_div);\n", - "\n", - " var canvas = (this.canvas = document.createElement('canvas'));\n", - " canvas.classList.add('mpl-canvas');\n", - " canvas.setAttribute('style', 'box-sizing: content-box;');\n", - "\n", - " this.context = canvas.getContext('2d');\n", - "\n", - " var backingStore =\n", - " this.context.backingStorePixelRatio ||\n", - " this.context.webkitBackingStorePixelRatio ||\n", - " this.context.mozBackingStorePixelRatio ||\n", - " this.context.msBackingStorePixelRatio ||\n", - " this.context.oBackingStorePixelRatio ||\n", - " this.context.backingStorePixelRatio ||\n", - " 1;\n", - "\n", - " this.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", - " 'canvas'\n", - " ));\n", - " rubberband_canvas.setAttribute(\n", - " 'style',\n", - " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", - " );\n", - "\n", - " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n", - " if (this.ResizeObserver === undefined) {\n", - " if (window.ResizeObserver !== undefined) {\n", - " this.ResizeObserver = window.ResizeObserver;\n", - " } else {\n", - " var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n", - " this.ResizeObserver = obs.ResizeObserver;\n", - " }\n", - " }\n", - "\n", - " this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n", - " var nentries = entries.length;\n", - " for (var i = 0; i < nentries; i++) {\n", - " var entry = entries[i];\n", - " var width, height;\n", - " if (entry.contentBoxSize) {\n", - " if (entry.contentBoxSize instanceof Array) {\n", - " // Chrome 84 implements new version of spec.\n", - " width = entry.contentBoxSize[0].inlineSize;\n", - " height = entry.contentBoxSize[0].blockSize;\n", - " } else {\n", - " // Firefox implements old version of spec.\n", - " width = entry.contentBoxSize.inlineSize;\n", - " height = entry.contentBoxSize.blockSize;\n", - " }\n", - " } else {\n", - " // Chrome <84 implements even older version of spec.\n", - " width = entry.contentRect.width;\n", - " height = entry.contentRect.height;\n", - " }\n", - "\n", - " // Keep the size of the canvas and rubber band canvas in sync with\n", - " // the canvas container.\n", - " if (entry.devicePixelContentBoxSize) {\n", - " // Chrome 84 implements new version of spec.\n", - " canvas.setAttribute(\n", - " 'width',\n", - " entry.devicePixelContentBoxSize[0].inlineSize\n", - " );\n", - " canvas.setAttribute(\n", - " 'height',\n", - " entry.devicePixelContentBoxSize[0].blockSize\n", - " );\n", - " } else {\n", - " canvas.setAttribute('width', width * fig.ratio);\n", - " canvas.setAttribute('height', height * fig.ratio);\n", - " }\n", - " canvas.setAttribute(\n", - " 'style',\n", - " 'width: ' + width + 'px; height: ' + height + 'px;'\n", - " );\n", - "\n", - " rubberband_canvas.setAttribute('width', width);\n", - " rubberband_canvas.setAttribute('height', height);\n", - "\n", - " // And update the size in Python. We ignore the initial 0/0 size\n", - " // that occurs as the element is placed into the DOM, which should\n", - " // otherwise not happen due to the minimum size styling.\n", - " if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n", - " fig.request_resize(width, height);\n", - " }\n", - " }\n", - " });\n", - " this.resizeObserverInstance.observe(canvas_div);\n", - "\n", - " function on_mouse_event_closure(name) {\n", - " return function (event) {\n", - " return fig.mouse_event(event, name);\n", - " };\n", - " }\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mousedown',\n", - " on_mouse_event_closure('button_press')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseup',\n", - " on_mouse_event_closure('button_release')\n", - " );\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband_canvas.addEventListener(\n", - " 'mousemove',\n", - " on_mouse_event_closure('motion_notify')\n", - " );\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseenter',\n", - " on_mouse_event_closure('figure_enter')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseleave',\n", - " on_mouse_event_closure('figure_leave')\n", - " );\n", - "\n", - " canvas_div.addEventListener('wheel', function (event) {\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " on_mouse_event_closure('scroll')(event);\n", - " });\n", - "\n", - " canvas_div.appendChild(canvas);\n", - " canvas_div.appendChild(rubberband_canvas);\n", - "\n", - " this.rubberband_context = rubberband_canvas.getContext('2d');\n", - " this.rubberband_context.strokeStyle = '#000000';\n", - "\n", - " this._resize_canvas = function (width, height, forward) {\n", - " if (forward) {\n", - " canvas_div.style.width = width + 'px';\n", - " canvas_div.style.height = height + 'px';\n", - " }\n", - " };\n", - "\n", - " // Disable right mouse context menu.\n", - " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", - " event.preventDefault();\n", - " return false;\n", - " });\n", - "\n", - " function set_focus() {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'mpl-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " continue;\n", - " }\n", - "\n", - " var button = (fig.buttons[name] = document.createElement('button'));\n", - " button.classList = 'mpl-widget';\n", - " button.setAttribute('role', 'button');\n", - " button.setAttribute('aria-disabled', 'false');\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - "\n", - " var icon_img = document.createElement('img');\n", - " icon_img.src = '_images/' + image + '.png';\n", - " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", - " icon_img.alt = tooltip;\n", - " button.appendChild(icon_img);\n", - "\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " var fmt_picker = document.createElement('select');\n", - " fmt_picker.classList = 'mpl-widget';\n", - " toolbar.appendChild(fmt_picker);\n", - " this.format_dropdown = fmt_picker;\n", - "\n", - " for (var ind in mpl.extensions) {\n", - " var fmt = mpl.extensions[ind];\n", - " var option = document.createElement('option');\n", - " option.selected = fmt === mpl.default_extension;\n", - " option.innerHTML = fmt;\n", - " fmt_picker.appendChild(option);\n", - " }\n", - "\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "};\n", - "\n", - "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", - " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", - " // which will in turn request a refresh of the image.\n", - " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", - "};\n", - "\n", - "mpl.figure.prototype.send_message = function (type, properties) {\n", - " properties['type'] = type;\n", - " properties['figure_id'] = this.id;\n", - " this.ws.send(JSON.stringify(properties));\n", - "};\n", - "\n", - "mpl.figure.prototype.send_draw_message = function () {\n", - " if (!this.waiting) {\n", - " this.waiting = true;\n", - " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " var format_dropdown = fig.format_dropdown;\n", - " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", - " fig.ondownload(fig, format);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", - " var size = msg['size'];\n", - " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", - " fig._resize_canvas(size[0], size[1], msg['forward']);\n", - " fig.send_message('refresh', {});\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", - " var x0 = msg['x0'] / fig.ratio;\n", - " var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n", - " var x1 = msg['x1'] / fig.ratio;\n", - " var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n", - " x0 = Math.floor(x0) + 0.5;\n", - " y0 = Math.floor(y0) + 0.5;\n", - " x1 = Math.floor(x1) + 0.5;\n", - " y1 = Math.floor(y1) + 0.5;\n", - " var min_x = Math.min(x0, x1);\n", - " var min_y = Math.min(y0, y1);\n", - " var width = Math.abs(x1 - x0);\n", - " var height = Math.abs(y1 - y0);\n", - "\n", - " fig.rubberband_context.clearRect(\n", - " 0,\n", - " 0,\n", - " fig.canvas.width / fig.ratio,\n", - " fig.canvas.height / fig.ratio\n", - " );\n", - "\n", - " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", - " // Updates the figure title.\n", - " fig.header.textContent = msg['label'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", - " var cursor = msg['cursor'];\n", - " switch (cursor) {\n", - " case 0:\n", - " cursor = 'pointer';\n", - " break;\n", - " case 1:\n", - " cursor = 'default';\n", - " break;\n", - " case 2:\n", - " cursor = 'crosshair';\n", - " break;\n", - " case 3:\n", - " cursor = 'move';\n", - " break;\n", - " }\n", - " fig.rubberband_canvas.style.cursor = cursor;\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_message = function (fig, msg) {\n", - " fig.message.textContent = msg['message'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", - " // Request the server to send over a new figure.\n", - " fig.send_draw_message();\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", - " fig.image_mode = msg['mode'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", - " for (var key in msg) {\n", - " if (!(key in fig.buttons)) {\n", - " continue;\n", - " }\n", - " fig.buttons[key].disabled = !msg[key];\n", - " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", - " if (msg['mode'] === 'PAN') {\n", - " fig.buttons['Pan'].classList.add('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " } else if (msg['mode'] === 'ZOOM') {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.add('active');\n", - " } else {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Called whenever the canvas gets updated.\n", - " this.send_message('ack', {});\n", - "};\n", - "\n", - "// A function to construct a web socket function for onmessage handling.\n", - "// Called in the figure constructor.\n", - "mpl.figure.prototype._make_on_message_function = function (fig) {\n", - " return function socket_on_message(evt) {\n", - " if (evt.data instanceof Blob) {\n", - " /* FIXME: We get \"Resource interpreted as Image but\n", - " * transferred with MIME type text/plain:\" errors on\n", - " * Chrome. But how to set the MIME type? It doesn't seem\n", - " * to be part of the websocket stream */\n", - " evt.data.type = 'image/png';\n", - "\n", - " /* Free the memory for the previous frames */\n", - " if (fig.imageObj.src) {\n", - " (window.URL || window.webkitURL).revokeObjectURL(\n", - " fig.imageObj.src\n", - " );\n", - " }\n", - "\n", - " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", - " evt.data\n", - " );\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " } else if (\n", - " typeof evt.data === 'string' &&\n", - " evt.data.slice(0, 21) === 'data:image/png;base64'\n", - " ) {\n", - " fig.imageObj.src = evt.data;\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " }\n", - "\n", - " var msg = JSON.parse(evt.data);\n", - " var msg_type = msg['type'];\n", - "\n", - " // Call the \"handle_{type}\" callback, which takes\n", - " // the figure and JSON message as its only arguments.\n", - " try {\n", - " var callback = fig['handle_' + msg_type];\n", - " } catch (e) {\n", - " console.log(\n", - " \"No handler for the '\" + msg_type + \"' message type: \",\n", - " msg\n", - " );\n", - " return;\n", - " }\n", - "\n", - " if (callback) {\n", - " try {\n", - " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", - " callback(fig, msg);\n", - " } catch (e) {\n", - " console.log(\n", - " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", - " e,\n", - " e.stack,\n", - " msg\n", - " );\n", - " }\n", - " }\n", - " };\n", - "};\n", - "\n", - "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", - "mpl.findpos = function (e) {\n", - " //this section is from http://www.quirksmode.org/js/events_properties.html\n", - " var targ;\n", - " if (!e) {\n", - " e = window.event;\n", - " }\n", - " if (e.target) {\n", - " targ = e.target;\n", - " } else if (e.srcElement) {\n", - " targ = e.srcElement;\n", - " }\n", - " if (targ.nodeType === 3) {\n", - " // defeat Safari bug\n", - " targ = targ.parentNode;\n", - " }\n", - "\n", - " // pageX,Y are the mouse positions relative to the document\n", - " var boundingRect = targ.getBoundingClientRect();\n", - " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", - " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", - "\n", - " return { x: x, y: y };\n", - "};\n", - "\n", - "/*\n", - " * return a copy of an object with only non-object keys\n", - " * we need this to avoid circular references\n", - " * http://stackoverflow.com/a/24161582/3208463\n", - " */\n", - "function simpleKeys(original) {\n", - " return Object.keys(original).reduce(function (obj, key) {\n", - " if (typeof original[key] !== 'object') {\n", - " obj[key] = original[key];\n", - " }\n", - " return obj;\n", - " }, {});\n", - "}\n", - "\n", - "mpl.figure.prototype.mouse_event = function (event, name) {\n", - " var canvas_pos = mpl.findpos(event);\n", - "\n", - " if (name === 'button_press') {\n", - " this.canvas.focus();\n", - " this.canvas_div.focus();\n", - " }\n", - "\n", - " var x = canvas_pos.x * this.ratio;\n", - " var y = canvas_pos.y * this.ratio;\n", - "\n", - " this.send_message(name, {\n", - " x: x,\n", - " y: y,\n", - " button: event.button,\n", - " step: event.step,\n", - " guiEvent: simpleKeys(event),\n", - " });\n", - "\n", - " /* This prevents the web browser from automatically changing to\n", - " * the text insertion cursor when the button is pressed. We want\n", - " * to control all of the cursor setting manually through the\n", - " * 'cursor' event from matplotlib */\n", - " event.preventDefault();\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", - " // Handle any extra behaviour associated with a key event\n", - "};\n", - "\n", - "mpl.figure.prototype.key_event = function (event, name) {\n", - " // Prevent repeat events\n", - " if (name === 'key_press') {\n", - " if (event.which === this._key) {\n", - " return;\n", - " } else {\n", - " this._key = event.which;\n", - " }\n", - " }\n", - " if (name === 'key_release') {\n", - " this._key = null;\n", - " }\n", - "\n", - " var value = '';\n", - " if (event.ctrlKey && event.which !== 17) {\n", - " value += 'ctrl+';\n", - " }\n", - " if (event.altKey && event.which !== 18) {\n", - " value += 'alt+';\n", - " }\n", - " if (event.shiftKey && event.which !== 16) {\n", - " value += 'shift+';\n", - " }\n", - "\n", - " value += 'k';\n", - " value += event.which.toString();\n", - "\n", - " this._key_event_extra(event, name);\n", - "\n", - " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", - " if (name === 'download') {\n", - " this.handle_save(this, null);\n", - " } else {\n", - " this.send_message('toolbar_button', { name: name });\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", - " this.message.textContent = tooltip;\n", - "};\n", - "\n", - "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n", - "// prettier-ignore\n", - "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", - "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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", - "\n", - "mpl.default_extension = \"png\";/* global mpl */\n", - "\n", - "var comm_websocket_adapter = function (comm) {\n", - " // Create a \"websocket\"-like object which calls the given IPython comm\n", - " // object with the appropriate methods. Currently this is a non binary\n", - " // socket, so there is still some room for performance tuning.\n", - " var ws = {};\n", - "\n", - " ws.close = function () {\n", - " comm.close();\n", - " };\n", - " ws.send = function (m) {\n", - " //console.log('sending', m);\n", - " comm.send(m);\n", - " };\n", - " // Register the callback with on_msg.\n", - " comm.on_msg(function (msg) {\n", - " //console.log('receiving', msg['content']['data'], msg);\n", - " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", - " ws.onmessage(msg['content']['data']);\n", - " });\n", - " return ws;\n", - "};\n", - "\n", - "mpl.mpl_figure_comm = function (comm, msg) {\n", - " // This is the function which gets called when the mpl process\n", - " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", - "\n", - " var id = msg.content.data.id;\n", - " // Get hold of the div created by the display call when the Comm\n", - " // socket was opened in Python.\n", - " var element = document.getElementById(id);\n", - " var ws_proxy = comm_websocket_adapter(comm);\n", - "\n", - " function ondownload(figure, _format) {\n", - " window.open(figure.canvas.toDataURL());\n", - " }\n", - "\n", - " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", - "\n", - " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", - " // web socket which is closed, not our websocket->open comm proxy.\n", - " ws_proxy.onopen();\n", - "\n", - " fig.parent_element = element;\n", - " fig.cell_info = mpl.find_output_cell(\"
\");\n", - " if (!fig.cell_info) {\n", - " console.error('Failed to find cell for figure', id, fig);\n", - " return;\n", - " }\n", - " fig.cell_info[0].output_area.element.on(\n", - " 'cleared',\n", - " { fig: fig },\n", - " fig._remove_fig_handler\n", - " );\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_close = function (fig, msg) {\n", - " var width = fig.canvas.width / fig.ratio;\n", - " fig.cell_info[0].output_area.element.off(\n", - " 'cleared',\n", - " fig._remove_fig_handler\n", - " );\n", - " fig.resizeObserverInstance.unobserve(fig.canvas_div);\n", - "\n", - " // Update the output cell to use the data from the current canvas.\n", - " fig.push_to_output();\n", - " var dataURL = fig.canvas.toDataURL();\n", - " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", - " // the notebook keyboard shortcuts fail.\n", - " IPython.keyboard_manager.enable();\n", - " fig.parent_element.innerHTML =\n", - " '';\n", - " fig.close_ws(fig, msg);\n", - "};\n", - "\n", - "mpl.figure.prototype.close_ws = function (fig, msg) {\n", - " fig.send_message('closing', msg);\n", - " // fig.ws.close()\n", - "};\n", - "\n", - "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", - " // Turn the data on the canvas into data in the output cell.\n", - " var width = this.canvas.width / this.ratio;\n", - " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] =\n", - " '';\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Tell IPython that the notebook contents must change.\n", - " IPython.notebook.set_dirty(true);\n", - " this.send_message('ack', {});\n", - " var fig = this;\n", - " // Wait a second, then push the new image to the DOM so\n", - " // that it is saved nicely (might be nice to debounce this).\n", - " setTimeout(function () {\n", - " fig.push_to_output();\n", - " }, 1000);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'btn-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " var button;\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " continue;\n", - " }\n", - "\n", - " button = fig.buttons[name] = document.createElement('button');\n", - " button.classList = 'btn btn-default';\n", - " button.href = '#';\n", - " button.title = name;\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message pull-right';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = document.createElement('div');\n", - " buttongrp.classList = 'btn-group inline pull-right';\n", - " button = document.createElement('button');\n", - " button.classList = 'btn btn-mini btn-primary';\n", - " button.href = '#';\n", - " button.title = 'Stop Interaction';\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', function (_evt) {\n", - " fig.handle_close(fig, {});\n", - " });\n", - " button.addEventListener(\n", - " 'mouseover',\n", - " on_mouseover_closure('Stop Interaction')\n", - " );\n", - " buttongrp.appendChild(button);\n", - " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", - " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", - "};\n", - "\n", - "mpl.figure.prototype._remove_fig_handler = function (event) {\n", - " var fig = event.data.fig;\n", - " if (event.target !== this) {\n", - " // Ignore bubbled events from children.\n", - " return;\n", - " }\n", - " fig.close_ws(fig, {});\n", - "};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (el) {\n", - " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (el) {\n", - " // this is important to make the div 'focusable\n", - " el.setAttribute('tabindex', 0);\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " } else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager) {\n", - " manager = IPython.keyboard_manager;\n", - " }\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which === 13) {\n", - " this.canvas_div.blur();\n", - " // select the cell after this one\n", - " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", - " IPython.notebook.select(index + 1);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " fig.ondownload(fig, null);\n", - "};\n", - "\n", - "mpl.find_output_cell = function (html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i = 0; i < ncells; i++) {\n", - " var cell = cells[i];\n", - " if (cell.cell_type === 'code') {\n", - " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", - " var data = cell.output_area.outputs[j];\n", - " if (data.data) {\n", - " // IPython >= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] === html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "};\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel !== null) {\n", - " IPython.notebook.kernel.comm_manager.register_target(\n", - " 'matplotlib',\n", - " mpl.mpl_figure_comm\n", - " );\n", - "}\n" - ], + "application/javascript": "/* Put everything inside the global mpl namespace */\n/* global mpl */\nwindow.mpl = {};\n\nmpl.get_websocket_type = function () {\n if (typeof WebSocket !== 'undefined') {\n return WebSocket;\n } else if (typeof MozWebSocket !== 'undefined') {\n return MozWebSocket;\n } else {\n alert(\n 'Your browser does not have WebSocket support. ' +\n 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n 'Firefox 4 and 5 are also supported but you ' +\n 'have to enable WebSockets in about:config.'\n );\n }\n};\n\nmpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n this.id = figure_id;\n\n this.ws = websocket;\n\n this.supports_binary = this.ws.binaryType !== undefined;\n\n if (!this.supports_binary) {\n var warnings = document.getElementById('mpl-warnings');\n if (warnings) {\n warnings.style.display = 'block';\n warnings.textContent =\n 'This browser does not support binary websocket messages. ' +\n 'Performance may be slow.';\n }\n }\n\n this.imageObj = new Image();\n\n this.context = undefined;\n this.message = undefined;\n this.canvas = undefined;\n this.rubberband_canvas = undefined;\n this.rubberband_context = undefined;\n this.format_dropdown = undefined;\n\n this.image_mode = 'full';\n\n this.root = document.createElement('div');\n this.root.setAttribute('style', 'display: inline-block');\n this._root_extra_style(this.root);\n\n parent_element.appendChild(this.root);\n\n this._init_header(this);\n this._init_canvas(this);\n this._init_toolbar(this);\n\n var fig = this;\n\n this.waiting = false;\n\n this.ws.onopen = function () {\n fig.send_message('supports_binary', { value: fig.supports_binary });\n fig.send_message('send_image_mode', {});\n if (fig.ratio !== 1) {\n fig.send_message('set_device_pixel_ratio', {\n device_pixel_ratio: fig.ratio,\n });\n }\n fig.send_message('refresh', {});\n };\n\n this.imageObj.onload = function () {\n if (fig.image_mode === 'full') {\n // Full images could contain transparency (where diff images\n // almost always do), so we need to clear the canvas so that\n // there is no ghosting.\n fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n }\n fig.context.drawImage(fig.imageObj, 0, 0);\n };\n\n this.imageObj.onunload = function () {\n fig.ws.close();\n };\n\n this.ws.onmessage = this._make_on_message_function(this);\n\n this.ondownload = ondownload;\n};\n\nmpl.figure.prototype._init_header = function () {\n var titlebar = document.createElement('div');\n titlebar.classList =\n 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n var titletext = document.createElement('div');\n titletext.classList = 'ui-dialog-title';\n titletext.setAttribute(\n 'style',\n 'width: 100%; text-align: center; padding: 3px;'\n );\n titlebar.appendChild(titletext);\n this.root.appendChild(titlebar);\n this.header = titletext;\n};\n\nmpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._init_canvas = function () {\n var fig = this;\n\n var canvas_div = (this.canvas_div = document.createElement('div'));\n canvas_div.setAttribute('tabindex', '0');\n canvas_div.setAttribute(\n 'style',\n 'border: 1px solid #ddd;' +\n 'box-sizing: content-box;' +\n 'clear: both;' +\n 'min-height: 1px;' +\n 'min-width: 1px;' +\n 'outline: 0;' +\n 'overflow: hidden;' +\n 'position: relative;' +\n 'resize: both;' +\n 'z-index: 2;'\n );\n\n function on_keyboard_event_closure(name) {\n return function (event) {\n return fig.key_event(event, name);\n };\n }\n\n canvas_div.addEventListener(\n 'keydown',\n on_keyboard_event_closure('key_press')\n );\n canvas_div.addEventListener(\n 'keyup',\n on_keyboard_event_closure('key_release')\n );\n\n this._canvas_extra_style(canvas_div);\n this.root.appendChild(canvas_div);\n\n var canvas = (this.canvas = document.createElement('canvas'));\n canvas.classList.add('mpl-canvas');\n canvas.setAttribute(\n 'style',\n 'box-sizing: content-box;' +\n 'pointer-events: none;' +\n 'position: relative;' +\n 'z-index: 0;'\n );\n\n this.context = canvas.getContext('2d');\n\n var backingStore =\n this.context.backingStorePixelRatio ||\n this.context.webkitBackingStorePixelRatio ||\n this.context.mozBackingStorePixelRatio ||\n this.context.msBackingStorePixelRatio ||\n this.context.oBackingStorePixelRatio ||\n this.context.backingStorePixelRatio ||\n 1;\n\n this.ratio = (window.devicePixelRatio || 1) / backingStore;\n\n var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n 'canvas'\n ));\n rubberband_canvas.setAttribute(\n 'style',\n 'box-sizing: content-box;' +\n 'left: 0;' +\n 'pointer-events: none;' +\n 'position: absolute;' +\n 'top: 0;' +\n 'z-index: 1;'\n );\n\n // Apply a ponyfill if ResizeObserver is not implemented by browser.\n if (this.ResizeObserver === undefined) {\n if (window.ResizeObserver !== undefined) {\n this.ResizeObserver = window.ResizeObserver;\n } else {\n var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n this.ResizeObserver = obs.ResizeObserver;\n }\n }\n\n this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n var nentries = entries.length;\n for (var i = 0; i < nentries; i++) {\n var entry = entries[i];\n var width, height;\n if (entry.contentBoxSize) {\n if (entry.contentBoxSize instanceof Array) {\n // Chrome 84 implements new version of spec.\n width = entry.contentBoxSize[0].inlineSize;\n height = entry.contentBoxSize[0].blockSize;\n } else {\n // Firefox implements old version of spec.\n width = entry.contentBoxSize.inlineSize;\n height = entry.contentBoxSize.blockSize;\n }\n } else {\n // Chrome <84 implements even older version of spec.\n width = entry.contentRect.width;\n height = entry.contentRect.height;\n }\n\n // Keep the size of the canvas and rubber band canvas in sync with\n // the canvas container.\n if (entry.devicePixelContentBoxSize) {\n // Chrome 84 implements new version of spec.\n canvas.setAttribute(\n 'width',\n entry.devicePixelContentBoxSize[0].inlineSize\n );\n canvas.setAttribute(\n 'height',\n entry.devicePixelContentBoxSize[0].blockSize\n );\n } else {\n canvas.setAttribute('width', width * fig.ratio);\n canvas.setAttribute('height', height * fig.ratio);\n }\n /* This rescales the canvas back to display pixels, so that it\n * appears correct on HiDPI screens. */\n canvas.style.width = width + 'px';\n canvas.style.height = height + 'px';\n\n rubberband_canvas.setAttribute('width', width);\n rubberband_canvas.setAttribute('height', height);\n\n // And update the size in Python. We ignore the initial 0/0 size\n // that occurs as the element is placed into the DOM, which should\n // otherwise not happen due to the minimum size styling.\n if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n fig.request_resize(width, height);\n }\n }\n });\n this.resizeObserverInstance.observe(canvas_div);\n\n function on_mouse_event_closure(name) {\n /* User Agent sniffing is bad, but WebKit is busted:\n * https://bugs.webkit.org/show_bug.cgi?id=144526\n * https://bugs.webkit.org/show_bug.cgi?id=181818\n * The worst that happens here is that they get an extra browser\n * selection when dragging, if this check fails to catch them.\n */\n var UA = navigator.userAgent;\n var isWebKit = /AppleWebKit/.test(UA) && !/Chrome/.test(UA);\n if(isWebKit) {\n return function (event) {\n /* This prevents the web browser from automatically changing to\n * the text insertion cursor when the button is pressed. We\n * want to control all of the cursor setting manually through\n * the 'cursor' event from matplotlib */\n event.preventDefault()\n return fig.mouse_event(event, name);\n };\n } else {\n return function (event) {\n return fig.mouse_event(event, name);\n };\n }\n }\n\n canvas_div.addEventListener(\n 'mousedown',\n on_mouse_event_closure('button_press')\n );\n canvas_div.addEventListener(\n 'mouseup',\n on_mouse_event_closure('button_release')\n );\n canvas_div.addEventListener(\n 'dblclick',\n on_mouse_event_closure('dblclick')\n );\n // Throttle sequential mouse events to 1 every 20ms.\n canvas_div.addEventListener(\n 'mousemove',\n on_mouse_event_closure('motion_notify')\n );\n\n canvas_div.addEventListener(\n 'mouseenter',\n on_mouse_event_closure('figure_enter')\n );\n canvas_div.addEventListener(\n 'mouseleave',\n on_mouse_event_closure('figure_leave')\n );\n\n canvas_div.addEventListener('wheel', function (event) {\n if (event.deltaY < 0) {\n event.step = 1;\n } else {\n event.step = -1;\n }\n on_mouse_event_closure('scroll')(event);\n });\n\n canvas_div.appendChild(canvas);\n canvas_div.appendChild(rubberband_canvas);\n\n this.rubberband_context = rubberband_canvas.getContext('2d');\n this.rubberband_context.strokeStyle = '#000000';\n\n this._resize_canvas = function (width, height, forward) {\n if (forward) {\n canvas_div.style.width = width + 'px';\n canvas_div.style.height = height + 'px';\n }\n };\n\n // Disable right mouse context menu.\n canvas_div.addEventListener('contextmenu', function (_e) {\n event.preventDefault();\n return false;\n });\n\n function set_focus() {\n canvas.focus();\n canvas_div.focus();\n }\n\n window.setTimeout(set_focus, 100);\n};\n\nmpl.figure.prototype._init_toolbar = function () {\n var fig = this;\n\n var toolbar = document.createElement('div');\n toolbar.classList = 'mpl-toolbar';\n this.root.appendChild(toolbar);\n\n function on_click_closure(name) {\n return function (_event) {\n return fig.toolbar_button_onclick(name);\n };\n }\n\n function on_mouseover_closure(tooltip) {\n return function (event) {\n if (!event.currentTarget.disabled) {\n return fig.toolbar_button_onmouseover(tooltip);\n }\n };\n }\n\n fig.buttons = {};\n var buttonGroup = document.createElement('div');\n buttonGroup.classList = 'mpl-button-group';\n for (var toolbar_ind in mpl.toolbar_items) {\n var name = mpl.toolbar_items[toolbar_ind][0];\n var tooltip = mpl.toolbar_items[toolbar_ind][1];\n var image = mpl.toolbar_items[toolbar_ind][2];\n var method_name = mpl.toolbar_items[toolbar_ind][3];\n\n if (!name) {\n /* Instead of a spacer, we start a new button group. */\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n buttonGroup = document.createElement('div');\n buttonGroup.classList = 'mpl-button-group';\n continue;\n }\n\n var button = (fig.buttons[name] = document.createElement('button'));\n button.classList = 'mpl-widget';\n button.setAttribute('role', 'button');\n button.setAttribute('aria-disabled', 'false');\n button.addEventListener('click', on_click_closure(method_name));\n button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n\n var icon_img = document.createElement('img');\n icon_img.src = '_images/' + image + '.png';\n icon_img.srcset = '_images/' + image + '_large.png 2x';\n icon_img.alt = tooltip;\n button.appendChild(icon_img);\n\n buttonGroup.appendChild(button);\n }\n\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n\n var fmt_picker = document.createElement('select');\n fmt_picker.classList = 'mpl-widget';\n toolbar.appendChild(fmt_picker);\n this.format_dropdown = fmt_picker;\n\n for (var ind in mpl.extensions) {\n var fmt = mpl.extensions[ind];\n var option = document.createElement('option');\n option.selected = fmt === mpl.default_extension;\n option.innerHTML = fmt;\n fmt_picker.appendChild(option);\n }\n\n var status_bar = document.createElement('span');\n status_bar.classList = 'mpl-message';\n toolbar.appendChild(status_bar);\n this.message = status_bar;\n};\n\nmpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n // which will in turn request a refresh of the image.\n this.send_message('resize', { width: x_pixels, height: y_pixels });\n};\n\nmpl.figure.prototype.send_message = function (type, properties) {\n properties['type'] = type;\n properties['figure_id'] = this.id;\n this.ws.send(JSON.stringify(properties));\n};\n\nmpl.figure.prototype.send_draw_message = function () {\n if (!this.waiting) {\n this.waiting = true;\n this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n }\n};\n\nmpl.figure.prototype.handle_save = function (fig, _msg) {\n var format_dropdown = fig.format_dropdown;\n var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n fig.ondownload(fig, format);\n};\n\nmpl.figure.prototype.handle_resize = function (fig, msg) {\n var size = msg['size'];\n if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n fig._resize_canvas(size[0], size[1], msg['forward']);\n fig.send_message('refresh', {});\n }\n};\n\nmpl.figure.prototype.handle_rubberband = function (fig, msg) {\n var x0 = msg['x0'] / fig.ratio;\n var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n var x1 = msg['x1'] / fig.ratio;\n var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n x0 = Math.floor(x0) + 0.5;\n y0 = Math.floor(y0) + 0.5;\n x1 = Math.floor(x1) + 0.5;\n y1 = Math.floor(y1) + 0.5;\n var min_x = Math.min(x0, x1);\n var min_y = Math.min(y0, y1);\n var width = Math.abs(x1 - x0);\n var height = Math.abs(y1 - y0);\n\n fig.rubberband_context.clearRect(\n 0,\n 0,\n fig.canvas.width / fig.ratio,\n fig.canvas.height / fig.ratio\n );\n\n fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n};\n\nmpl.figure.prototype.handle_figure_label = function (fig, msg) {\n // Updates the figure title.\n fig.header.textContent = msg['label'];\n};\n\nmpl.figure.prototype.handle_cursor = function (fig, msg) {\n fig.canvas_div.style.cursor = msg['cursor'];\n};\n\nmpl.figure.prototype.handle_message = function (fig, msg) {\n fig.message.textContent = msg['message'];\n};\n\nmpl.figure.prototype.handle_draw = function (fig, _msg) {\n // Request the server to send over a new figure.\n fig.send_draw_message();\n};\n\nmpl.figure.prototype.handle_image_mode = function (fig, msg) {\n fig.image_mode = msg['mode'];\n};\n\nmpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n for (var key in msg) {\n if (!(key in fig.buttons)) {\n continue;\n }\n fig.buttons[key].disabled = !msg[key];\n fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n }\n};\n\nmpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n if (msg['mode'] === 'PAN') {\n fig.buttons['Pan'].classList.add('active');\n fig.buttons['Zoom'].classList.remove('active');\n } else if (msg['mode'] === 'ZOOM') {\n fig.buttons['Pan'].classList.remove('active');\n fig.buttons['Zoom'].classList.add('active');\n } else {\n fig.buttons['Pan'].classList.remove('active');\n fig.buttons['Zoom'].classList.remove('active');\n }\n};\n\nmpl.figure.prototype.updated_canvas_event = function () {\n // Called whenever the canvas gets updated.\n this.send_message('ack', {});\n};\n\n// A function to construct a web socket function for onmessage handling.\n// Called in the figure constructor.\nmpl.figure.prototype._make_on_message_function = function (fig) {\n return function socket_on_message(evt) {\n if (evt.data instanceof Blob) {\n var img = evt.data;\n if (img.type !== 'image/png') {\n /* FIXME: We get \"Resource interpreted as Image but\n * transferred with MIME type text/plain:\" errors on\n * Chrome. But how to set the MIME type? It doesn't seem\n * to be part of the websocket stream */\n img.type = 'image/png';\n }\n\n /* Free the memory for the previous frames */\n if (fig.imageObj.src) {\n (window.URL || window.webkitURL).revokeObjectURL(\n fig.imageObj.src\n );\n }\n\n fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n img\n );\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n } else if (\n typeof evt.data === 'string' &&\n evt.data.slice(0, 21) === 'data:image/png;base64'\n ) {\n fig.imageObj.src = evt.data;\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n }\n\n var msg = JSON.parse(evt.data);\n var msg_type = msg['type'];\n\n // Call the \"handle_{type}\" callback, which takes\n // the figure and JSON message as its only arguments.\n try {\n var callback = fig['handle_' + msg_type];\n } catch (e) {\n console.log(\n \"No handler for the '\" + msg_type + \"' message type: \",\n msg\n );\n return;\n }\n\n if (callback) {\n try {\n // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n callback(fig, msg);\n } catch (e) {\n console.log(\n \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n e,\n e.stack,\n msg\n );\n }\n }\n };\n};\n\nfunction getModifiers(event) {\n var mods = [];\n if (event.ctrlKey) {\n mods.push('ctrl');\n }\n if (event.altKey) {\n mods.push('alt');\n }\n if (event.shiftKey) {\n mods.push('shift');\n }\n if (event.metaKey) {\n mods.push('meta');\n }\n return mods;\n}\n\n/*\n * return a copy of an object with only non-object keys\n * we need this to avoid circular references\n * https://stackoverflow.com/a/24161582/3208463\n */\nfunction simpleKeys(original) {\n return Object.keys(original).reduce(function (obj, key) {\n if (typeof original[key] !== 'object') {\n obj[key] = original[key];\n }\n return obj;\n }, {});\n}\n\nmpl.figure.prototype.mouse_event = function (event, name) {\n if (name === 'button_press') {\n this.canvas.focus();\n this.canvas_div.focus();\n }\n\n // from https://stackoverflow.com/q/1114465\n var boundingRect = this.canvas.getBoundingClientRect();\n var x = (event.clientX - boundingRect.left) * this.ratio;\n var y = (event.clientY - boundingRect.top) * this.ratio;\n\n this.send_message(name, {\n x: x,\n y: y,\n button: event.button,\n step: event.step,\n modifiers: getModifiers(event),\n guiEvent: simpleKeys(event),\n });\n\n return false;\n};\n\nmpl.figure.prototype._key_event_extra = function (_event, _name) {\n // Handle any extra behaviour associated with a key event\n};\n\nmpl.figure.prototype.key_event = function (event, name) {\n // Prevent repeat events\n if (name === 'key_press') {\n if (event.key === this._key) {\n return;\n } else {\n this._key = event.key;\n }\n }\n if (name === 'key_release') {\n this._key = null;\n }\n\n var value = '';\n if (event.ctrlKey && event.key !== 'Control') {\n value += 'ctrl+';\n }\n else if (event.altKey && event.key !== 'Alt') {\n value += 'alt+';\n }\n else if (event.shiftKey && event.key !== 'Shift') {\n value += 'shift+';\n }\n\n value += 'k' + event.key;\n\n this._key_event_extra(event, name);\n\n this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n return false;\n};\n\nmpl.figure.prototype.toolbar_button_onclick = function (name) {\n if (name === 'download') {\n this.handle_save(this, null);\n } else {\n this.send_message('toolbar_button', { name: name });\n }\n};\n\nmpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n this.message.textContent = tooltip;\n};\n\n///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n// prettier-ignore\nvar _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\nmpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o\", \"download\"]];\n\nmpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\n\nmpl.default_extension = \"png\";/* global mpl */\n\nvar comm_websocket_adapter = function (comm) {\n // Create a \"websocket\"-like object which calls the given IPython comm\n // object with the appropriate methods. Currently this is a non binary\n // socket, so there is still some room for performance tuning.\n var ws = {};\n\n ws.binaryType = comm.kernel.ws.binaryType;\n ws.readyState = comm.kernel.ws.readyState;\n function updateReadyState(_event) {\n if (comm.kernel.ws) {\n ws.readyState = comm.kernel.ws.readyState;\n } else {\n ws.readyState = 3; // Closed state.\n }\n }\n comm.kernel.ws.addEventListener('open', updateReadyState);\n comm.kernel.ws.addEventListener('close', updateReadyState);\n comm.kernel.ws.addEventListener('error', updateReadyState);\n\n ws.close = function () {\n comm.close();\n };\n ws.send = function (m) {\n //console.log('sending', m);\n comm.send(m);\n };\n // Register the callback with on_msg.\n comm.on_msg(function (msg) {\n //console.log('receiving', msg['content']['data'], msg);\n var data = msg['content']['data'];\n if (data['blob'] !== undefined) {\n data = {\n data: new Blob(msg['buffers'], { type: data['blob'] }),\n };\n }\n // Pass the mpl event to the overridden (by mpl) onmessage function.\n ws.onmessage(data);\n });\n return ws;\n};\n\nmpl.mpl_figure_comm = function (comm, msg) {\n // This is the function which gets called when the mpl process\n // starts-up an IPython Comm through the \"matplotlib\" channel.\n\n var id = msg.content.data.id;\n // Get hold of the div created by the display call when the Comm\n // socket was opened in Python.\n var element = document.getElementById(id);\n var ws_proxy = comm_websocket_adapter(comm);\n\n function ondownload(figure, _format) {\n window.open(figure.canvas.toDataURL());\n }\n\n var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n\n // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n // web socket which is closed, not our websocket->open comm proxy.\n ws_proxy.onopen();\n\n fig.parent_element = element;\n fig.cell_info = mpl.find_output_cell(\"
\");\n if (!fig.cell_info) {\n console.error('Failed to find cell for figure', id, fig);\n return;\n }\n fig.cell_info[0].output_area.element.on(\n 'cleared',\n { fig: fig },\n fig._remove_fig_handler\n );\n};\n\nmpl.figure.prototype.handle_close = function (fig, msg) {\n var width = fig.canvas.width / fig.ratio;\n fig.cell_info[0].output_area.element.off(\n 'cleared',\n fig._remove_fig_handler\n );\n fig.resizeObserverInstance.unobserve(fig.canvas_div);\n\n // Update the output cell to use the data from the current canvas.\n fig.push_to_output();\n var dataURL = fig.canvas.toDataURL();\n // Re-enable the keyboard manager in IPython - without this line, in FF,\n // the notebook keyboard shortcuts fail.\n IPython.keyboard_manager.enable();\n fig.parent_element.innerHTML =\n '';\n fig.close_ws(fig, msg);\n};\n\nmpl.figure.prototype.close_ws = function (fig, msg) {\n fig.send_message('closing', msg);\n // fig.ws.close()\n};\n\nmpl.figure.prototype.push_to_output = function (_remove_interactive) {\n // Turn the data on the canvas into data in the output cell.\n var width = this.canvas.width / this.ratio;\n var dataURL = this.canvas.toDataURL();\n this.cell_info[1]['text/html'] =\n '';\n};\n\nmpl.figure.prototype.updated_canvas_event = function () {\n // Tell IPython that the notebook contents must change.\n IPython.notebook.set_dirty(true);\n this.send_message('ack', {});\n var fig = this;\n // Wait a second, then push the new image to the DOM so\n // that it is saved nicely (might be nice to debounce this).\n setTimeout(function () {\n fig.push_to_output();\n }, 1000);\n};\n\nmpl.figure.prototype._init_toolbar = function () {\n var fig = this;\n\n var toolbar = document.createElement('div');\n toolbar.classList = 'btn-toolbar';\n this.root.appendChild(toolbar);\n\n function on_click_closure(name) {\n return function (_event) {\n return fig.toolbar_button_onclick(name);\n };\n }\n\n function on_mouseover_closure(tooltip) {\n return function (event) {\n if (!event.currentTarget.disabled) {\n return fig.toolbar_button_onmouseover(tooltip);\n }\n };\n }\n\n fig.buttons = {};\n var buttonGroup = document.createElement('div');\n buttonGroup.classList = 'btn-group';\n var button;\n for (var toolbar_ind in mpl.toolbar_items) {\n var name = mpl.toolbar_items[toolbar_ind][0];\n var tooltip = mpl.toolbar_items[toolbar_ind][1];\n var image = mpl.toolbar_items[toolbar_ind][2];\n var method_name = mpl.toolbar_items[toolbar_ind][3];\n\n if (!name) {\n /* Instead of a spacer, we start a new button group. */\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n buttonGroup = document.createElement('div');\n buttonGroup.classList = 'btn-group';\n continue;\n }\n\n button = fig.buttons[name] = document.createElement('button');\n button.classList = 'btn btn-default';\n button.href = '#';\n button.title = name;\n button.innerHTML = '';\n button.addEventListener('click', on_click_closure(method_name));\n button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n buttonGroup.appendChild(button);\n }\n\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n\n // Add the status bar.\n var status_bar = document.createElement('span');\n status_bar.classList = 'mpl-message pull-right';\n toolbar.appendChild(status_bar);\n this.message = status_bar;\n\n // Add the close button to the window.\n var buttongrp = document.createElement('div');\n buttongrp.classList = 'btn-group inline pull-right';\n button = document.createElement('button');\n button.classList = 'btn btn-mini btn-primary';\n button.href = '#';\n button.title = 'Stop Interaction';\n button.innerHTML = '';\n button.addEventListener('click', function (_evt) {\n fig.handle_close(fig, {});\n });\n button.addEventListener(\n 'mouseover',\n on_mouseover_closure('Stop Interaction')\n );\n buttongrp.appendChild(button);\n var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n titlebar.insertBefore(buttongrp, titlebar.firstChild);\n};\n\nmpl.figure.prototype._remove_fig_handler = function (event) {\n var fig = event.data.fig;\n if (event.target !== this) {\n // Ignore bubbled events from children.\n return;\n }\n fig.close_ws(fig, {});\n};\n\nmpl.figure.prototype._root_extra_style = function (el) {\n el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n};\n\nmpl.figure.prototype._canvas_extra_style = function (el) {\n // this is important to make the div 'focusable\n el.setAttribute('tabindex', 0);\n // reach out to IPython and tell the keyboard manager to turn it's self\n // off when our div gets focus\n\n // location in version 3\n if (IPython.notebook.keyboard_manager) {\n IPython.notebook.keyboard_manager.register_events(el);\n } else {\n // location in version 2\n IPython.keyboard_manager.register_events(el);\n }\n};\n\nmpl.figure.prototype._key_event_extra = function (event, _name) {\n // Check for shift+enter\n if (event.shiftKey && event.which === 13) {\n this.canvas_div.blur();\n // select the cell after this one\n var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n IPython.notebook.select(index + 1);\n }\n};\n\nmpl.figure.prototype.handle_save = function (fig, _msg) {\n fig.ondownload(fig, null);\n};\n\nmpl.find_output_cell = function (html_output) {\n // Return the cell and output element which can be found *uniquely* in the notebook.\n // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n // IPython event is triggered only after the cells have been serialised, which for\n // our purposes (turning an active figure into a static one), is too late.\n var cells = IPython.notebook.get_cells();\n var ncells = cells.length;\n for (var i = 0; i < ncells; i++) {\n var cell = cells[i];\n if (cell.cell_type === 'code') {\n for (var j = 0; j < cell.output_area.outputs.length; j++) {\n var data = cell.output_area.outputs[j];\n if (data.data) {\n // IPython >= 3 moved mimebundle to data attribute of output\n data = data.data;\n }\n if (data['text/html'] === html_output) {\n return [cell, data, j];\n }\n }\n }\n }\n};\n\n// Register the function which deals with the matplotlib target/channel.\n// The kernel may be null if the page has been refreshed.\nif (IPython.notebook.kernel !== null) {\n IPython.notebook.kernel.comm_manager.register_target(\n 'matplotlib',\n mpl.mpl_figure_comm\n );\n}\n", "text/plain": [ "" ] @@ -1034,7 +86,7 @@ { "data": { "text/html": [ - "" + "
" ], "text/plain": [ "" @@ -1042,20 +94,11 @@ }, "metadata": {}, "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ - "plt.plot(data)" + "plt.plot(data)\n", + "plt.show()" ] }, { @@ -1136,7 +179,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXAAAAD4CAYAAAD1jb0+AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAegUlEQVR4nO3deXiU5b3/8feXfQ1bggSSGBbZAwoJmxvuqLgjoMUNPRys7emmiLVWT6t1a3tsz69KUXFXdnGl7opWhQSQsAuyTcKSQFgCCdnmPn8k/i6agllmJjPPzOd1XVxOZh58vjd3+PBk5v7ejznnEBER72kU7gJERKR+FOAiIh6lABcR8SgFuIiIRynARUQ8qklDniw+Pt6lpqY25ClFRDxv+fLle51zCdWfb9AAT01NJSsrqyFPKSLieWa2/XjP6y0UERGPUoCLiHiUAlxExKMU4CIiHqUAFxHxqBoD3MxmmVmema2p9vxPzWyjma01s8dCV6KIiBxPba7AnwfGHPuEmZ0DXAEMcs4NAP4Y/NJEROSH1BjgzrklQEG1p28HHnHOlVQdkxeC2kREPO9ISTkPvLmWQ0fLgv7/ru974L2BM81sqZl9ZmYZJzrQzKaYWZaZZeXn59fzdCIi3rPvcAnXP/01L329naxt1a+DA1ffAG8CdABGAHcBc83Mjnegc26mcy7dOZeekPBvnaAiIlHJV1DEtTO+YsPuQv4+aSjn9j0p6Oeobyt9DrDQVd7OZ5mZ+YF4QJfYIhLzNuw+xE2zllFcWsErtw0nPbVjSM5T3yvwRcC5AGbWG2gG7A1STSIinrVsawHXzvgKgHlTR4UsvKEWV+Bm9howGog3sxzgfmAWMKtqaWEpcJPTzTVFJMZ9sG4PP3l1Bd06tOTFycNI6tAqpOerMcCdc9ed4KVJQa5FRMSz5mTu4J6Fq0lLas9zN2fQsXWzkJ+zQbeTFRGJNs45nvz0Ox5/byNn9U7gqR8NoXXzholWBbiISD35/Y7fv7OO5/65jStO7crj4wbTrEnD7VCiABcRqYfScj93zlvFm6t2Mvn07vzm0n40anTc1dQhowAXEamjIyXlTH15OZ9v2svdY/oy9ewenKAVJqQU4CIidbDvcAmTn89kzc5DPDZuEOPTk8NWiwJcRKSWcvYXceOzy8g9UMzfJw3l/P7B766sCwW4iEgtNFR3ZV0owEVEapC5rYBbn8+kZbPGzJs6ij5d2oa7JEABLiLygxq6u7IuFOAiIicwN9PH9IXZDdpdWRcKcBGRasLZXVkXkVeRiEgYhbu7si4U4CIiVUrL/dw1fxVvfBO+7sq6UICLiPCv3ZXTxvTh9rN7hqW7si4U4CIS877vrlyde5DHrhnE+IzwdVfWhQJcRGLav3RX3pDOBWHurqwLBbiIxKxjuytfvm04GRHQXVkXNX60amazzCyv6vZp1V+708ycmcWHpjwRkdDI3FbA+Kp7V86dOtJz4Q21u6nx88CY6k+aWTJwAbAjyDWJiITUB+v2MOmZpcS3bc6C20fRt0tcuEuqlxoD3Dm3BCg4zkv/A0wDdDNjEfGMuZk+pr68nL5d2jJ/6qiIao2vq3q9B25mlwO5zrlVkb7MRkQEKrsrn/rsOx77x0bOPCWeGZOGRmR3ZV3UuXozawXcC1xYy+OnAFMAUlJS6no6EZGA+f2OB99Zz6x/buXywV3547WR211ZF/UZQU+gO7DKzLYBScAKM+tyvIOdczOdc+nOufSEhIT6VyoiUg+l5X5+MfcbZv1zK7ecnsoTE06NivCGelyBO+dWA52//7oqxNOdc3uDWJeISMCOlJRz+ysrWPJtvme6K+uiNssIXwO+AvqYWY6Z3Rr6skREAlNwpJTrn1nKF5vyeeyaQfx4dK+oCm+oxRW4c+66Gl5PDVo1IiJBkLO/iBtnLSN3v/e6K+vC2x/BiohUs3F3ITfOWkpxaQUv3TqcYd2916BTWwpwEYkax967cu7UkZ5t0KktBbiIRIUP1+3hjldX0K19S16YPIzkjt5t0KktBbiIeN7cLB/3LFzNwK5xzLo5g05tmoe7pAahABcRz4rG7sq6iJ2RikhUidbuyrpQgIuI5xx778pbTk/lvkv7R/S9K0NFAS4inhLt3ZV1oQAXEc8oOFLKLc9nsjrnAI9ek8aEjNjeIE8BLiKeECvdlXWhABeRiPd9d2VRDHRX1oUCXEQi2vfdlS2aNmZeDHRX1oUCXEQiVix2V9aFAlxEItL33ZUDusbxXAx1V9aFAlxEIopzjhmfbeHRf2yIye7KutCfiohEDL/f8dC763n2i9jtrqwLBbiIRITScj/T5q9i0Tc7uXlUKr8dG5vdlXWhABeRsDu2u/Kui/rw49Gx211ZF7W5J+YsM8szszXHPPe4mW0ws2wze93M2oe0ShGJWsfeu/LRa9K445zou3dlqNTmzaXngTHVnvsAGOicGwR8C9wT5LpEJAbk7C9i3Iwv2bDrEDMmDY351vi6qjHAnXNLgIJqz73vnCuv+vJrICkEtYlIFNu4u5BxT31FfmEJL906nAsHdAl3SZ4TjI93JwOLT/SimU0xsywzy8rPzw/C6UTE67K2FXDtjC/xO8e8qSPVGl9PAQW4md0LlAOvnOgY59xM51y6cy49ISEhkNOJSBT4cN0efvTMUuLbNGfB7aPUGh+Aeq9CMbObgLHAec45F7ySRCRaqbsyuOoV4GY2BrgbONs5VxTckkQk2lTvrnxq0lDaqLsyYDX+CZrZa8BoIN7McoD7qVx10hz4oGq5z9fOuakhrFNEPOrY7srLBnflT+quDJoaA9w5d91xnn42BLWISJRRd2Vo6WcYEQkJdVeGngJcRILu2HtXPnJ1GhOHqUEnFBTgIhJUx967csakoWrQCSEFuIgEzbd7Crnx2WUcKS3XvSsbgAJcRIIia1sBk6vuXTn3P0fSL1ENOqGmABeRgH20fg8/fmUFXdu35EXdu7LBKMBFJCDzsnxMV3dlWCjARaRenHP8fckWHlm8gTN6xTPjBnVXNjT9aYtInfn9jj+8u55n1F0ZVgpwEamTsgo/0+Zn8/rKXHVXhpkCXERqrai0nNtfXsFn6q6MCApwEakVdVdGHgW4iNQo90AxNzy7lJz9xTw1aSgXqbsyIijAReQH/Ut35eRhDO/RKdwlSRUFuIic0PLtBUx+PotmTRqpuzICKcBF5Lg+Wr+HO15dQWI7dVdGKgW4iPyb77sr+yfG8dwtGcSruzIi1bjy3sxmmVmema055rmOZvaBmW2q+m+H0JYpIg2h8t6V33HX/GxG9ujEa1NGKLwjWG1ap54HxlR7bjrwkXPuFOCjqq9FxMP8fsdD76znkcUbGDsokVk3Z6g1PsLVGODOuSVAQbWnrwBeqHr8AnBlcMsSkYZUVuHnV/NW8cwXW7l5VCp/nXiaWuM9oL7/vJ7knNsF4JzbZWadT3SgmU0BpgCkpGjhv0ikOba78s4Le3PHOb3UXekRIf8n1jk30zmX7pxLT0hICPXpRKQO9h8p5fqnl/L5pnwevjqNn5x7isLbQ+p7Bb7HzBKrrr4TgbxgFiUioZd7oJgbn12KT92VnlXfK/A3gZuqHt8EvBGcckSkIXy7p5BrnvySvMISXpo8TOHtUTVegZvZa8BoIN7McoD7gUeAuWZ2K7ADuDaURYpI8Ki7MnrUGODOuetO8NJ5Qa5FRELs4w2V967sEteCl24dru5Kj9MiT5EYMX95DncvyFZ3ZRRRgIvEgL9/9h0P696VUUezKBLF/H7Hw4vX8/TnWxk7KJE/jR9M8yaNw12WBIkCXCRKHXvvyptGnsz9lw3QvSujjAJcJAqpuzI2KMBFosz+qntXZucc4OGr07hO966MWgpwkShybHflkz8aypiBatCJZgpwkSjgnGNeVg6/f2cdOHhx8jBG6N6VUU8BLuJxvoIi7lm4mi8272VY9448es0guse3DndZ0gAU4CIeVeF3vPDlNh5/byONGxkPXjmQ64elaKVJDFGAi3jQpj2FTFuQzcodBxjdJ4E/XJVG1/Ytw12WNDAFuIiHlJb7mfHZd/y/jzfTunljnphwKlec2lVLBGOUAlzEI7JzDjBtfjYbdhdy2eCu3H9Zf+1nEuMU4CIR7mhZBf/zwbc8/fkWEto25+kb07mg/0nhLksigAJcJIJ9vWUf0xdks21fEdcNS2b6xf1o17JpuMuSCKEAF4lAhUfLeGTxBl5ZuoOUjq149bbhjOoVH+6yJMIowEUizMcb9nDv62vYc+got53RnV9e2JtWzfRXVf6dvitEIkTBkVJ+99ZaFn2zk1M6t+HJ20dxWkqHcJclESygADezXwC3AQ5YDdzinDsajMJEYoVzjreyd/HAm2spPFrGz847hR+f01P7dkuN6h3gZtYN+C+gv3Ou2MzmAhOB54NUm0jU233wKL9ZtIYP1+9hcFI7Hh03nL5ddJNhqZ1A30JpArQ0szKgFbAz8JJEop9zjtmZPv7wznrK/H7uvaQfk8/oTmO1wUsd1DvAnXO5ZvZHYAdQDLzvnHu/+nFmNgWYApCSon2JRbbvO8L0Bav5ass+RvToyCNXDyJVm09JPTSq7280sw7AFUB3oCvQ2swmVT/OOTfTOZfunEtPSEiof6UiHlfhdzzz+RYuemIJa3IP8oer0nj1thEKb6m3QN5COR/Y6pzLBzCzhcAo4OVgFCYSTTburtx8apXvAOf17cyDVw0ksZ02n5LABBLgO4ARZtaKyrdQzgOyglKVSJQoLffz5Keb+dsnm2nboil/ve40LhuUqM2nJCgCeQ98qZnNB1YA5cBKYGawChPxum98B7h7fjYb9xRyxalduf+yAXRs3SzcZUkUCWgVinPufuD+INUiEhWKSyv40/sbmfXPrXRu24Jnb0rnvH7afEqCT52YIkH05Xd7mb5gNTsKirh+eArTL+5LXAttPiWhoQAXCYJDR8t4+N31vLbMx8mdWvHaf4xgZE/dVFhCSwEuEqAP1+3h3kWryS8sYcpZPfjF+b1p2Uxt8BJ6CnCRetp3uIQH3lrHW6t20rdLW2bekM7g5PbhLktiiAJcpI6cc7y5aicPvLmWwyXl/PKC3kw9uyfNmtS7L06kXhTgInWw80Axv1m0ho835HFqcnseGzeI3ie1DXdZEqMU4CK14Pc7Xl22g0cWb6DC77hvbH9uHpWqzackrBTgIjXYuvcI0xdks3RrAaf36sTDVw0ipVOrcJclogAXOZHyCj/PfrGVP3/wLc2aNOLRa9IYn56sNniJGApwkeNYv+sQdy/IJjvnIBf0P4kHrxzISXEtwl2WyL9QgIsco6S8gr99vJknP/2O9q2a8rfrh3BJWhdddUtEUoCLVFm+fT93L8hmc95hrj6tG/eN7U8HbT4lEUwBLjGvqLScx9/byPNfbiMxrgXP3ZLBOX06h7sskRopwCWmfbFpL9MXZpOzv5gbRpzMtDF9aKvNp8QjFOASkw4Wl/HQO+uYm5VD9/jWzJkyguE9tPmUeIsCXGLOe2t3c9+iNew7UsrUs3vy8/NPoUVTbT4l3qMAl5iRX1jCA2+u5Z3Vu+iXGMezN2WQltQu3GWJ1FtAAW5m7YFngIGAAyY7574KQl0iQeOc4/WVufzu7XUUlVRw10V9mHJWD5o21uZT4m2BXoH/BfiHc26cmTUD1F8sESX3QDG/Xriaz77NZ0hK5eZTvTpr8ymJDvUOcDOLA84CbgZwzpUCpcEpSyQwfr/j5aXbeXTxBhzwwGX9uWGkNp+S6BLIFXgPIB94zswGA8uBnznnjhx7kJlNAaYApKSkBHA6kdr5Lv8w0xdkk7ltP2eeEs8frkojuaN+OJToE8ibgE2AIcBTzrnTgCPA9OoHOedmOufSnXPpCQkJAZxO5IeVV/h58tPNXPyXz9m4u5DHxw3ixcnDFN4StQK5As8BcpxzS6u+ns9xAlykIazdeZC7F2SzJvcQYwZ04XdXDqBzW20+JdGt3gHunNttZj4z6+Oc2wicB6wLXmkiNTtaVsH/fryJGZ9toUOrZjz1oyFcnJYY7rJEGkSgq1B+CrxStQJlC3BL4CWJ1E7WtgKmLchmS/4RrhmSxH1j+9G+lTafktgRUIA7574B0oNTikjtHCmp3Hzqha+20bVdS16YPIyze+vzFYk96sQUT1nybT73LFzNzoPF3DQylTsv6kOb5vo2ltik73zxhANFpTz4znrmL8+hR0Jr5v3nSNJTO4a7LJGwUoBLxFu8ehf3vbGW/UWl3HFOT356rjafEgEFuESwvENH+e0ba/nH2t0M6BrHC5MzGNBVm0+JfE8BLhHHOcf85Tn8/u11HC33M21MH/7jTG0+JVKdAlwiiq+giF+/vprPN+0lI7UDj1wziJ4JbcJdlkhEUoBLRPD7HS9+tY3H3tuIAb+/YgA/Gn4yjbT5lMgJKcAl7DbnFXL3gtUs376fs3sn8NBVA0nqoP1LRGqiAJewKavwM3PJFv7y4SZaNW/Mn8cP5qrTumGmq26R2lCAS1isyT3IXfOzWb/rEJemJfLA5QNIaNs83GWJeIoCXBrU0bIKnvhwE09/voWOrZsxY9JQxgzsEu6yRDxJAS4NZtnWAqYvyGbL3iOMT0/i3kv6065V03CXJeJZCnAJucMl5Ty6eAMvfb2dpA4tefnW4ZxxSny4yxLxPAW4hNQnG/O4d+Fqdh06yuTTu3PnRb1p1UzfdiLBoL9JEhL7j5Ty+7fXsXBlLr06t2H+1FEMPblDuMsSiSoKcAkq5xzvrN7F/W+s5WBxGf91bi/uOLcXzZto8ymRYFOAS9DsOXSU+xat4f11e0jr1o6Xbh1O/65x4S5LJGoFHOBm1hjIAnKdc2MDL0m8xjnH3CwfD76zntJyP/dc3Jdbz+hOE20+JRJSwbgC/xmwHtClVgzasa+Ie17P5p+b9zGse0cevWYQ3eNbh7sskZgQUICbWRJwKfAQ8MugVCSeUFRazqtLd/Cn97+lcSPjwSsHcv2wFG0+JdKAAr0CfwKYBrQ90QFmNgWYApCSkhLg6SScnHOsyjnInEwfb63ayeGScs7pk8BDV6XRtX3LcJcnEnPqHeBmNhbIc84tN7PRJzrOOTcTmAmQnp7u6ns+CZ8DRaW8vjKXOZk+NuwupEXTRlya1pUJGclkpHbQ5lMiYRLIFfjpwOVmdgnQAogzs5edc5OCU5qEk9/v+GrLPmZn+nhv7W5Ky/0MSmrHQ1cN5LLBXYlroRZ4kXCrd4A75+4B7gGougK/U+HtfbsPHmX+ch9zsnz4CoqJa9GE64elMD49WUsCRSKM1oELZRV+Pt6Qx5xMH59uzMPvYFTPTtx5YR8uGtBFd4AXiVBBCXDn3KfAp8H4f0nD2ZJ/mDlZPhYsz2Xv4RI6t23O7aN7Mj49mZM7aSmgSKTTFXiMKS6tYPGaXczO9LFsawGNGxnn9u3MxIxkzu6doOYbEQ9RgMeINbkHmZ25gzdW7qSwpJyTO7Vi2pg+jBuSROe4FuEuT0TqQQEexQ4WlfHGqsrlf2t3HqJ5k0ZckpbI+PRkRvToqOV/Ih6nAI8yzjmWbi1gTqaPd1fvoqTcT//EOH53xQCuGNxNd8ARiSIK8CiRd+go81fkMDfTx7Z9RbRt3oRr05OYmJHCwG7twl2eiISAAtzDyiv8fLoxnzlZPj7ekEeF3zGse0d+eu4pXJKWSMtmWv4nEs0U4B60fd8R5mb5mJeVQ15hCfFtmnHbmd0Zn55Mz4Q24S5PRBqIAtwjjpZV8N7a3cxe5uOrLftoZDC6T2cmZCRzbt/ONNXyP5GYowCPcOt2HmJulo/XV+ZysLiM5I4t+dUFvRmXnkRiO+0AKBLLFOARqPBoGW+u2smcTB/ZOQdp1rgRFw3swsSMZEb26KQ9t0UEUIBHDOccWdv3M3tZ5fK/4rIK+pzUlvsv68+Vp3ajQ+tm4S5RRCKMAjzM9h4uYeGKHGZn+tiSf4TWzRpz5WldmZCRwuCkdmq2EZETUoCHQYXfsWRTPnOW+fhw/R7K/Y6hJ3fgsXE9uTQtkdbNNS0iUjMlRQPyFRQxL8vHvOU57Dp4lI6tm3HL6alMyEimV+cT3pVOROS4FOAhVlJewQfr9jAn08cXm/cCcOYpCdw3tj/n9zuJZk20/E9E6kcBHiIbdxcyJ9PH6ytz2F9URrf2LfnZeadwbXoy3XQDYBEJAgV4EB0uKeftVTuZk+Vj5Y4DNG1sXNi/C+MzkjmjVzyNtfxPRIJIAR4g5xwrfQeYs8zHW9k7KSqtoFfnNvzm0n5cdVo3OrVpHu4SRSRK1TvAzSwZeBHoAviBmc65vwSrsEhXcKSUhStymJPpY1PeYVo2bcxlgxOZkJHCkJT2Wv4nIiEXyBV4OfAr59wKM2sLLDezD5xz64JUW8Tx+x1fbN7LnCwf76/dTVmF49Tk9jx8dRpjByXStoX22haRhlPvAHfO7QJ2VT0uNLP1QDcg6gJ854Fi5mXlMDfLR+6BYtq3asqkESczISOZvl3iwl2eiMSooLwHbmapwGnA0uO8NgWYApCSkhKM0zWI0nI/H63fw+xMH0s25eMcnNErnukX9+WC/ifRoqn22haR8Ao4wM2sDbAA+Llz7lD1151zM4GZAOnp6S7Q84Xa5rzDzM3ysWB5DvuOlNIlrgU/OacX49OTSe7YKtzliYj8fwEFuJk1pTK8X3HOLQxOSQ2vqLScd7J3MSfTR9b2/TRpZJzXrzMTM1I4q3eClv+JSEQKZBWKAc8C651zfw5eSQ3DOUd2zkFmZ/p4a9VODpeU0yO+Nfdc3JerhySR0FbL/0QksgVyBX46cAOw2sy+qXru1865dwOuKoQOFJWyaGUuszN9bNhdSIumjbgkLZGJGSlkpHbQ8j8R8YxAVqF8AXgi7fx+x9db9jE708c/1u6mtNxPWrd2PHjlQC4/tStxWv4nIh4U1Z2Yuw8eZf5yH3OzcthRUERciyZcl5HM+IxkBnRtF+7yREQCEnUBXlbh55MNeczJ9PHJxjz8Dkb06MgvL+jNmIFdtPxPRKJG1AT41r1HmJPpY/7yHPYeLiGhbXOmnt2T8enJpMa3Dnd5IiJB5+kALy6tYPGayuV/S7cW0LiRcU6fzkzISOacPgk0aay9tkUkenkywNfkHmROpo9F3+RSeLSckzu14q6L+jBuaBInxbUId3kiIg3CMwF+sLiMN7+pXP63duchmjVpxCUDuzAhI4Xh3TvSSM02IhJjPBHgf/1oE3/7ZDMl5X76Jcbx35cP4MpTu9GulZb/iUjs8kSAd23fknFDk5iYkcLAbnFqthERwSMBPm5oEuOGJoW7DBGRiKJlGiIiHqUAFxHxKAW4iIhHKcBFRDxKAS4i4lEKcBERj1KAi4h4lAJcRMSjzLmGu1G8meUD2+v52+OBvUEsJ5w0lsgTLeMAjSVSBTKWk51zCdWfbNAAD4SZZTnn0sNdRzBoLJEnWsYBGkukCsVY9BaKiIhHKcBFRDzKSwE+M9wFBJHGEnmiZRygsUSqoI/FM++Bi4jIv/LSFbiIiBxDAS4i4lERFeBmNsvM8sxszQleNzP7q5ltNrNsMxvS0DXWVi3GMtrMDprZN1W/ftvQNdaGmSWb2Sdmtt7M1prZz45zjCfmpZZj8cq8tDCzZWa2qmos/32cY7wyL7UZiyfmBcDMGpvZSjN7+zivBXdOnHMR8ws4CxgCrDnB65cAiwEDRgBLw11zAGMZDbwd7jprMY5EYEjV47bAt0B/L85LLcfilXkxoE3V46bAUmCER+elNmPxxLxU1fpL4NXj1RvsOYmoK3Dn3BKg4AcOuQJ40VX6GmhvZokNU13d1GIsnuCc2+WcW1H1uBBYD3Srdpgn5qWWY/GEqj/rw1VfNq36VX1FglfmpTZj8QQzSwIuBZ45wSFBnZOICvBa6Ab4jvk6B4/+BawysurHxsVmNiDcxdTEzFKB06i8QjqW5+blB8YCHpmXqh/VvwHygA+cc56dl1qMBbwxL08A0wD/CV4P6px4LcCPdzt6T/5LDaygcn+DwcD/AovCW84PM7M2wALg5865Q9VfPs5vidh5qWEsnpkX51yFc+5UIAkYZmYDqx3imXmpxVgifl7MbCyQ55xb/kOHHee5es+J1wI8B0g+5uskYGeYagmIc+7Q9z82OufeBZqaWXyYyzouM2tKZeC94pxbeJxDPDMvNY3FS/PyPefcAeBTYEy1lzwzL9870Vg8Mi+nA5eb2TZgNnCumb1c7ZigzonXAvxN4MaqT3JHAAedc7vCXVR9mFkXM7Oqx8OonIt94a3q31XV+Cyw3jn35xMc5ol5qc1YPDQvCWbWvupxS+B8YEO1w7wyLzWOxQvz4py7xzmX5JxLBSYCHzvnJlU7LKhz0qT+5Qafmb1G5afN8WaWA9xP5QcaOOdmAO9S+SnuZqAIuCU8ldasFmMZB9xuZuVAMTDRVX1MHWFOB24AVle9RwnwayAFPDcvtRmLV+YlEXjBzBpTGWZznXNvm9lU8Ny81GYsXpmXfxPKOVErvYiIR3ntLRQREamiABcR8SgFuIiIRynARUQ8SgEuIuJRCnAREY9SgIuIeNT/Ad9l4Mxw9ofxAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -1184,7 +227,7 @@ }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAD4CAYAAAAXUaZHAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAXfklEQVR4nO3df5DddX3v8ecbEgiGtOXHsokQSLCI1wsVNEWUSlqQC4oVbMttVJi0pQWHHxe8thWGaZXuUKi942gr3jEDxtxKAStYaKVemQAyuUQxIVGEXC4OIEQ2yRYsJPzIks37/vE9m/292T3n7PnxPc/HzJmz5/vjfD9nIa99n8/38/18IzORJJXLPs1ugCSp/gx3SSohw12SSshwl6QSMtwlqYRmNbsBAIceemguWrSo2c2QpLayfv36f8/MrvHWtUS4L1q0iHXr1jW7GZLUViLiZxOts1tGkkrIcJekEjLcJamEDHdJKiHDXZJKyHCXpCbp3d7L0q8tZcuOLXV/b8Ndkpqk58Ee1jy7hp7v9dT9vQ13SWqC3u29rNy4kt25m5UbV9a9ejfcJakJeh7sYXfuBmAgB+pevRvuktRgg1V7/0A/AP0D/XWv3g13SWqw4VX7oHpX74a7JDXY2s1r91Ttg/oH+nlo80N1O0ZLTBwmSZ1kw8UbZvwYVu6SVEKGuySVkOEuSSVkuEtSCRnuklRChrsklZDhLkklZLhLUgkZ7pJUQoa7JJWQ4S5JJbTXcI+Ir0bEtoj4ybBlB0fEvRHxZOX5oGHrro6In0bEExFx5kw1XJI0salU7l8Dzhq17CpgdWYeA6yuvCYi3g4sA/5zZZ8vR8S+dWutJGlK9hrumfkg8OKoxecAqyo/rwLOHbb8tszcmZlPAz8FTqpPUyVJU1Vtn3t3ZvYCVJ4Pqyw/HHhu2HabK8vGiIiLImJdRKzr6+urshmSpPHU+4RqjLMsx9swM1dk5pLMXNLV1VXnZkhSZ6s23LdGxAKAyvO2yvLNwMJh2x0BPF998ySpPfRu72Xp15bW9T6otag23O8Glld+Xg7cNWz5sojYPyIWA8cAD9fWRElqfT0P9rDm2TV1vQ9qLaYyFPJWYC1wbERsjogLgRuAMyLiSeCMymsy8zHgG8DjwHeASzNzYKYaL0mtoHd7Lys3rmR37mblxpUtUb3v9R6qmfnRCVadPsH21wHX1dIoSWonPQ/2sDt3AzCQA/R8r4cbz76xqW3yClVJqsFg1d4/0A9A/0B/S1Tvhrsk1WB41T5osHpvJsNdkmqwdvPaPVX7oP6Bfh7a/FCTWlTYa5+7JGliGy7e0OwmjMvKXZJKyHCXpBIy3CWphAx3SSohw12SSshwl6QSMtwlqYQMd0kqIcNdkkrIcJekEjLcJamEDHdJKiHDXZJKyHCXpBIy3CVpHL3be1n6taVNv6NStQx3SRpHz4M9rHl2TdPvqFQtw12SRhm8L+ru3N0S90OthuEuSaMMvy9qK9wPtRqGuyQNM1i1D94XtX+gvy2rd8NdkoYZXrUPasfq3XCXpGHWbl67p2of1D/Qz0ObH2pSi6ozq9kNkKRWsuHiDc1uQl1YuUtSCdUU7hHxyYh4LCJ+EhG3RsSciDg4Iu6NiCcrzwfVq7GSpKmpOtwj4nDgvwFLMvM4YF9gGXAVsDozjwFWV15Lkhqo1m6ZWcABETELeBPwPHAOsKqyfhVwbo3HkCRNU9Xhnpk/B/4H8CzQC7yUmd8FujOzt7JNL3DYePtHxEURsS4i1vX19VXbDEnSOGrpljmIokpfDLwZmBsR5091/8xckZlLMnNJV1dXtc2QJI2jlm6Z9wNPZ2ZfZr4B3Am8F9gaEQsAKs/bam+mJGk6agn3Z4GTI+JNERHA6cAm4G5geWWb5cBdtTVRkjRdVV/ElJk/iIhvAo8Au4ANwArgQOAbEXEhxR+A8+rRUEnS1NV0hWpmfgb4zKjFOymqeElSk3iFqiSVkOEuqfTa/ZZ51TDcJZVeu98yrxqGu6RSK8Mt86phuEsqtTLcMq8ahruk0irLLfOqYbhLKq2y3DKvGoa7pNIqyy3zquFt9iSVVllumVcNK3dJKiHDXZJKyHCXpBIy3CWphAx3SSohw12SSshwl6QSMtwlqYQMd0kqIcNdkkrIcJekEjLcJbWVTrxlXjUMd0ltpRNvmVcNw11S2+jUW+ZVw3CX1DY69ZZ51TDcJbWFTr5lXjUMd0ltoZNvmVcNw11SW+jkW+ZVo6bb7EXErwA3AccBCfwR8ARwO7AIeAb4r5n5i1qOI0mdfMu8atRauX8R+E5mvg14B7AJuApYnZnHAKsrryVJDVR1uEfELwGnAjcDZGZ/Zv4HcA6wqrLZKuDc2pooSZquWir3o4E+YGVEbIiImyJiLtCdmb0AlefDxts5Ii6KiHURsa6vr6+GZkiSRqsl3GcB7wT+Z2aeCLzCNLpgMnNFZi7JzCVdXV01NEOSNFot4b4Z2JyZP6i8/iZF2G+NiAUAledttTVRkjRdVYd7Zm4BnouIYyuLTgceB+4GlleWLQfuqqmFkqRpq2koJHA5cEtE7Ac8BfwhxR+Mb0TEhcCzwHk1HkOSNE01hXtmbgSWjLPq9FreV5JUG69QldQ0zs0+cwx3SU3j3Owzx3CX1BTOzT6zDHdJTeHc7DPLcJfUcM7NPvMMd0kN59zsM89wl9Rwzs0+82q9iEmSps252WeelbsklZDhLkklZLhLUgkZ7pJUQoa7JJWQ4S5JJWS4S1IJGe6S6sYpfFuH4S6pbpzCt3UY7pLqwil8W4vhLqkunMK3tRjukmrmFL6tx3CXVDOn8G09hrukmjmFb+txyl9JNXMK39Zj5S5JJWS4S1IJGe6SVEI1h3tE7BsRGyLiXyuvD46IeyPiycrzQbU3U5I0HfWo3K8ANg17fRWwOjOPAVZXXkuSGqimcI+II4CzgZuGLT4HWFX5eRVwbi3HkNQcTgLW3mqt3L8A/Dkw/OqF7szsBag8HzbejhFxUUSsi4h1fX19NTZDUr05CVh7qzrcI+JDwLbMXF/N/pm5IjOXZOaSrq6uapshaQY4CVj7q6VyPwX4cEQ8A9wGnBYRXwe2RsQCgMrztppbKamhnASs/VUd7pl5dWYekZmLgGXAfZl5PnA3sLyy2XLgrppbKalhnASsHGZinPsNwBkR8SRwRuW1pDbhJGDlUJe5ZTLzAeCBys8vAKfX430lNZ6TgJWDE4dJGsFJwMrB6QckqYQMd0kqIcNdkkrIcJc6gFMJdB7DXeoATiXQeQx3qeScSqAzGe5SyTmVQGcy3KUScyqBzmW4SyXmVAKdy3CXSsypBDqX0w9IJeZUAp3Lyl2SSshwl6QSMtwlqYQMd6kNOZ2A9sZwl9qQ0wlobwx3qc04nYCmwnCX2ozTCWgqDHepjTidgKbKcJfaiNMJaKoMd6mNOJ2ApsrpB6Q24nQC5TB/PmzdOnZ5dzdsqVMPm5W7JDXYeME+2fJqGO5Sk3lBkmaC4S41mRcktbf58yFi7GP+/Oa2y3CXmsgLktpfI7pYqlF1uEfEwoi4PyI2RcRjEXFFZfnBEXFvRDxZeT6ofs2VysULkjRTaqncdwGfysz/BJwMXBoRbweuAlZn5jHA6sprSaN4QVJrakQ3S3f39JZXo+pwz8zezHyk8vN2YBNwOHAOsKqy2Srg3BrbKJWSFyS1pkZ0s2zZApljH/UaBgl16nOPiEXAicAPgO7M7IXiDwBw2AT7XBQR6yJiXV9fXz2aIbUVL0jSTKr5IqaIOBC4A7gyM1+OiCntl5krgBUAS5YsyVrbIbUbL0iaeY24WKi7e+JjNFNNlXtEzKYI9lsy887K4q0RsaCyfgGwrbYmSu3DMeutpSxdLNWoZbRMADcDmzLz88NW3Q0sr/y8HLir+uZJ7cUx62oVtVTupwAXAKdFxMbK44PADcAZEfEkcEbltVR6jlmfWY26WKgRI1kaoeo+98xcA0zUwX56te8rtavxxqzfePaNTW5VeTTqYqFmd6fUi1eoSnXgmHW1GsNdqgPHrE+PXSwzz3CXJjHV0S+OWZ+eRnaxtOJIlkbwZh3SJIaPfpms/9wx62o1Vu7SBBz9MnVlmY+lTAx3aQLO2Dh1nXyxUKsy3KVxdPLol1a9+YSmx3CXxtHJo18aUYXbxTLzDHd1jOnM++Lol5llF8vMc7SMOsZUR75AeUa/NGJWRLUmK3d1hE4d+dKo8eR2s7Qew10doSwjX1r1ZKfdLK3HcFfplWnkiyc7NVWGu9rSdE6OturIF6twzSTDXW1pOjfFaNWRL43qD1dniszm3750yZIluW7dumY3Q22id3svR//d0by+63UOmHUAT13xFPMPbG65W82olMluNzzRP8vp7uNomXKLiPWZuWS8dVbuagnVdrO0QvcKtG4VbhdL5zLc1RKm2s3SqJOjrdof7slOTZXhrqabzhj0ak6OVhPUVuJqd4a7mm463SzVnBxt1aC2CtdM8oSq6q53ey/L7ljG7b93+15PdA4/OTpospOkrXrisppjqEQGBmDnTth/f9h3X3jppeJ/yJ07hx6vvw6/8RswZw48+iisXw+zZsH551d92MlOqDq3jOpuOnO4vOWPenj9bbtH/J/42usDHP2HPbz6T2P3beUqfKI/OpoBmfDGG2PD89BD4Zd/GV5+GR55ZOS6nTvhfe+DRYvg6afh1ltH7r9zJ1x2Gbz97fDQQ3D99UP7DT5WrYJ3vANuuw0uvXRo/cBA0a5HH4Xjjiu2u+KKse1++uni+P/yL3DNNdDVVVO4T8Zw16SmU4XPnw9bX+mFK1bC7N18ee1KvrzsL+ieO3/Cqvq1Q9bCrJHdLMzq57VD2mv2xY7o8x4YKB777Ve8fvbZItyGB+Bhh8Fb3wq7d8Ptt48Nz3e9C047DV59FT796bHhvGxZ8di6Fc4+e2y4/tVfwcUXw+OPFyE62k03wYUXwqZN8Fu/NXb9bbcV4frUU0W4QvF59t+/ePzu7xbh/vrr8PzzQ8sPOqiouGfPLvZZvBg++tFi3Zw5Q9sddlix/swz4ZZbhpYPPgb/2n/iE/CxjxX7zhC7ZTSuPd0fZ18C7/oKrPsE3HPj3rs/zr4ETry5COxd+8Ejfwz33NjU7o9q9mmJ8eHjVae7d8PChcX6xx6Dvr6R4ThvHnzgA8X6r38dnntuZEAedRRceWWx/vLL4ZlnRr7/ySfDF75QrD/hhGL/wXW7dhWB9o//WKw/8EB45ZWRbf6TP4EVK4q27zPOKb1PfhI+//liv4ULRwbfnDlwySVFeL/4Ilxwwcjg3H9/OO88OP10eOEF+MpXxu7/nvfAr/5qUbmvXz92/fz5RbsHBorf7X77jd/ONjFZt4zh3iH2hNWBvfB7y+Cbt8OO+ROGVURl2yuOhtmvwxsHwBefgh3zJw7RecO2H1TZL7ePX/U3ItynFdQDA8U/9gjYvr0ImdHV48knF32ljz5aBOzo9Z/6VPEed9wBDzwwcl1mUdECXHtt8fV8+P7z5hXvCfCRj8A///PI9i1eXFSdUITcffeNXP9rvwY/+lHx87vfDQ8/XPw8WJ2+733w7W8Xy845pwjv4dXnySfDZz9brP/0p2HHjqF1c+bA8ccX7YKiMoWRAbxwIbztbcXyJ54YW7nOmVP0Sasu7HMvmekGNQwLt6U9cOQaOLUH7rlx8r7qpT0QlWGHMbBnnyltP2hwPybvex/Xyy8XX7+Hhx8fnnj7q68utr38cjj6aPje9+BLX2LLr48K33/4BzjmmKJf9M1Xj1y3a1cRnosXw9///dBX9+H6+oq+3VtvLfplR7vsMjjgAPj+98d+NX/Tm4a2mzu3+AszPBwPOmho/bJlRTfGROs/97nidzT8/efNG1p/331FkE5Und5118S/S4C/+ZvJ13/845OvP/bYyddrRlm519l0v85XE9R7qtdRXSawl66JiSrxZ342MuAOPZQ4fv+Jq/DvPl18/X3pJbjuuj3hG/EwLNg49uC9J5D/Z9dQ18ENNxT9jT/8IXHSr0/wm4RcfV9RnQ7/fdHLVsZ+C+hmC1tmH1kE4b/9G5xyCtx9N1x11div9jfeWHx1v//+oothdHV52WVwyCFFBTz41X74e5x6avG8ZQv84hdj33/u3Mm/Ykh10pRumYg4C/gisC9wU2beMNG21YT7dEOxmhCtKXhH7QOQ23cM9Zt2dY3cfqKgvuWWohHDwjduuH7ioD51KSxdWpx4guLM/gsvED/fPHF/OKOC6MoriSd3Dm07qLJPvvNg6Okp2rV48Z7wiy29E/73yo/8zlD4/cEfwG/+Jjz/PPPfOo+tr8wbs313N2x57IWiW2F0eB51VFGh9vfDa68Vy9q871SqRsO7ZSJiX4rv4WcAm4EfRsTdmfl4vY4x5W6GV1+F7dvZurV74u2/9a2xX80vuWRqx/jLvyy+/g52HfDouPsAQ1+Zjz8efvzjofc4sBdOWAn77IYTV8KDf7HnDwLXXz/UBwuVs/XXT9xlElH0Bw9673uLE0e3V44xGNaz+oeO9cWbR4bnW94Cf/fxcUexsPAhuGZt8bq7u/j9VnRP8q2FO+8cu+LNb2bLjrGLhxwydHJwPPvtNzRyQ9IIM1K5R8R7gM9m5pmV11cDZOY4HZTVVe6TdjPM3g82by6GJV1zDfz1XxPkxNuPrlz32QcGBqZ2UvEzn4E1a/ZUl/GtOyfe53N/OzQc6vd/f+hzTDbC5MUXi37TYdVpVScuP3TJxJX4t8f2h7fEaBFJk2rGCdXDgeeGvd4MvHtUoy4CLgI48sgjqzvKRNXrn/7p0PjR3/5tOPxwuHSS7TdsGNvvmgnE3k8qXnvtyDbFJMf5sz8b+xkOnKSiZj4cfPDkn3vPcSc/cTlr0Vp2jVOJz1o8/nhyA1xqbzNVuZ8HnJmZf1x5fQFwUmZePt72VVXu06xeq6p2G7DPdCtqgNmXnciuro1jls/qO4E3vrRh3H0klU8zKvfNwMJhr48Anq/rEaZbvVYzTK+KfQ44q4fXxtnngLPG32e6FTVggEvaq5kK9x8Cx0TEYuDnwDLgY/U8wHRDsZoQrWafY9+/lo1bxu5z7PvH38egljQTZnIo5AeBL1AMhfxqZl430bZlGucuSY3SlCtUM/Me4J6Zen9J0sS86kOSSshwl6QSMtwlqYQMd0kqoZaYFTIi+oCf1fAWhwL/XqfmtBs/e+fq5M/fyZ8dhj7/UZnZNd4GLRHutYqIdRMNByo7P3tnfnbo7M/fyZ8dpvb57ZaRpBIy3CWphMoS7iua3YAm8rN3rk7+/J382WEKn78Ufe6SpJHKUrlLkoYx3CWphNo63CPirIh4IiJ+GhFXNbs9jRQRX42IbRHxk2a3pdEiYmFE3B8RmyLisYi4otltapSImBMRD0fEjyqf/dq971UuEbFvRGyIiH9tdlsaLSKeiYhHI2JjREw6lW7b9rlXbsL9/xh2E27go/W8CXcri4hTgR3A/8rM45rdnkaKiAXAgsx8JCLmAeuBczvhv31EBDA3M3dExGxgDXBFZn6/yU1rmIj478AS4Jcy80PNbk8jRcQzwJLM3OsFXO1cuZ8E/DQzn8rMfuA24Jwmt6lhMvNB4MVmt6MZMrM3Mx+p/Lwd2ERx397Sy8KOysvZlUd7VmhViIgjgLOBm5rdllbXzuE+3k24O+IfuIZExCLgROAHTW5Kw1S6JTYC24B7M7NjPjvFDYD+HNi9l+3KKoHvRsT6iLhosg3bOdxjnGUdU8EIIuJA4A7gysx8udntaZTMHMjMEyjuTXxSRHREt1xEfAjYlpnrm92WJjolM98JfAC4tNI9O652DveZvwm3Wlalv/kO4JbMvLPZ7WmGzPwP4AHgrOa2pGFOAT5c6Xe+DTgtIr7e3CY1VmY+X3neBnyLont6XO0c7ntuwh0R+1HchPvuJrdJDVA5qXgzsCkzP9/s9jRSRHRFxK9Ufj4AeD/wf5vaqAbJzKsz84jMXETx7/2+zDy/yc1qmIiYWxlAQETMBf4LMOFoubYN98zcBVwG/G+KE2rfyMzHmtuqxomIW4G1wLERsTkiLmx2mxroFOACisptY+XxwWY3qkEWAPdHxI8pCpx7M7PjhgR2qG5gTUT8CHgY+HZmfmeijdt2KKQkaWJtW7lLkiZmuEtSCRnuklRChrsklZDhLkklZLhLUgkZ7pJUQv8fQypaGq0cW2YAAAAASUVORK5CYII=\n", + "image/png": "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", "text/plain": [ "
" ] @@ -1259,7 +302,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3.9.19 ('matplotlib')", "language": "python", "name": "python3" }, @@ -1273,7 +316,12 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "1c3a946ddf3ee7cda41fa133e6366d1351543b92c771f65a565514f942d3e40d" + } } }, "nbformat": 4, diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..00ba4b4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,42 @@ +appnope==0.1.4 +asttokens==2.4.1 +comm==0.2.2 +contourpy==1.2.0 +cycler==0.12.1 +debugpy==1.8.1 +decorator==5.1.1 +exceptiongroup==1.2.0 +executing==2.0.1 +fonttools==4.50.0 +importlib_metadata==7.1.0 +importlib_resources==6.4.0 +ipykernel==6.29.4 +ipython==8.18.1 +jedi==0.19.1 +jupyter_client==8.6.1 +jupyter_core==5.7.2 +kiwisolver==1.4.5 +matplotlib==3.8.3 +matplotlib-inline==0.1.6 +nest-asyncio==1.6.0 +numpy==1.26.4 +packaging==24.0 +parso==0.8.3 +pexpect==4.9.0 +pillow==10.2.0 +platformdirs==4.2.0 +prompt-toolkit==3.0.43 +psutil==5.9.8 +ptyprocess==0.7.0 +pure-eval==0.2.2 +Pygments==2.17.2 +pyparsing==3.1.2 +python-dateutil==2.9.0.post0 +pyzmq==25.1.2 +six==1.16.0 +stack-data==0.6.3 +tornado==6.4 +traitlets==5.14.2 +typing_extensions==4.10.0 +wcwidth==0.2.13 +zipp==3.18.1