From 3fd916e189dd492db3cbdca57c9d3d3727438dbb Mon Sep 17 00:00:00 2001 From: Dieter Weber Date: Mon, 15 Apr 2024 18:34:30 +0200 Subject: [PATCH 1/6] Make calculation conform to figure in https://arxiv.org/abs/2403.08538 Previously, the camera length was measured from the focus point, not the specimen plane as written in the paper --- .../util/stem_overfocus_sim.py | 4 +- tests/test_overfocus.py | 44 ++++++++++--------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/microscope_calibration/util/stem_overfocus_sim.py b/src/microscope_calibration/util/stem_overfocus_sim.py index a2bcbff..f2e88cf 100644 --- a/src/microscope_calibration/util/stem_overfocus_sim.py +++ b/src/microscope_calibration/util/stem_overfocus_sim.py @@ -70,8 +70,8 @@ def detector_px_to_specimen_px( overfocus, transformation_matrix, fov_size_y, fov_size_x): position_y, position_x = (y_px - cy) * detector_pixel_size, (x_px - cx) * detector_pixel_size position_y, position_x = transformation_matrix @ np.array((position_y, position_x)) - specimen_position_y = position_y / camera_length * overfocus - specimen_position_x = position_x / camera_length * overfocus + specimen_position_y = position_y / (overfocus + camera_length) * overfocus + specimen_position_x = position_x / (overfocus + camera_length) * overfocus specimen_px_x = specimen_position_x / scan_pixel_size + fov_size_x / 2 specimen_px_y = specimen_position_y / scan_pixel_size + fov_size_y / 2 return specimen_px_y, specimen_px_x diff --git a/tests/test_overfocus.py b/tests/test_overfocus.py index c4b3e2b..45095c9 100644 --- a/tests/test_overfocus.py +++ b/tests/test_overfocus.py @@ -60,7 +60,7 @@ def test_get_transformation_matrix(params): 'y_px': 3., 'x_px': -7., }, - (3, -7) + (1.5, -3.5) ), ( { @@ -68,7 +68,7 @@ def test_get_transformation_matrix(params): 'x_px': -7., 'transformation_matrix': np.array(((-1., 0.), (0., -1.))), }, - (-3, 7) + (-1.5, 3.5) ), ( { @@ -76,7 +76,7 @@ def test_get_transformation_matrix(params): 'y_px': 3., 'x_px': -7., }, - (6, -14) + (3, -7) ), ( { @@ -85,7 +85,9 @@ def test_get_transformation_matrix(params): 'y_px': 3., 'x_px': -7., }, - (3, -7) + # Factor 2 from pixel size ratio, factor 3 from + # overfocus / (camera length + overfocus) + (3*2/3, -7*2/3) ), ( { @@ -94,7 +96,9 @@ def test_get_transformation_matrix(params): 'y_px': 3., 'x_px': -7., }, - (3, -7) + # Factor 10 from pixel size ratio, factor 0.11 from + # overfocus / (camera length + overfocus) + (3/1.1, -7/1.1) ), ( { @@ -103,7 +107,8 @@ def test_get_transformation_matrix(params): 'y_px': 3., 'x_px': -7., }, - (2, -12) + # (y_px - cy) * overfocus / (camera length + overfocus) + ((3 - 1)/2, (-7 - 5)/2) ), ( { @@ -112,7 +117,8 @@ def test_get_transformation_matrix(params): 'fov_size_y': 4, 'fov_size_x': 6, }, - (5, -4) + # (y_px - fov_size_y) * overfocus / (camera length + overfocus) + ((3 + 4) / 2, (-7 + 6) / 2) ), ( { @@ -128,9 +134,7 @@ def test_get_transformation_matrix(params): 'fov_size_x': 10, 'transformation_matrix': np.array(((-1., 0.), (0., -1.))), }, - # y: (-3 + 17) * 2 + 2 - # x: (7 + 19) * 2 + 5 - (30, 57) + ((-3 + 17) * 2/2 + 2, (7 + 19) * 2/2 + 5) ), ( { @@ -140,7 +144,7 @@ def test_get_transformation_matrix(params): 'x_px': -7., 'transformation_matrix': np.array(((-1., 0.), (0., 1.))), }, - (-3, -7) + (3 * -1 * 10 * 0.1/1.1, -7 * 1 * 10 * 0.1 / 1.1) ), ( { @@ -152,7 +156,7 @@ def test_get_transformation_matrix(params): 'fov_size_x': 10, 'transformation_matrix': np.array(((-1., 0.), (0., 1.))), }, - (-1, -2) + (-1 * (3 * 10 * 0.1/1.1 - 4/2), 1 * (-7 * 10 * 0.1 / 1.1 + 10/2)), ), ] ) @@ -179,8 +183,8 @@ def test_detector_specimen_px(params): def test_project(): size = 16 params = OverfocusParams( - overfocus=0.1, - scan_pixel_size=0.1, + overfocus=1, + scan_pixel_size=0.5, camera_length=1, detector_pixel_size=1, semiconv=0.004, @@ -203,8 +207,8 @@ def test_project(): def test_project_2(): size = 16 params = OverfocusParams( - overfocus=0.1, - scan_pixel_size=0.1, + overfocus=1, + scan_pixel_size=0.5, camera_length=1, detector_pixel_size=1, semiconv=0.004, @@ -227,8 +231,8 @@ def test_project_2(): def test_project_3(): size = 16 params = OverfocusParams( - overfocus=0.1, - scan_pixel_size=0.1, + overfocus=1, + scan_pixel_size=0.5, camera_length=1, detector_pixel_size=0.5, semiconv=0.004, @@ -254,8 +258,8 @@ def test_project_3(): def test_project_rotate(): size = 16 params = OverfocusParams( - overfocus=0.1, - scan_pixel_size=0.1, + overfocus=1, + scan_pixel_size=0.5, camera_length=1, detector_pixel_size=1, semiconv=0.004, From f575f23fe296ba064595b88f708b6b92529e9488 Mon Sep 17 00:00:00 2001 From: Dieter Weber Date: Mon, 15 Apr 2024 18:40:16 +0200 Subject: [PATCH 2/6] Changelog entry of sorts --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index a23b852..d72a6f0 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,15 @@ Tools to calibrate a microscope ## Rotation and handedness See preprint at https://arxiv.org/abs/2403.08538 for a description and https://github.com/LiberTEM/Microscope-Calibration/blob/main/examples/stem_overfocus.ipynb for an example. + +### Changelog + +### Since deposition https://doi.org/10.5281/zenodo.10418769 + +* Fix definition of camera length in the simulator to match figure in + https://arxiv.org/pdf/2403.08538.pdf, PR + https://github.com/LiberTEM/Microscope-Calibration/pull/17. Preciously, the + camera length was defined from the focus point, not the specimen plane. See + also https://github.com/TemGym/TemGym/pull/33 for the corresponding update in + TemGym. Note that the TemGym model used for calculation was correct, only the + alternative manual ray tracing implementation was affected. From e0d6bc234e3dd51bbdcfda122f4db64182d2e267 Mon Sep 17 00:00:00 2001 From: Dieter Weber Date: Mon, 15 Apr 2024 18:41:41 +0200 Subject: [PATCH 3/6] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d72a6f0..b1cb65c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ See preprint at https://arxiv.org/abs/2403.08538 for a description and https://g * Fix definition of camera length in the simulator to match figure in https://arxiv.org/pdf/2403.08538.pdf, PR - https://github.com/LiberTEM/Microscope-Calibration/pull/17. Preciously, the + https://github.com/LiberTEM/Microscope-Calibration/pull/17. Previously, the camera length was defined from the focus point, not the specimen plane. See also https://github.com/TemGym/TemGym/pull/33 for the corresponding update in TemGym. Note that the TemGym model used for calculation was correct, only the From e80f0352011d345bd22c4bbaf62e22d2a0dc2ef7 Mon Sep 17 00:00:00 2001 From: Dieter Weber Date: Tue, 16 Apr 2024 11:11:02 +0200 Subject: [PATCH 4/6] Review @sk1p Thx! :-) --- prototypes/testbed.ipynb | 25426 +--------------- .../util/stem_overfocus_sim.py | 33 + tests/test_overfocus.py | 217 +- 3 files changed, 1071 insertions(+), 24605 deletions(-) diff --git a/prototypes/testbed.ipynb b/prototypes/testbed.ipynb index 305601d..9df4bc0 100644 --- a/prototypes/testbed.ipynb +++ b/prototypes/testbed.ipynb @@ -8,7 +8,7 @@ "outputs": [], "source": [ "%load_ext autoreload\n", - "%matplotlib nbagg" + "%matplotlib widget" ] }, { @@ -40,6 +40,80 @@ { "cell_type": "code", "execution_count": 4, + "id": "75b85d71-a5a0-43ec-bc2a-9949578de84a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "85d84b7c7bc94036940db3ef4b17422f", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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Snl5eVqwYIGampqSeMYAko3cAJAMNID9qLS0VHfffbfq6ur02muvaebMmZozZ47eeecdSdLSpUv11FNPaf369aqtrdWBAwc0f/78JJ81gGQiNwAkA4tA+tHs2bPjPv/Zz36mVatWadu2bSotLdVDDz2ktWvXaubMmZKkNWvW6JxzztG2bdt04YX2YdneXFvyqnLyen58tiFr24C1lNiQtW3AWpI2755kHjNkPu7b48270o/NHG495oMfm0PWwT05Rq1zgjngbbv7veT/Dvh+734vJTZkbRuwlhIbsrbtziD536HB7+4MkrkIINZhfn/x2ciNU45JbsQhNzBQeAdwgESjUa1bt07t7e2qqKhQXV2durq6VFlZ2f2YyZMnq6ysTFu3mv/RAnAPuQFgsPAOYD976623VFFRoY6ODuXl5WnDhg0699xztXPnTgWDQY0YMSLu8UVFRWpsbOz1eJFIRJFIzz8rW1paBurUASQJuQFgsPEOYD87++yztXPnTm3fvl233HKLFi5cqHffffcLH6+6ulrhcLj7Y9y4cf14tgBSAbkBYLDRAPazYDCoCRMmqLy8XNXV1ZoyZYruu+8+FRcXq7OzU0ePHo17fFNTk4qLi3s93ooVK9Tc3Nz90dDQMMBXAGCwkRsABhsN4ACLxWKKRCIqLy9XVlaWNm3qudN8fX299u3bp4oK+9C1JIVCoe7bQ5z8ADC0kRsABhozgP1oxYoVuvLKK1VWVqbW1latXbtWW7Zs0XPPPadwOKwbb7xRy5YtU2FhoQoKCrR48WJVVFT0eSWfJF2as1/5uT39u22VnW2FnZTYKjvbCjspsVV2thV2UmKr7Gwr7KTEVtnZVthJia2ys62wkxJbZWfbnkvyv0WX3+25JHMVaPRYL3tUoVfkRjxyIx65gYFCA9iPDh06pOuvv14HDx5UOBzW+eefr+eee06XX365JOnee+9VIBDQggULFIlENGvWLD3wwANJPmsAyURuAEgGGsB+9NBDD33m17Ozs1VTU6OamppBOiMAqY7cAJAMzAACAAA4hncA04znfTKn0dYWi6u3Rc05kdgxcx5EkqId5mM72rqMWkso5utxnxzTfC3b67e1mscMZtpnT2xzIdGIeczOtk6j1mJ5HUk63m7O3cRs554VNWrtrWZNklo6zdc60e7v3G2Pk+zn3x4xXz923HLuHZnW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", + "text/html": [ + "\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "size = 32\n", + "params = OverfocusParams(\n", + " overfocus=1,\n", + " scan_pixel_size=1,\n", + " camera_length=1,\n", + " detector_pixel_size=1,\n", + " semiconv=0.004,\n", + " cy=size*2/2,\n", + " cx=size*2/2,\n", + " scan_rotation=0,\n", + " flip_y=False\n", + ")\n", + "obj = smiley(size)\n", + "projected = project(\n", + " image=obj,\n", + " scan_shape=(size, size),\n", + " detector_shape=(size*2, size*2),\n", + " sim_params=params,\n", + ")\n", + "\n", + "fig, axes = plt.subplots(2, 2)\n", + "\n", + "axes[0, 0].imshow(obj)\n", + "axes[0, 1].imshow(projected[size//2, size//2, ::2, ::2])\n", + "axes[1, 0].imshow(obj)\n", + "axes[1, 1].imshow(projected[:, :, size*2//2, size*2//2])\n", + "\n", + "#assert_allclose(obj, projected[size//2, size//2, ::2, ::2])\n", + "#assert_allclose(obj, projected[::2, ::2, size//2, size//2])" + ] + }, + { + "cell_type": "code", + "execution_count": 5, "id": "bc0dcc61", "metadata": {}, "outputs": [ @@ -54,7 +128,7 @@ " 'cx': 0}" ] }, - "execution_count": 4, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -68,22 +142,22 @@ " cy=0,\n", " cx=0,\n", ")\n", - "p" + "p\t" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "id": "da01928a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(0.0, 1.0)" + "(0.0, 0.5)" ] }, - "execution_count": 5, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -101,7 +175,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "id": "50ced9b6", "metadata": {}, "outputs": [], @@ -130,970 +204,109 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "id": "6e96ba6c", "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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", + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4fbcd821bab34487b59e05426d3d19ef", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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AQAyIwACAGRGAAQAyIwACACQGQEQACAzAiAAQGYEQACAzAiAAACZEQABADIjAAIAZEYABADIjAAIAJAZARAAIDMCIABAZgRAAIDMCIAAAJkRAAEAMiMAAgBkRgAEAMiMAAgAkBkBEAAgMwIgAEBmBEAAgMwIgAAAmREAAQAyIwACAGRGAAQAyIwACACQGQEQACAzAiAAQGYEQACAzAiAAACZEQABADIjAAIAZEYABADIjAAIAJAZARAAIDMCIABAZgRAAIDMCIAAAJkRAAEAMiMAAgBkRgAEAMiMAAgAkBkBEAAgMwIgAEBmBEAAgMwIgAAAmREAAQAyIwACAGRGAAQAyIwACACQGQEQACAzAiAAQGYEQACAzAiAAACZEQABADIjAAIAZEYABADIjAAIAJAZARAAIDMCIABAZgRAAIDMCIAAAJkRAAEAMiMAAgBkRgAEAMiMAAgAkBkBEAAgMwIgAEBmBEAAgMwIgAAAmREAAQAyIwACAGRGAAQAyIwACACQGQEQACAzAiAAQGYEQACAzAiAAACZEQABADIjAAIAZEYABADIjAAIAJAZARAAIDMCIABAZgRAAIDMCIAAAJkRAAEAMiMAAgBkRgAEAMiMAAgAkBkBEAAgMwIgAEBmBEAAgMwIgAAAmREAAQAyIwACAGRGAAQAyIwACACQGQEQACAzAiAAQGYEQACAzAiAAACZEQABADIjAAIAZEYABADIjAAIAJAZARAAIDMCIABAZgRAAIDMCIAAAJn5f1X6GIVdRNHEAAAAAElFTkSuQmCC", + "text/html": [ "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " fig.ondownload(fig, null);\n", - "};\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ffd126179d2b4f46881f1dcd4e2b25c9", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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AQAyIwACAGRGAAQAyIwACACQGQEQACAzAiAAQGYEQACAzAiAAACZEQABADIjAAIAZEYABADIjAAIAJAZARAAIDMCIABAZgRAAIDMCIAAAJkRAAEAMiMAAgBkRgAEAMiMAAgAkBkBEAAgMwIgAEBmBEAAgMwIgAAAmREAAQAyIwACAGRGAAQAyIwACACQGQEQACAzAiAAQGYEQACAzAiAAACZEQABADIjAAIAZEYABADIjAAIAJAZARAAIDMCIABAZgRAAIDMCIAAAJkRAAEAMiMAAgBkRgAEAMiMAAgAkBkBEAAgMwIgAEBmBEAAgMwIgAAAmREAAQAyIwACAGRGAAQAyIwACACQGQEQACAzAiAAQGYEQACAzAiAAACZEQABADIjAAIAZEYABADIjAAIAJAZARAAIDMCIABAZgRAAIDMCIAAAJkRAAEAMiMAAgBkRgAEAMiMAAgAkBkBEAAgMwIgAEBmBEAAgMwIgAAAmREAAQAyIwACAGRGAAQAyIwACACQGQEQACAzAiAAQGYEQACAzAiAAACZEQABADIjAAIAZEYABADIjAAIAJAZARAAIDMCIABAZgRAAIDMCIAAAJkRAAEAMiMAAgBkRgAEAMiMAAgAkBkBEAAgMwIgAEBmBEAAgMwIgAAAmREAAQAyIwACAGRGAAQAyIwACACQGQEQACAzAiAAQGYEQACAzAiAAACZEQABADIjAAIAZEYABADIjAAIAJAZARAAIDMCIABAZgRAAIDMCIAAAJn5f1X6GIVdRNHEAAAAAElFTkSuQmCC", + "text/html": [ "\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", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axes = plt.subplots(1, 3)\n", + "axes[0].imshow(obj)\n", + "axes[1].imshow(projected[:, :, size//2, size//2])\n", + "axes[2].imshow(projected[:, :, size//2, size//2] - obj)\n", + "\n", + "fig, axes = plt.subplots(1, 3)\n", + "axes[0].imshow(obj)\n", + "axes[1].imshow(projected[size//2, size//2, :])\n", + "axes[2].imshow(projected[size//2, size//2, :] - obj)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "984405c9", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5395aed8b71947529d3ddcf14f5fdd32", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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", + "text/html": [ "\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" + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " ], "text/plain": [ - "" + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" ] }, "metadata": {}, @@ -1101,11 +314,24 @@ }, { "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "35f010e01e9a469b8ca9dddc421a6131", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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e+/p7bff1ueff653331XktSqVSv99re/1TPPPKOxY8e6f/euv/56Sb+EfXp6urp06aKpU6fKx8dHc+bM0U033aS//OUv6tatmyTp66+/dh+PadOm6cyZM5o6dar7d+RSZGRk6JtvvtH48ePVokULHT58WKtXr9b+/fvdv0uXquL1nD59ujZt2qS3335bwcHB+uyzzxQXF6fnnntOf/7znzVz5ky1b99ew4cPv6yfA9R7BkCNKiwsNJLMwIEDz7vdv/3bvxlJpri42BhjzLBhw0x4eLg5c+aMe5tDhw4ZHx8f89vf/ta9rG/fvqZDhw7m1KlT7mXl5eXm+uuvN61atXIvmzNnjpFkbrjhBo/nNMaYTz/91EgyCxcu9FjeuXNnEx4ebo4dO+Ze9tVXXxkfHx8zfPhw97Lhw4cbHx8f88UXX1Tar/LycmOMMVOnTjVV/S+mYq69e/caY4xZsmSJkVTlc1XYu3evkWRmzpxZ5fqZM2d6PKcxxvTu3du0a9eu2ues+Lmvvvqqe1l8fLyRVOk2depUY8z/vW4V96vzt7/9rcrX91ySjL+/v9mzZ4972VdffWUkmddff9297NzXzBhjRowYYRo3buzxfF988YWRZObMmeOxvLy83LRq1cqkpaW5j48xxpw8edIkJCSYm2++2b1s0KBBpmHDhua7775zL/v222+Nr69vlcezOj/99NN5j1mF6l7P+Ph4M2LECPf9itfg3H1ISUkxDofDPPTQQ+5lZ86cMTExMaZ3794XPS9gG94CBmrY8ePHJUmBgYHn3a5ifXFxsSRpyJAhOnz4sNatW+feZtGiRSovL9eQIUMkST/++KPWrl2ru+66S8ePH9fRo0d19OhRHTt2TGlpadq9e7d++OEHj58zZsyYStePVeXQoUPKzc3VyJEjFRIS4l7esWNH3Xzzzfrzn/8sSSovL9fSpUs1YMAAXXfddZWe51K/KqTiOsSPPvpIZWVll/TYK9GkSRNJ/3e8KiQnJ2v16tUet4qzSH369JEx5rxn/yS5z/CtXLlSJ0+ePO+2qampSkpKct/v2LGjgoKC9Pe///1Sd6laubm52r17t+6++24dO3bM/XtTUlKivn37av369SovL9fZs2e1cuVKDRo0SHFxce7HX3vttUpLS7ukn1lxfeK6dev0008/1di+jB492uN3LDk5WcYYjR492r3M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", "text/html": [ - "" + "\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " ], "text/plain": [ - "" + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" ] }, "metadata": {}, @@ -1113,964 +339,49 @@ }, { "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", + "application/vnd.jupyter.widget-view+json": { + "model_id": "77b74f8086de46b993bfd06a26689271", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAvQ0lEQVR4nO3de1TVdb7/8dcGYYsKm1CuCoiXtLyuQ4rktSSQyjQtb5Vapl0wRz3V5JzMPFPR5ExajWZ1zqSnIk3Hy9hMmmliNtqMFpmNcpSjiSmYNmwUdYvy+f3Rjz3tQPMGW/k8H2vttdzf73d/9/vL16XP9d0XHMYYIwAAAFgjwN8DAAAAoHYRgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABnLe///3vuv7669WwYUM5HA7l5eX5eyScwejRo9W8eXN/j3FBHA6Hnn76aX+PAdRJBCBwmfr666919913q2nTpnI6nYqLi9Ndd92lr7/+2q9zlZeX684779T333+vmTNn6q233lJiYqJfZzqbPXv2yOFw6Le//W2163/729/K4XBoz5493mV9+vSRw+GQw+FQQECAwsLC1KZNG91zzz1avXp1tftp3ry59zE/vZ04caImDu2ykJOTo1mzZvl7DADnqZ6/BwBQ1ZIlSzR8+HBFRERozJgxSkpK0p49e/Tf//3fWrx4sRYsWKDbb7/dL7MVFBTom2++0RtvvKH777/fLzPUhmbNmik7O1uSVFZWpl27dmnJkiV6++23NWTIEL399tsKCgryeUznzp317//+71X2FRwcXCsz+0NOTo62bdumiRMn+nsUAOeBAAQuMwUFBbrnnnvUokULrV+/XpGRkd51v/jFL9SzZ0/dc8892rp1q1q0aFFrc5WVlalhw4Y6ePCgJCk8PLzWntsfXC6X7r77bp9lzz//vCZMmKA5c+aoefPm+s1vfuOzvmnTplUeAwCXI14CBi4zM2bM0LFjx/T666/7xJ8kNWnSRK+99prKysr0wgsvSJIWL14sh8Oh3NzcKvt67bXX5HA4tG3bNu+yHTt26I477lBERITq16+v6667Tn/60598Hjdv3jzvPh9++GFFRUWpWbNmGj16tHr37i1JuvPOO+VwONSnTx/v49auXauePXuqYcOGCg8P14ABA7R9+/Yqc3377bcaM2aM4uLi5HQ6lZSUpIceekgnT56UJD399NNyOBxVHlc5149frt28ebMyMjLUpEkThYSEKCkpSffdd9/P/JQvTGBgoF5++WVde+21+v3vfy+3233Ojz127Jh27NihQ4cO/ey2O3fu1ODBgxUTE6P69eurWbNmGjZsWJXne/vtt5WcnKyQkBBFRERo2LBhKiws/Nn9V1RUaNasWWrXrp3q16+v6OhoPfDAA/rnP/9ZZdsPPvhAvXv3VmhoqMLCwtSlSxfl5ORI+uGl8j//+c/65ptvvC93//j9hh6PR9OmTVOrVq3kdDoVHx+vxx9/XB6Px+c5PB6PJk2apMjISIWGhuq2227Tvn37fvY4AFw4rgACl5kVK1aoefPm6tmzZ7Xre/XqpebNm+vPf/6zJOmWW25Ro0aN9N5773njrNLChQvVrl07tW/fXtIP7yvs3r27mjZtqieeeEINGzbUe++9p4EDB+qPf/xjlZeVH374YUVGRuqpp55SWVmZevXqpaZNm+q5557ThAkT1KVLF0VHR0uSPvroI2VmZqpFixZ6+umndfz4cb3yyivq3r27Pv/8c28Y7N+/X127dlVJSYnGjRuntm3b6ttvv9XixYt17Nix83q59ODBg0pPT1dkZKSeeOIJhYeHa8+ePVqyZMk57+N8BQYGavjw4Zo6dao2bNigW265xbuuvLy8SuA1aNBADRo00N/+9jfdcMMNmjZt2lk/2HDy5EllZGTI4/HokUceUUxMjL799lu9//77KikpkcvlkiQ9++yzmjp1qoYMGaL7779f3333nV555RX16tVLX3zxxVmv0D7wwAOaN2+e7r33Xk2YMEG7d+/W73//e33xxRf69NNPvS9tz5s3T/fdd5/atWunKVOmKDw8XF988YVWrlypESNG6D/+4z/kdru1b98+zZw5U5LUqFEjST9E5m233aYNGzZo3Lhxuuaaa/TVV19p5syZ+t///V8tW7bMO8/9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6o033qiy7vjx4yorK5MkZWZmSpJefvlln2347SJAzeIKIHCZad26tebPn6+77rpLHTp0qPKbQA4dOqR33323ynumgoKCNGjQIC1YsEBlZWXV/uqz2bNnq0ePHurQoYPGjh2rFi1aqLi4WBs3btS+ffv05ZdfXvDcM2bMUGZmplJTUzVmzBjv18C4XC6fDz4899xz+vDDD9W7d2/v14McOHBAixYt0oYNGxQeHq709HQlJCRozJgxeuyxxxQYGKg//OEPioyM9Im4+fPna86cObr99tvVsmVLHTlyRG+88YbCwsK80Vn5nN26ddO//du/ady4cWrevLn27Nmj119/XQ6Hw+el8kput1tvv/22pB/irfI3gRQUFGjYsGHVBtTZnOvXwKxdu1bjx4/XnXfeqauvvlqnTp3SW2+9pcDAQA0ePFjSD4H8zDPPaMqUKdqzZ48GDhyo0NBQ7d69W0uXLtW4ceP06KOPVrv/3r1764EHHlB2drby8vKUnp6uoKAg7dy5U4sWLdJLL72kO+64Q2FhYZo5c6buv/9+denSRSNGjNBVV12lL7/8UseOHfPGeHJyshYuXKjJkyerS5cuatSokfr376977rlH7733nh588EF9/PHH6t69u06fPq0dO3bovffe06pVq3Tdddepc+fOGj58uObMmSO3263rr79ea9as0a5du87r5wvgPPnr48cAzm7r1q1m+PDhJjY21gQFBZmYmBgzfPhw89VXX53xMatXrzaSjMPhMIWFhdVuU1BQYEaOHGliYmJMUFCQadq0qbn11lvN4sWLvdtUft1KdV+vcqavgTHGmI8++sh0797dhISEmLCwMNO/f3/zj3/8o8p233zzjRk5cqSJjIw0TqfTtGjRwmRlZRmPx+PdZsuWLSYlJcUEBwebhIQE8+KLL1b5GpjPP//cDB8+3CQkJBin02mioqLMrbfeajZv3lzlObdv326GDh1qoqKiTL169UxUVJQZNmyY2b59e5Vte/fu7fNVLo0aNTKtW7c2d999t/nwww+r/bkmJiaaW265pdp1P/65/dzXmvzf//2fue+++0zLli1N/fr1TUREhLnhhhvMRx99VGXbP/7xj6ZHjx6mYcOGpmHDhqZt27YmKyvL5Ofne7f56dfAVHr99ddNcnKyCQkJMaGhoaZDhw7m8ccfN/v37/fZ7k9/+pO5/vrr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", + "text/html": [ "\n", - " parent_element.appendChild(this.root);\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "af84e6c10e114c148d20f4e05081de16", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAArmElEQVR4nO3de3TU9Z3/8dckJMMtmRhzmYQQCBdBuZ4FiSkIKCkhKhsEFagKaIQVg1ZYtcUjIlvXUGm9LoJtt8BWEYQVWGi9IEgou4EW3BShkkIKgkDCRZOBIEMgn98f/jLbMUG5JPMt83k+zvme43y/35l5f+fbQ5/nO5e4jDFGAAAAsEaE0wMAAAAgtAhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAc88c//lHf+9731KpVK7lcLpWUlDg9EgBYgQAEwtzOnTt1zz33qE2bNnK73UpNTdXdd9+tnTt3OjpXTU2N7rzzTn3xxRd68cUX9Zvf/Ebt2rVzdKZvs2/fPrlcLv3sZz9rcPvPfvYzuVwu7du3L7Bu8ODBcrlccrlcioiIUGxsrLp06aJ7771Xa9eubfBx2rdvH7jPN5fTp083xaEBsFAzpwcA0HTeeecdjR07VvHx8crPz1dGRob27dunf//3f9fy5cu1ZMkS3X777Y7MVlZWps8++0y//OUv9cADDzgyQyikpaWpsLBQklRdXa09e/bonXfe0RtvvKG77rpLb7zxhqKiooLu07t3b/3zP/9zvceKjo4OycwAwh8BCISpsrIy3XvvverQoYM2btyoxMTEwLYf/vCHuvHGG3Xvvfdq+/bt6tChQ8jmqq6uVqtWrXTkyBFJUlxcXMie2wkej0f33HNP0LrZs2frkUce0Wuvvab27dvrpz/9adD2Nm3a1LsPADQm3gIGwtScOXN06tQp/eIXvwiKP0lKSEjQ66+/rurqaj3//POSpOXLl8vlcqmoqKjeY73++utyuVzasWNHYN2uXbt0xx13KD4+Xs2bN1ffvn31X//1X0H3W7hwYeAxH3roISUlJSktLU0TJkzQoEGDJEl33nmnXC6XBg8eHLjf+vXrdeONN6pVq1aKi4tTXl6ePv3003pzHTx4UPn5+UpNTZXb7VZGRoYmT56sM2fOSJKeeeYZuVyueverm+tv367dunWrcnJylJCQoBYtWigjI0P333//d7zKlyYyMlKvvPKKrrvuOv3bv/2bqqqqLvi+p06d0q5du3Ts2LHv3Hf37t0aNWqUvF6vmjdvrrS0NI0ZMybwfHVvay9cuLDefV0ul5555pnA7brX8i9/+YvuueceeTweJSYmasaMGTLG6MCBA8rLy1NsbKy8Xq9+/vOfX/AxAQg9rgACYWr16tVq3769brzxxga3Dxw4UO3bt9dvf/tbSdKtt96q1q1b6+233w7EWZ2lS5eqW7du6t69u6SvP1fYv39/tWnTRj/+8Y/VqlUrvf322xoxYoT+8z//s97byg899JASExP19NNPq7q6WgMHDlSbNm303HPP6ZFHHtH111+v5ORkSdKHH36o3NxcdejQQc8884y++uorvfrqq+rfv78+/vhjtW/fXpJ06NAh9evXT5WVlZo0aZK6du2qgwcPavny5Tp16tRFvV165MgRDR06VImJifrxj3+suLg47du3T++8884FP8bFioyM1NixYzVjxgxt2rRJt956a2BbTU1NvcBr2bKlWrZsqT/84Q+66aabNHPmzKBA+6YzZ84oJydHfr9fDz/8sLxerw4ePKg1a9aosrJSHo/nkuYePXq0rr32Ws2ePVu//e1v9eyzzyo+Pl6vv/66br75Zv30pz/Vm2++qccee0zXX3+9Bg4ceEnPA6CJGQBhp7Ky0kgyeXl537rfP/7jPxpJxufzGWOMGTt2rElKSjJnz54N7HP48GETERFh/uVf/iWwbsiQIaZHjx7m9OnTgXW1tbXme9/7nuncuXNg3YIFC4wkM2DAgKDHNMaYjz76yEgyy5YtC1rfu3dvk5SUZI4fPx5Y96c//clERESYcePGBdaNGzfOREREmD/+8Y/1jqu2ttYYY8zMmTNNQ//M1c21d+9eY4wxK1asMJIafKw6e/fuNZLMnDlzGtw+Z86coMc0xphBgwaZbt26nfcx65735ZdfDqxr166dkVRvmTlzpjHm/163utvn87//+78Nvr4NHdOCBQvqbfvmc9S9lpMmTQqsO3v2rElLSzMul8vMnj07sP7LL780LVq0MOPHj//WGQE4h7eAgTB04sQJSVJMTMy37le33efzSfr66s6RI0e0YcOGwD7Lly9XbW2tRo8eLUn64osvtH79et111106ceKEjh07pmPHjun48ePKycnR7t27dfDgwaDnmThxoiIjI79z7sOHD6ukpEQTJkxQfHx8YH3Pnj31/e9/X7/73e8kSbW1tVq5cqWGDx+uvn371nucht72/TZ1n0Ncs2aNampqLuq+l6N169aS/u981cnMzNTatWuDlnHjxkn6+pvFxphvvfonKXCF7/3339epU6cabea//cJOZGSk+vbtK2OM8vPzA+vj4uLUpUsX/fWvf2205wXQuAhAIAzVhd03w+KbvhmKw4YNk8fj0dKlSwP7LF26VL1799Y111wjSdqzZ4+MMZoxY4YSExODlpkzZ0pS4AsedTIyMi5o7s8++0yS1KVLl3rbrr32Wh07dkzV1dU6evSofD5f4C3pyzVo0CCNGjVKs2bNUkJCgvLy8rRgwQL5/f6LfqyLic+TJ09Kqh/qCQkJys7ODlou9os6GRkZmjZtmn71q18pISFBOTk5mjt37kV93rAh6enpQbc9Ho+aN2+uhISEeuu//PLLy3ouAE2HAATCkMfjUUpKirZv3/6t+23fvl1t2rRRbGysJMntdmvEiBFasWKFzp49q4MHD+q///u/A1f/pK+vvknSY489Vu8qVd3SqVOnoOdp0aJFIx/hhTlfjJ07d67efsuXL1dxcbGmTJmigwcP6v7771efPn0Ckda8eXNJ0ldffdXgY9ZdZavb70LUfanmm69XY/n5z3+u7du368knn9RXX32lRx55RN26ddPnn38u6cJfn7/V0JXc813dNcZcwtQAQoEABMLUbbfdpr1792rTpk0Nbv/973+vffv26bbbbgtaP3r0aB07dkzr1q3TsmXLZIwJCsC6K1FRUVH1rlLVLd/11vP51P0QdGlpab1tu3btUkJCglq1aqXExETFxsYGfSu5IVdddZUkqbKyMmh93ZXGb7rhhhv0r//6r9q6davefPNN7dy5U0uWLJEkJSYmqmXLlg3OVjdzy5Yt610JO59z585p8eLFatmypQYMGHBB97kUPXr00FNPPaWNGzfq97//vQ4ePKj58+dLuvjXB0D4IACBMPX444+rRYsW+qd/+icdP348aNsXX3yhBx98UC1bttTjjz8etC07O1vx8fFaunSpli5dqn79+gW9hZuUlKTBgwfr9ddf1+HDh+s979GjRy955pSUFPXu3VuLFi0KipIdO3bogw8+0C233CJJioiI0IgRI7R69Wpt3bq13uPUXXnq2LGjJGnjxo2BbdXV1Vq0aFHQ/l9++WW9q1W9e/eWpMDbwJGRkRo6dKhWr16t/fv3B+27f/9+rV69WkOHDr2gzzqeO3dOjzzyiD799FM98sgjgSuwF+JCfwbG5/Pp7NmzQet69OihiIiIwDHFxsYqISEh6PWRpNdee+2C5wFwZeJnYIAw1blzZy1atEh33323evToUe8vgRw7dkxvvfVWIJLqREVFaeTIkVqyZImqq6sb/NNnc+fO1YABA9SjRw9NnDhRHTp0UEVFhYqLi/X555/rT3/60yXPPWfOHOXm5iorK0v5+fmBn4HxeDxBX3x47rnn9MEHH2jQoEGaNGmSrr32Wh0+fFjLli3Tpk2bFBcXp6FDhyo9PV35+fl6/PHHFRkZqV//+tdKTEwMirhFixbptdde0+23366OHTvqxIkT+uUvf6nY2NhAdNY95w033KB/+Id/0KRJk9S+fXvt27dPv/jFL+RyufTcc8/VO56qqiq98cYbkr6Ot7q/BFJWVqYxY8boJz/5yUW9Phf6MzDr16/XlClTdOedd+qaa67R2bNn9Zvf/EaRkZEaNWpUYL8HHnhAs2fP1gMPPKC+fftq48aN+stf/nJRMwG4Ajn4DWQAIbB9+3YzduxYk5KSYqKioozX6zVjx441n3zyyXnvs3btWiPJuFwuc+DAgQb3KSsrM+PGjTNer9dERUWZNm3amNtuu80sX748sE/dz6009PMq5/sZGGOM+fDDD03//v1NixYtTGxsrBk+fLj585//XG+/zz77zIwbN84kJiYat9ttOnToYAoKCozf7w/ss23bNpOZmWmio6NNenq6eeGFF+r9DMzHH39sxo4da9LT043b7TZJSUnmtttuM1u3bq33nJ9++qkZPXq0SUpKMs2aNTNJSUlmzJgx5tNPP62376BBg4J+yqV169amc+fO5p577jEffPBBg69ru3btzK233trgtr993b7rZ2D++te/mvvvv9907NjRNG/e3MTHx5ubbrrJfPjhh0H7nTp1yuTn5xuPx2NiYmLMXXfdZY4cOXLen4E5evRo0P3Hjx9vWrVq1eCxf9tP4ABwlssYPqULAABgEz4DCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGvwSCS1JbW6tDhw4pJibmvH9QHgDw98sYoxMnTig1NVUREVwPsg0BiEty6NAhtW3b1ukxAACX6cCBA0pLS3N6DIQYAWi5uXPnas6cOSovL1evXr306quvql+/ft95v5iYGEnSAN2iZopq6jEBAI3srGq0Sb8L/HsOuxCAFlu6dKmmTZum+fPnKzMzUy+99JJycnJUWlqqpKSkb71v3du+zRSlZi4CEACuOP//D8HyMR478aa/xV544QVNnDhR9913n6677jrNnz9fLVu21K9//WunRwMAAE2IALTUmTNntG3bNmVnZwfWRUREKDs7W8XFxfX29/v98vl8QQsAALgyEYCWOnbsmM6dO6fk5OSg9cnJySovL6+3f2FhoTweT2DhCyAAAFy5CEBckOnTp6uqqiqwHDhwwOmRAADAJeJLIJZKSEhQZGSkKioqgtZXVFTI6/XW29/tdsvtdodqPAAA0IS4Amip6Oho9enTR+vWrQusq62t1bp165SVleXgZAAAoKlxBdBi06ZN0/jx49W3b1/169dPL730kqqrq3Xfffc5PRoAAGhCBKDFRo8eraNHj+rpp59WeXm5evfurffee6/eF0MAAEB4cRljjNND4Mrj8/nk8Xg0WHn8EDQAXIHOmhpt0CpVVVUpNjbW6XEQYnwGEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBaKlnnnlGLpcraOnatavTYwEAgBBo5vQAcE63bt304YcfBm43a8b/HAAAsAH/j2+xZs2ayev1Oj0GAAAIMd4Cttju3buVmpqqDh066O6779b+/fvPu6/f75fP5wtaAADAlYkAtFRmZqYWLlyo9957T/PmzdPevXt144036sSJEw3uX1hYKI/HE1jatm0b4okBAEBjcRljjNNDwHmVlZVq166dXnjhBeXn59fb7vf75ff7A7d9Pp/atm2rwcpTM1dUKEcFADSCs6ZGG7RKVVVVio2NdXochBifAYQkKS4uTtdcc4327NnT4Ha32y232x3iqQAAQFPgLWBIkk6ePKmysjKlpKQ4PQoAAGhiBKClHnvsMRUVFWnfvn36n//5H91+++2KjIzU2LFjnR4NAAA0Md4CttTnn3+usWPH6vjx40pMTNSAAQO0efNmJSYmOj0aAABoYgSgpZYsWeL0CAAAwCG8BQwAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAIahjRs3avjw4UpNTZXL5dLKlSuDthtj9PTTTyslJUUtWrRQdna2du/e7cywAAAg5AjAMFRdXa1evXpp7ty5DW5//vnn9corr2j+/PnasmWLWrVqpZycHJ0+fTrEkwIAACc0c3oANL7c3Fzl5uY2uM0Yo5deeklPPfWU8vLyJEn/8R//oeTkZK1cuVJjxowJ5agAAMABXAG0zN69e1VeXq7s7OzAOo/Ho8zMTBUXFzs4GQAACBWuAFqmvLxckpScnBy0Pjk5ObCtIX6/X36/P3Db5/M1zYAAAKDJcQUQF6SwsFAejyewtG3b1umRAADAJSIALeP1eiVJFRUVQesrKioC2xoyffp0VVVVBZYDBw406ZwAAKDpEICWycjIkNfr1bp16wLrfD6ftmzZoqysrPPez+12KzY2NmgBAABXJj4DGIZOnjypPXv2BG7v3btXJSUlio+PV3p6uh599FE9++yz6ty5szIyMjRjxgylpqZqxIgRzg0NAABChgAMQ1u3btVNN90UuD1t2jRJ0vjx47Vw4UI98cQTqq6u1qRJk1RZWakBAwbovffeU/PmzZ0aGQAAhJDLGGOcHgJXHp/PJ4/Ho8HKUzNXlNPjAAAu0llTow1apaqqKj7WYyE+AwgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAxDGzdu1PDhw5WamiqXy6WVK1cGbZ8wYYJcLlfQMmzYMGeGBQAAIUcAhqHq6mr16tVLc+fOPe8+w4YN0+HDhwPLW2+9FcIJAQCAk5o5PQAaX25urnJzc791H7fbLa/XG6KJAADA3xOuAFpqw4YNSkpKUpcuXTR58mQdP37c6ZEAAECIcAXQQsOGDdPIkSOVkZGhsrIyPfnkk8rNzVVxcbEiIyMbvI/f75ff7w/c9vl8oRoXAAA0MgLQQmPGjAn8d48ePdSzZ0917NhRGzZs0JAhQxq8T2FhoWbNmhWqEQEAQBPiLWCoQ4cOSkhI0J49e867z/Tp01VVVRVYDhw4EMIJAQBAY+IKIPT555/r+PHjSklJOe8+brdbbrc7hFMBAICmQgCGoZMnTwZdzdu7d69KSkoUHx+v+Ph4zZo1S6NGjZLX61VZWZmeeOIJderUSTk5OQ5ODQAAQoUADENbt27VTTfdFLg9bdo0SdL48eM1b948bd++XYsWLVJlZaVSU1M1dOhQ/eQnP+EKHwAAliAAw9DgwYNljDnv9vfffz+E0wAAgL83fAkEAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEYhgoLC3X99dcrJiZGSUlJGjFihEpLS4P2OX36tAoKCnT11VerdevWGjVqlCoqKhyaGAAAhBIBGIaKiopUUFCgzZs3a+3ataqpqdHQoUNVXV0d2Gfq1KlavXq1li1bpqKiIh06dEgjR450cGoAABAqLmOMcXoINK2jR48qKSlJRUVFGjhwoKqqqpSYmKjFixfrjjvukCTt2rVL1157rYqLi3XDDTd852P6fD55PB4NVp6auaKa+hAAAI3srKnRBq1SVVWVYmNjnR4HIcYVQAtUVVVJkuLj4yVJ27ZtU01NjbKzswP7dO3aVenp6SouLm7wMfx+v3w+X9ACAACuTARgmKutrdWjjz6q/v37q3v37pKk8vJyRUdHKy4uLmjf5ORklZeXN/g4hYWF8ng8gaVt27ZNPToAAGgiBGCYKygo0I4dO7RkyZLLepzp06erqqoqsBw4cKCRJgQAAKHWzOkB0HSmTJmiNWvWaOPGjUpLSwus93q9OnPmjCorK4OuAlZUVMjr9Tb4WG63W263u6lHBgAAIcAVwDBkjNGUKVO0YsUKrV+/XhkZGUHb+/Tpo6ioKK1bty6wrrS0VPv371dWVlaoxwUAACHGFcAwVFBQoMWLF2vVqlWKiYkJfK7P4/GoRYsW8ng8ys/P17Rp0xQfH6/Y2Fg9/PDDysrKuqBvAAMAgCsbARiG5s2bJ0kaPHhw0PoFCxZowoQJkqQXX3xRERERGjVqlPx+v3JycvTaa6+FeFIAAOAEfgcQl4TfAQSAKxu/A2g3PgMIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAMQ4WFhbr++usVExOjpKQkjRgxQqWlpUH7DB48WC6XK2h58MEHHZoYAACEEgEYhoqKilRQUKDNmzdr7dq1qqmp0dChQ1VdXR2038SJE3X48OHA8vzzzzs0MQAACKVmTg+Axvfee+8F3V64cKGSkpK0bds2DRw4MLC+ZcuW8nq9oR4PAAA4jCuAFqiqqpIkxcfHB61/8803lZCQoO7du2v69Ok6derUeR/D7/fL5/MFLQAA4MrEFcAwV1tbq0cffVT9+/dX9+7dA+t/8IMfqF27dkpNTdX27dv1ox/9SKWlpXrnnXcafJzCwkLNmjUrVGMDAIAm5DLGGKeHQNOZPHmy3n33XW3atElpaWnn3W/9+vUaMmSI9uzZo44dO9bb7vf75ff7A7d9Pp/atm2rwcpTM1dUk8wOAGg6Z02NNmiVqqqqFBsb6/Q4CDGuAIaxKVOmaM2aNdq4ceO3xp8kZWZmStJ5A9DtdsvtdjfJnAAAILQIwDBkjNHDDz+sFStWaMOGDcrIyPjO+5SUlEiSUlJSmng6AADgNAIwDBUUFGjx4sVatWqVYmJiVF5eLknyeDxq0aKFysrKtHjxYt1yyy26+uqrtX37dk2dOlUDBw5Uz549HZ4eAAA0NT4DGIZcLleD6xcsWKAJEybowIEDuueee7Rjxw5VV1erbdu2uv322/XUU09d8OdAfD6fPB4PnwEEgCsUnwG0G1cAw9B3NX3btm1VVFQUomkAAMDfG34HEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYADEPz5s1Tz549FRsbq9jYWGVlZendd98NbD99+rQKCgp09dVXq3Xr1ho1apQqKiocnBgAAIQSARiG0tLSNHv2bG3btk1bt27VzTffrLy8PO3cuVOSNHXqVK1evVrLli1TUVGRDh06pJEjRzo8NQAACBWXMcY4PQSaXnx8vObMmaM77rhDiYmJWrx4se644w5J0q5du3TttdequLhYN9xwwwU9ns/nk8fj0WDlqZkrqilHBwA0gbOmRhu0SlVVVYqNjXV6HIQYVwDD3Llz57RkyRJVV1crKytL27ZtU01NjbKzswP7dO3aVenp6SouLnZwUgAAECrNnB4ATeOTTz5RVlaWTp8+rdatW2vFihW67rrrVFJSoujoaMXFxQXtn5ycrPLy8vM+nt/vl9/vD9z2+XxNNToAAGhiXAEMU126dFFJSYm2bNmiyZMna/z48frzn/98yY9XWFgoj8cTWNq2bduI0wIAgFAiAMNUdHS0OnXqpD59+qiwsFC9evXSyy+/LK/XqzNnzqiysjJo/4qKCnm93vM+3vTp01VVVRVYDhw40MRHAAAAmgoBaIna2lr5/X716dNHUVFRWrduXWBbaWmp9u/fr6ysrPPe3+12B35Wpm4BAABXJj4DGIamT5+u3Nxcpaen68SJE1q8eLE2bNig999/Xx6PR/n5+Zo2bZri4+MVGxurhx9+WFlZWRf8DWAAAHBlIwDD0JEjRzRu3DgdPnxYHo9HPXv21Pvvv6/vf//7kqQXX3xRERERGjVqlPx+v3JycvTaa685PDUAAAgVfgcQl4TfAQSAKxu/A2g3PgMIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDL8LWBckrq/IHhWNRJ/TBAArjhnVSPp//49h10IQFySEydOSJI26XcOTwIAuBwnTpyQx+NxegyEmMuQ/rgEtbW1OnTokGJiYuRyuQLrfT6f2rZtqwMHDoT1Hxe34ThtOEaJ4ww3NhxnYx2jMUYnTpxQamqqIiL4RJhtuAKISxIREaG0tLTzbo+NjQ3bf3z/lg3HacMxShxnuLHhOBvjGLnyZy+SHwAAwDIEIAAAgGUIQDQqt9utmTNnyu12Oz1Kk7LhOG04RonjDDc2HKcNx4imx5dAAAAALMMVQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAESjmTt3rtq3b6/mzZsrMzNTf/jDH5weqVE988wzcrlcQUvXrl2dHuuybdy4UcOHD1dqaqpcLpdWrlwZtN0Yo6efflopKSlq0aKFsrOztXv3bmeGvQzfdZwTJkyod36HDRvmzLCXqLCwUNdff71iYmKUlJSkESNGqLS0NGif06dPq6CgQFdffbVat26tUaNGqaKiwqGJL82FHOfgwYPrnc8HH3zQoYkvzbx589SzZ8/ADz5nZWXp3XffDWwPh3MJ5xCAaBRLly7VtGnTNHPmTH388cfq1auXcnJydOTIEadHa1TdunXT4cOHA8umTZucHumyVVdXq1evXpo7d26D259//nm98sormj9/vrZs2aJWrVopJydHp0+fDvGkl+e7jlOShg0bFnR+33rrrRBOePmKiopUUFCgzZs3a+3ataqpqdHQoUNVXV0d2Gfq1KlavXq1li1bpqKiIh06dEgjR450cOqLdyHHKUkTJ04MOp/PP/+8QxNfmrS0NM2ePVvbtm3T1q1bdfPNNysvL087d+6UFB7nEg4yQCPo16+fKSgoCNw+d+6cSU1NNYWFhQ5O1bhmzpxpevXq5fQYTUqSWbFiReB2bW2t8Xq9Zs6cOYF1lZWVxu12m7feesuBCRvHN4/TGGPGjx9v8vLyHJmnqRw5csRIMkVFRcaYr89dVFSUWbZsWWCfTz/91EgyxcXFTo152b55nMYYM2jQIPPDH/7QuaGayFVXXWV+9atfhe25ROhwBRCX7cyZM9q2bZuys7MD6yIiIpSdna3i4mIHJ2t8u3fvVmpqqjp06KC7775b+/fvd3qkJrV3716Vl5cHnVuPx6PMzMywO7eStGHDBiUlJalLly6aPHmyjh8/7vRIl6WqqkqSFB8fL0natm2bampqgs5n165dlZ6efkWfz28eZ50333xTCQkJ6t69u6ZPn65Tp045MV6jOHfunJYsWaLq6mplZWWF7blE6DRzegBc+Y4dO6Zz584pOTk5aH1ycrJ27drl0FSNLzMzUwsXLlSXLl10+PBhzZo1SzfeeKN27NihmJgYp8drEuXl5ZLU4Lmt2xYuhg0bppEjRyojI0NlZWV68sknlZubq+LiYkVGRjo93kWrra3Vo48+qv79+6t79+6Svj6f0dHRiouLC9r3Sj6fDR2nJP3gBz9Qu3btlJqaqu3bt+tHP/qRSktL9c477zg47cX75JNPlJWVpdOnT6t169ZasWKFrrvuOpWUlITduURoEYDABcrNzQ38d8+ePZWZmal27drp7bffVn5+voOToTGMGTMm8N89evRQz5491bFjR23YsEFDhgxxcLJLU1BQoB07doTF51S/zfmOc9KkSYH/7tGjh1JSUjRkyBCVlZWpY8eOoR7zknXp0kUlJSWqqqrS8uXLNX78eBUVFTk9FsIAbwHjsiUkJCgyMrLet88qKirk9XodmqrpxcXF6ZprrtGePXucHqXJ1J0/286tJHXo0EEJCQlX5PmdMmWK1qxZo48++khpaWmB9V6vV2fOnFFlZWXQ/lfq+TzfcTYkMzNTkq648xkdHa1OnTqpT58+KiwsVK9evfTyyy+H3blE6BGAuGzR0dHq06eP1q1bF1hXW1urdevWKSsry8HJmtbJkydVVlamlJQUp0dpMhkZGfJ6vUHn1ufzacuWLWF9biXp888/1/Hjx6+o82uM0ZQpU7RixQqtX79eGRkZQdv79OmjqKiooPNZWlqq/fv3X1Hn87uOsyElJSWSdEWdz4bU1tbK7/eHzbmEc3gLGI1i2rRpGj9+vPr27at+/frppZdeUnV1te677z6nR2s0jz32mIYPH6527drp0KFDmjlzpiIjIzV27FinR7ssJ0+eDLoqsnfvXpWUlCg+Pl7p6el69NFH9eyzz6pz587KyMjQjBkzlJqaqhEjRjg39CX4tuOMj4/XrFmzNGrUKHm9XpWVlemJJ55Qp06dlJOT4+DUF6egoECLFy/WqlWrFBMTE/gsmMfjUYsWLeTxeJSfn69p06YpPj5esbGxevjhh5WVlaUbbrjB4ekv3HcdZ1lZmRYvXqxbbrlFV199tbZv366pU6dq4MCB6tmzp8PTX7jp06crNzdX6enpOnHihBYvXqwNGzbo/fffD5tzCQc5/TVkhI9XX33VpKenm+joaNOvXz+zefNmp0dqVKNHjzYpKSkmOjratGnTxowePdrs2bPH6bEu20cffWQk1VvGjx9vjPn6p2BmzJhhkpOTjdvtNkOGDDGlpaXODn0Jvu04T506ZYYOHWoSExNNVFSUadeunZk4caIpLy93euyL0tDxSTILFiwI7PPVV1+Zhx56yFx11VWmZcuW5vbbbzeHDx92buhL8F3HuX//fjNw4EATHx9v3G636dSpk3n88cdNVVWVs4NfpPvvv9+0a9fOREdHm8TERDNkyBDzwQcfBLaHw7mEc1zGGBPK4AQAAICz+AwgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYJn/B5FcfsDI5Q4VAAAAAElFTkSuQmCC", + "text/html": [ "\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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " ], "text/plain": [ - "" + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" ] }, "metadata": {}, @@ -2078,20788 +389,269 @@ }, { "data": { - "text/html": [ - "" - ], "text/plain": [ - "" + "" ] }, + "execution_count": 9, "metadata": {}, - "output_type": "display_data" - }, + "output_type": "execute_result" + } + ], + "source": [ + "%autoreload\n", + "size = 32\n", + "params = OverfocusParams(\n", + " overfocus=0.0001,\n", + " scan_pixel_size=0.00000001,\n", + " camera_length=1,\n", + " detector_pixel_size=0.0001,\n", + " semiconv=np.pi,\n", + " cy=size/2,\n", + " cx=size/2,\n", + " scan_rotation=0,\n", + " flip_y=False\n", + ")\n", + "obj = np.zeros((size, size))\n", + "obj[size//2, size//2] = 1\n", + "sim = project(obj, scan_shape=(size, size), detector_shape=(size, size), sim_params=params)\n", + "assert sim[size//2, size//2, size//2, size//2] == 1\n", + "\n", + "udf = OverfocusUDF(params)\n", + "ctx = Context.make_with('inline')\n", + "ds = ctx.load('memory', data=sim)\n", + "\n", + "res = ctx.run_udf(dataset=ds, udf=udf, plots=True)\n", + "\n", + "res['point']" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "cc589032", + "metadata": {}, + "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 7, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fa6f4397ead849b9bb3ab21015edd2fb", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAetUlEQVR4nO3df2xV933w8Y/5YZcU+1Lzw8bDMCe00JRAJRocKy2jxQMcKYJApCTtNJKhVM1MNLC6VFRNUrRKrhKpTVtR8se0ZJNK0mUqQYmWZBkpRtEMU5gsmm6xAmKCCOy0SNjgDEPwef6oep/HCzQJ2Pc89vf1ko7qe87x1eerU5G3zv3hsizLsgAAIBkT8h4AAIDSEoAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAImZlPcAjE1DQ0Nx8uTJqKysjLKysrzHAeBjyrIszp49G3V1dTFhgvtBqRGAXJWTJ09GfX193mMAcI1OnDgRc+bMyXsMSkwAJm7Hjh3x+OOPR09PTyxZsiR+8pOfxLJlyz709yorKyMi4otxW0yKyaM9JgAj7P24GK/HPxf/PSctAjBhP//5z6OtrS2efPLJaGxsjCeeeCJWr14d3d3dMWvWrD/4u79/2XdSTI5JZQIQYMzJfvc/3saTJi/6J+wHP/hB3H///XHffffFjTfeGE8++WRcd9118Xd/93d5jwYAjCIBmKgLFy7EoUOHorm5ubhvwoQJ0dzcHJ2dnR84f3BwMPr7+4dtAMDYJAAT9dvf/jYuXboUNTU1w/bX1NRET0/PB85vb2+PQqFQ3HwABADGLgHIR7Jt27bo6+srbidOnMh7JADgKvkQSKJmzJgREydOjN7e3mH7e3t7o7a29gPnV1RUREVFRanGAwBGkTuAiSovL4+lS5fG3r17i/uGhoZi79690dTUlONkAMBocwcwYW1tbbFx48b4whe+EMuWLYsnnngiBgYG4r777st7NABgFAnAhN11113xm9/8Jh555JHo6emJz3/+8/Hyyy9/4IMhAMD4UpZlWZb3EIw9/f39USgUYkWs9UXQAGPQ+9nF2Bd7oq+vL6qqqvIehxLzHkAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAjARH33u9+NsrKyYdvChQvzHgsAKIFJeQ9Afj73uc/Fv/7rvxYfT5rk/w4AkAL/xU/YpEmTora2Nu8xAIAS8xJwwt5+++2oq6uL66+/Pr72ta/F8ePHr3ju4OBg9Pf3D9sAgLFJACaqsbExnn766Xj55Zdj586dcezYsfjSl74UZ8+evez57e3tUSgUilt9fX2JJwYARkpZlmVZ3kOQvzNnzsS8efPiBz/4QWzatOkDxwcHB2NwcLD4uL+/P+rr62NFrI1JZZNLOSoAI+D97GLsiz3R19cXVVVVeY9DiXkPIBERMW3atPjMZz4TR44cuezxioqKqKioKPFUAMBo8BIwERFx7ty5OHr0aMyePTvvUQCAUSYAE/XNb34zOjo64r//+7/j3/7t3+KOO+6IiRMnxj333JP3aADAKPMScKLeeeeduOeee+L06dMxc+bM+OIXvxgHDhyImTNn5j0aADDKBGCinn322bxHAABy4iVgAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECMBxaP/+/XH77bdHXV1dlJWVxfPPPz/seJZl8cgjj8Ts2bNjypQp0dzcHG+//XY+wwIAJScAx6GBgYFYsmRJ7Nix47LHH3vssfjxj38cTz75ZBw8eDA++clPxurVq+P8+fMlnhQAyMOkvAdg5LW0tERLS8tlj2VZFk888UR85zvfibVr10ZExD/8wz9ETU1NPP/883H33XeXclQAIAfuACbm2LFj0dPTE83NzcV9hUIhGhsbo7OzM8fJAIBScQcwMT09PRERUVNTM2x/TU1N8djlDA4OxuDgYPFxf3//6AwIAIw6dwD5SNrb26NQKBS3+vr6vEcCAK6SAExMbW1tRET09vYO29/b21s8djnbtm2Lvr6+4nbixIlRnRMAGD0CMDENDQ1RW1sbe/fuLe7r7++PgwcPRlNT0xV/r6KiIqqqqoZtAMDY5D2A49C5c+fiyJEjxcfHjh2Lrq6uqK6ujrlz58aWLVvie9/7Xnz605+OhoaGePjhh6Ouri7WrVuX39AAQMkIwHHojTfeiC9/+cvFx21tbRERsXHjxnj66afjoYceioGBgfj6178eZ86ciS9+8Yvx8ssvxyc+8Ym8RgYASqgsy7Is7yEYe/r7+6NQKMSKWBuTyibnPQ4AH9P72cXYF3uir6/P23oS5D2AAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgOPQ/v374/bbb4+6urooKyuL559/ftjxe++9N8rKyoZta9asyWdYAKDkBOA4NDAwEEuWLIkdO3Zc8Zw1a9bEqVOnitszzzxTwgkBgDxNynsARl5LS0u0tLT8wXMqKiqitra2RBMBAP8/cQcwUfv27YtZs2bFggUL4oEHHojTp0/nPRIAUCLuACZozZo1sX79+mhoaIijR4/Gt7/97WhpaYnOzs6YOHHiZX9ncHAwBgcHi4/7+/tLNS4AMMIEYILuvvvu4s833XRTLF68OG644YbYt29frFy58rK/097eHtu3by/ViADAKPISMHH99dfHjBkz4siRI1c8Z9u2bdHX11fcTpw4UcIJAYCR5A4g8c4778Tp06dj9uzZVzynoqIiKioqSjgVADBaBOA4dO7cuWF3844dOxZdXV1RXV0d1dXVsX379tiwYUPU1tbG0aNH46GHHor58+fH6tWrc5waACgVATgOvfHGG/HlL3+5+LitrS0iIjZu3Bg7d+6Mw4cPx9///d/HmTNnoq6uLlatWhV/8zd/4w4fACRCAI5DK1asiCzLrnj8lVdeKeE0MHa9crLrY52/uu7zozIHwEjzIRAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxPhbwABX4G/7AuOVO4AAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGA41B7e3vcfPPNUVlZGbNmzYp169ZFd3f3sHPOnz8fra2tMX369Jg6dWps2LAhent7c5oYACglATgOdXR0RGtraxw4cCBeffXVuHjxYqxatSoGBgaK52zdujVeeOGFeO6556KjoyNOnjwZ69evz3FqAKBUyrIsy/IegtH1m9/8JmbNmhUdHR2xfPny6Ovri5kzZ8auXbvizjvvjIiIt956Kz772c9GZ2dn3HLLLR/6nP39/VEoFGJFrI1JZZNHewkAjLD3s4uxL/ZEX19fVFVV5T0OJeYOYAL6+voiIqK6ujoiIg4dOhQXL16M5ubm4jkLFy6MuXPnRmdn52WfY3BwMPr7+4dtAMDYJADHuaGhodiyZUvceuutsWjRooiI6OnpifLy8pg2bdqwc2tqaqKnp+eyz9Pe3h6FQqG41dfXj/boAMAoEYDjXGtra7z55pvx7LPPXtPzbNu2Lfr6+orbiRMnRmhCAKDUJuU9AKNn8+bN8eKLL8b+/ftjzpw5xf21tbVx4cKFOHPmzLC7gL29vVFbW3vZ56qoqIiKiorRHhkAKAF3AMehLMti8+bNsXv37njttdeioaFh2PGlS5fG5MmTY+/evcV93d3dcfz48Whqair1uABAibkDOA61trbGrl27Ys+ePVFZWVl8X1+hUIgpU6ZEoVCITZs2RVtbW1RXV0dVVVU8+OCD0dTU9JE+AQwAjG0CcBzauXNnRESsWLFi2P6nnnoq7r333oiI+OEPfxgTJkyIDRs2xODgYKxevTp++tOflnhSACAPvgeQq+J7AAHGNt8DmDbvAQQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAch9rb2+Pmm2+OysrKmDVrVqxbty66u7uHnbNixYooKysbtn3jG9/IaWIAoJQE4DjU0dERra2tceDAgXj11Vfj4sWLsWrVqhgYGBh23v333x+nTp0qbo899lhOEwMApTQp7wEYeS+//PKwx08//XTMmjUrDh06FMuXLy/uv+6666K2trbU4wEAOXMHMAF9fX0REVFdXT1s/89+9rOYMWNGLFq0KLZt2xbvvffeFZ9jcHAw+vv7h20AwNjkDuA4NzQ0FFu2bIlbb701Fi1aVNz/1a9+NebNmxd1dXVx+PDh+Na3vhXd3d3xi1/84rLP097eHtu3by/V2ADAKCrLsizLewhGzwMPPBAvvfRSvP766zFnzpwrnvfaa6/FypUr48iRI3HDDTd84Pjg4GAMDg4WH/f390d9fX2siLUxqWzyqMwOwOh5P7sY+2JP9PX1RVVVVd7jUGLuAI5jmzdv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OHjw4Li+thER77zzTpw+fXpMXd8sy2Lz5s2xe/fueO2116KhoWHY8aVLl8bkyZOHXc/u7u44fvz4mLqeH7bOy+nq6oqIGFPX83KGhoZicHBw3FxL8uMlYEZEW1tbbNy4Mb7whS/EsmXL4oknnoiBgYG477778h5txHzzm9+M22+/PebNmxcnT56MRx99NCZOnBj33HNP3qNdk3Pnzg27K3Ls2LHo6uqK6urqmDt3bmzZsiW+973vxac//eloaGiIhx9+OOrq6mLdunX5DX0V/tA6q6urY/v27bFhw4aora2No0ePxkMPPRTz58+P1atX5zj1x9Pa2hq7du2KPXv2RGVlZfG9YIVCIaZMmRKFQiE2bdoUbW1tUV1dHVVVVfHggw9GU1NT3HLLLTlP/9F92DqPHj0au3btittuuy2mT58ehw8fjq1bt8by5ctj8eLFOU//0W3bti1aWlpi7ty5cfbs2di1a1fs27cvXnnllXFzLclR3h9DZvz4yU9+ks2dOzcrLy/Pli1blh04cCDvkUbUXXfdlc2ePTsrLy/P/uiP/ii76667siNHjuQ91jX75S9/mUXEB7aNGzdmWfa7r4J5+OGHs5qamqyioiJbuXJl1t3dne/QV+EPrfO9997LVq1alc2cOTObPHlyNm/evOz+++/Penp68h77Y7nc+iIie+qpp4rn/M///E/2l3/5l9mnPvWp7LrrrsvuuOOO7NSpU/kNfRU+bJ3Hjx/Pli9fnlVXV2cVFRXZ/Pnzs7/+67/O+vr68h38Y/qLv/iLbN68eVl5eXk2c+bMbOXKldm//Mu/FI+Ph2tJfsqyLMtKGZwAAOTLewABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABLzfwBt9U01C+igRQAAAABJRU5ErkJggg==", + "text/html": [ + "\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ - "fig, axes = plt.subplots(1, 3)\n", - "axes[0].imshow(obj)\n", - "axes[1].imshow(projected[:, :, size//2, size//2])\n", - "axes[2].imshow(projected[:, :, size//2, size//2] - obj)\n", - "\n", - "fig, axes = plt.subplots(1, 3)\n", - "axes[0].imshow(obj)\n", - "axes[1].imshow(projected[size//2, size//2, :])\n", - "axes[2].imshow(projected[size//2, size//2, :] - obj)" + "fig, axes = plt.subplots()\n", + "axes.imshow(sim[size//2, size//2])" ] }, { "cell_type": "code", - "execution_count": 8, - "id": "984405c9", - "metadata": { - "scrolled": false - }, + "execution_count": 11, + "id": "845d2423", + "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", + "text/plain": [ + "" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f07f5767fdb648e19fc7d6377833bcc4", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAex0lEQVR4nO3df2xV933w8Y/5YZcU+1Lzw8bDMBJaaEqgEg3ESstoYYAjRRCIlKSdRjKUqpmJBqhL5apJilbJVSK1aStK/piWbFJJukwlKNGSLCO1UTTDFCaLplusYDFBBHZaJGxwhnHwef6oep/HCzQJ2Pc89vf1ko7KPef46vPVqchb5x5fyrIsywIAgGRMyHsAAABKSwACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRmUt4DMDYNDQ3FqVOnorKyMsrKyvIeB4CPKcuyOHfuXNTV1cWECe4HpUYAclVOnToV9fX1eY8BwDU6efJkzJkzJ+8xKDEBmLjdu3fH448/Ht3d3bF06dL4yU9+EsuXL//Qn6usrIyIiC/GbTEpJo/2mACMsPdjMF6Pfy7+fU5aBGDCfv7zn8fOnTvjySefjBUrVsQTTzwR69ati87Ozpg1a9Yf/Nnff+w7KSbHpDIBCDDmZL/7H4/xpMmH/gn7wQ9+EPfff3/cd999ceONN8aTTz4Z1113Xfzd3/1d3qMBAKNIACbq4sWLceTIkVizZk1x34QJE2LNmjXR3t7+gfMHBgair69v2AYAjE0CMFG//e1v49KlS1FTUzNsf01NTXR3d3/g/JaWligUCsXNL4AAwNglAPlImpubo7e3t7idPHky75EAgKvkl0ASNWPGjJg4cWL09PQM29/T0xO1tbUfOL+ioiIqKipKNR4AMIrcAUxUeXl5LFu2LA4cOFDcNzQ0FAcOHIiGhoYcJwMARps7gAnbuXNnbNmyJb7whS/E8uXL44knnoj+/v6477778h4NABhFAjBhd911V/zmN7+JRx55JLq7u+Pzn/98vPzyyx/4xRAAYHwpy7Isy3sIxp6+vr4oFAqxKjb4ImiAMej9bDBaY3/09vZGVVVV3uNQYp4BBABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAEzUd7/73SgrKxu2LVq0KO+xAIASmJT3AOTnc5/7XPzrv/5r8fWkSf7vAAAp8F/8hE2aNClqa2vzHgMAKDEfASfs7bffjrq6urj++uvja1/7Wpw4ceKK5w4MDERfX9+wDQAYmwRgolasWBFPP/10vPzyy7Fnz544fvx4fOlLX4pz585d9vyWlpYoFArFrb6+vsQTAwAjpSzLsizvIcjf2bNnY968efGDH/wgtm7d+oHjAwMDMTAwUHzd19cX9fX1sSo2xKSyyaUcFYAR8H42GK2xP3p7e6OqqirvcSgxzwASERHTpk2Lz3zmM3Hs2LHLHq+oqIiKiooSTwUAjAYfARMREefPn4+urq6YPXt23qMAAKNMACbqm9/8ZrS1tcV///d/x7/927/FHXfcERMnTox77rkn79EAgFHmI+BEvfPOO3HPPffEmTNnYubMmfHFL34xDh06FDNnzsx7NABglAnARD377LN5jwAA5MRHwAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGA49DBgwfj9ttvj7q6uigrK4vnn39+2PEsy+KRRx6J2bNnx5QpU2LNmjXx9ttv5zMsAFByAnAc6u/vj6VLl8bu3bsve/yxxx6LH//4x/Hkk0/G4cOH45Of/GSsW7cuLly4UOJJAYA8TMp7AEZeY2NjNDY2XvZYlmXxxBNPxHe+853YsGFDRET8wz/8Q9TU1MTzzz8fd999dylHBQBy4A5gYo4fPx7d3d2xZs2a4r5CoRArVqyI9vb2HCcDAErFHcDEdHd3R0RETU3NsP01NTXFY5czMDAQAwMDxdd9fX2jMyAAMOrcAeQjaWlpiUKhUNzq6+vzHgkAuEoCMDG1tbUREdHT0zNsf09PT/HY5TQ3N0dvb29xO3ny5KjOCQCMHgGYmPnz50dtbW0cOHCguK+vry8OHz4cDQ0NV/y5ioqKqKqqGrYBAGOTZwDHofPnz8exY8eKr48fPx4dHR1RXV0dc+fOje3bt8f3vve9+PSnPx3z58+Phx9+OOrq6mLjxo35DQ0AlIwAHIfeeOON+PKXv1x8vXPnzoiI2LJlSzz99NPx0EMPRX9/f3z961+Ps2fPxhe/+MV4+eWX4xOf+EReIwMAJVSWZVmW9xCMPX19fVEoFGJVbIhJZZPzHgeAj+n9bDBaY3/09vZ6rCdBngEEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIzKS8BwAolVdOdXys89fVfX5U5gDImzuAAACJEYDj0MGDB+P222+Purq6KCsri+eff37Y8XvvvTfKysqGbevXr89nWACg5ATgONTf3x9Lly6N3bt3X/Gc9evXx+nTp4vbM888U8IJAYA8eQZwHGpsbIzGxsY/eE5FRUXU1taWaCIA4P8n7gAmqrW1NWbNmhULFy6MBx54IM6cOZP3SABAibgDmKD169fHpk2bYv78+dHV1RXf/va3o7GxMdrb22PixImX/ZmBgYEYGBgovu7r6yvVuADACBOACbr77ruLf77ppptiyZIlccMNN0Rra2usXr36sj/T0tISu3btKtWIAMAo8hEwcf3118eMGTPi2LFjVzynubk5ent7i9vJkydLOCEAMJLcASTeeeedOHPmTMyePfuK51RUVERFRUUJpwIARosAHIfOnz8/7G7e8ePHo6OjI6qrq6O6ujp27doVmzdvjtra2ujq6oqHHnooFixYEOvWrctxagCgVATgOPTGG2/El7/85eLrnTt3RkTEli1bYs+ePXH06NH4+7//+zh79mzU1dXF2rVr42/+5m/c4QOARJRlWZblPQRjT19fXxQKhVgVG2JS2eS8xwHgY3o/G4zW2B+9vb1RVVWV9ziUmF8CAQBIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAByHWlpa4uabb47KysqYNWtWbNy4MTo7O4edc+HChWhqaorp06fH1KlTY/PmzdHT05PTxABAKQnAcaitrS2ampri0KFD8eqrr8bg4GCsXbs2+vv7i+fs2LEjXnjhhXjuueeira0tTp06FZs2bcpxagCgVMqyLMvyHoLR9Zvf/CZmzZoVbW1tsXLlyujt7Y2ZM2fG3r17484774yIiLfeeis++9nPRnt7e9xyyy0f+p59fX1RKBRiVWyISWWTR3sJAIyw97PBaI390dvbG1VVVXmPQ4m5A5iA3t7eiIiorq6OiIgjR47E4OBgrFmzpnjOokWLYu7cudHe3n7Z9xgYGIi+vr5hGwAwNgnAcW5oaCi2b98et956ayxevDgiIrq7u6O8vDymTZs27Nyampro7u6+7Pu0tLREoVAobvX19aM9OgAwSgTgONfU1BRvvvlmPPvss9f0Ps3NzdHb21vcTp48OUITAgClNinvARg927ZtixdffDEOHjwYc+bMKe6vra2NixcvxtmzZ4fdBezp6Yna2trLvldFRUVUVFSM9sgAQAm4AzgOZVkW27Zti3379sVrr70W8+fPH3Z82bJlMXny5Dhw4EBxX2dnZ5w4cSIaGhpKPS4AUGLuAI5DTU1NsXfv3ti/f39UVlYWn+srFAoxZcqUKBQKsXXr1ti5c2dUV1dHVVVVPPjgg9HQ0PCRfgMYABjbBOA4tGfPnoiIWLVq1bD9Tz31VNx7770REfHDH/4wJkyYEJs3b46BgYFYt25d/PSnPy3xpABAHnwPIFfF9wACjG2+BzBtngEEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwAHIdaWlri5ptvjsrKypg1a1Zs3LgxOjs7h52zatWqKCsrG7Z94xvfyGliAKCUBOA41NbWFk1NTXHo0KF49dVXY3BwMNauXRv9/f3Dzrv//vvj9OnTxe2xxx7LaWIAoJQm5T0AI+/ll18e9vrpp5+OWbNmxZEjR2LlypXF/dddd13U1taWejwAIGfuACagt7c3IiKqq6uH7f/Zz34WM2bMiMWLF0dzc3O89957V3yPgYGB6OvrG7YBAGOTO4Dj3NDQUGzfvj1uvfXWWLx4cXH/V7/61Zg3b17U1dXF0aNH41vf+lZ0dnbGL37xi8u+T0tLS+zatatUYwMAo6gsy7Is7yEYPQ888EC89NJL8frrr8ecOXOueN5rr70Wq1evjmPHjsUNN9zwgeMDAwMxMDBQfN3X1xf19fWxKjbEpLLJozI7AKPn/WwwWmN/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jhw5Em+88UZ85StfiQ0bNsSvf/3riBgf15IcZTACli9fnjU1NRVfX7p0Kaurq8taWlpynGpkPfroo9nSpUvzHmNURUS2b9++4uuhoaGstrY2e/zxx4v7zp49m1VUVGTPPPNMDhOOjP+9zizLsi1btmQbNmzIZZ7R8u6772YRkbW1tWVZ9rtrN3ny5Oy5554rnvNf//VfWURk7e3teY15zf73OrMsy/7kT/4k+6u/+qv8hholn/rUp7K//du/HbfXktJxB5BrdvHixThy5EisWbOmuG/ChAmxZs2aaG9vz3Gykff2229HXV1dXH/99fG1r30tTpw4kfdIo+r48ePR3d097NoWCoVYsWLFuLu2ERGtra0xa9asWLhwYTzwwANx5syZvEe6Jr29vRERUV1dHRERR44cicHBwWHXc9GiRTF37twxfT3/9zp/72c/+1nMmDEjFi9eHM3NzfHee+/lMd6IuHTpUjz77LPR398fDQ0N4/ZaUjqT8h6Ase+3v/1tXLp0KWpqaobtr6mpibfeeiunqUbeihUr4umnn46FCxfG6dOnY9euXfGlL30p3nzzzaisrMx7vFHR3d0dEXHZa/v7Y+PF+vXrY9OmTTF//vzo6uqKb3/729HY2Bjt7e0xceLEvMf72IaGhmL79u1x6623xuLFiyPid9ezvLw8pk2bNuzcsXw9L7fOiIivfvWrMW/evKirq4ujR4/Gt771rejs7Ixf/OIXOU778f3qV7+KhoaGuHDhQkydOjX27dsXN954Y3R0dIy7a0lpCUD4iBobG4t/XrJkSaxYsSLmzZsX//iP/xhbt27NcTJGwt13313880033RRLliyJG264IVpbW2P16tU5TnZ1mpqa4s033xwXz6n+IVda59e//vXin2+66aaYPXt2rF69Orq6uuKGG24o9ZhXbeHChdHR0RG9vb3xT//0T7Fly5Zoa2vLeyzGAR8Bc81mzJgREydO/MBvn/X09ERtbW1OU42+adOmxWc+85k4duxY3qOMmt9fv9SubUTE9ddfHzNmzBiT13fbtm3x4osvxi9/+cuYM2dOcX9tbW1cvHgxzp49O+z8sXo9r7TOy1mxYkVExJi7nuXl5bFgwYJYtmxZtLS0xNKlS+NHP/rRuLuWlJ4A5JqVl5fHsmXL4sCBA8V9Q0NDceDAgWhoaMhxstF1/vz56OrqitmzZ+c9yqiZP39+1NbWDru2fX19cfjw4XF9bSMi3nnnnThz5syYur5ZlsW2bdti37598dprr8X8+fOHHV+2bFlMnjx52PXs7OyMEydOjKnr+WHrvJyOjo6IiDF1PS9naGgoBgYGxs21JD8+AmZE7Ny5M7Zs2RJf+MIXYvny5fHEE09Ef39/3HfffXmPNmK++c1vxu233x7z5s2LU6dOxaOPPhoTJ06Me+65J+/Rrsn58+eH3RU5fvx4dHR0RHV1dcydOze2b98e3/ve9+LTn/50zJ8/Px5++OGoq6uLjRs35jf0VfhD66yuro5du3bF5s2bo7a2Nrq6uuKhhx6KBQsWxLp163Kc+uNpamqKvXv3xv79+6OysrL4LFihUIgpU6ZEoVCIrVu3xs6dO6O6ujqqqqriwQcfjIaGhrjllltynv6j+7B1dnV1xd69e+O2226L6dOnx9GjR2PHjh2xcuXKWLJkSc7Tf3TNzc3R2NgYc+fOjXPnzsXevXujtbU1XnnllXFzLclR3r+GzPjxk5/8JJs7d25WXl6eLV++PDt06FDeI42ou+66K5s9e3ZWXl6e/dEf/VF21113ZceOHct7rGv2y1/+MouID2xbtmzJsux3XwXz8MMPZzU1NVlFRUW2evXqrLOzM9+hr8IfWud7772XrV27Nps5c2Y2efLkbN68edn999+fdXd35z32x3K59UVE9tRTTxXP+Z//+Z/sL//yL7NPfepT2XXXXZfdcccd2enTp/Mb+ip82DpPnDiRrVy5Mquurs4qKiqyBQsWZH/913+d9fb25jv4x/QXf/EX2bx587Ly8vJs5syZ2erVq7N/+Zd/KR4fD9eS/JRlWZaVMjgBAMiXZwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABLzfwBLhlW1NsH4gQAAAABJRU5ErkJggg==", + "text/html": [ "\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%autoreload\n", - "size = 32\n", - "params = OverfocusParams(\n", - " overfocus=0.0001,\n", - " scan_pixel_size=0.00000001,\n", - " camera_length=1,\n", - " detector_pixel_size=0.0001,\n", - " semiconv=np.pi,\n", - " cy=size/2,\n", - " cx=size/2,\n", - " scan_rotation=0,\n", - " flip_y=False\n", - ")\n", - "obj = np.zeros((size, size))\n", - "obj[size//2, size//2] = 1\n", - "sim = project(obj, scan_shape=(size, size), detector_shape=(size, size), sim_params=params)\n", - "assert sim[size//2, size//2, size//2, size//2] == 1\n", - "\n", - "udf = OverfocusUDF(params)\n", - "ctx = Context.make_with('inline')\n", - "ds = ctx.load('memory', data=sim)\n", - "\n", - "res = ctx.run_udf(dataset=ds, udf=udf, plots=True)\n", - "\n", - "res['point']" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "cc589032", - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots()\n", - "axes.imshow(sim[size//2, size//2])" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "845d2423", - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots()\n", - "axes.imshow(sim[:, :, size//2 + 1, size//2 + 1])" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "c2f86c2f", - "metadata": {}, - "outputs": [], - "source": [ - "def get_translation_matrix(params: OverfocusParams, nav_shape):\n", - " a = []\n", - " b = []\n", - "\n", - " for det_y in (-10, 10):\n", - " for det_x in (-10, 10):\n", - " spec_y, spec_x = detector_px_to_specimen_px(\n", - " y_px=float(det_y),\n", - " x_px=float(det_x),\n", - " fov_size_y=float(nav_shape[0]),\n", - " fov_size_x=float(nav_shape[1]),\n", - " transformation_matrix=get_transformation_matrix(params),\n", - " cy=params['cy'],\n", - " cx=params['cx'],\n", - " detector_pixel_size=float(params['detector_pixel_size']),\n", - " scan_pixel_size=float(params['scan_pixel_size']),\n", - " camera_length=float(params['camera_length']),\n", - " overfocus=float(params['overfocus']),\n", - " )\n", - " for scan_y in (-10, 10):\n", - " for scan_x in (-10, 10): \n", - " offset_y = scan_y - nav_shape[0] / 2\n", - " offset_x = scan_x - nav_shape[1] / 2\n", - " image_px_y = spec_y + offset_y\n", - " image_px_x = spec_x + offset_x\n", - " a.append((\n", - " image_px_y,\n", - " image_px_x,\n", - " scan_y,\n", - " scan_x,\n", - " 1\n", - " ))\n", - " b.append((det_y, det_x))\n", - " #print(a)\n", - " #print(b)\n", - " res = np.linalg.lstsq(a, b, rcond=None)\n", - " return res[0]" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "1aa7bd4b", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[ 1.00000000e+00, -4.91104128e-16],\n", - " [-1.55431223e-15, 1.00000000e+00],\n", - " [-1.00000000e+00, -1.23400968e-15],\n", - " [ 8.21841917e-16, -1.00000000e+00],\n", - " [ 1.60000000e+01, 1.60000000e+01]])" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "params = OverfocusParams(\n", - " overfocus=0.0001,\n", - " scan_pixel_size=0.00000001,\n", - " camera_length=1,\n", - " detector_pixel_size=0.0001,\n", - " semiconv=np.pi,\n", - " cy=size/2,\n", - " cx=size/2,\n", - " scan_rotation=0,\n", - " flip_y=False\n", - ")\n", - "\n", - "get_translation_matrix(params, nav_shape=(32, 32))" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "f7857d5e", - "metadata": {}, - "outputs": [], - "source": [ - "class RefOverfocusUDF(OverfocusUDF):\n", - " def get_task_data(self):\n", - " overfocus_params = self.params.overfocus_params\n", - " translation_matrix = get_translation_matrix(\n", - " params=overfocus_params,\n", - " nav_shape=self._get_fov()\n", - " )\n", - " select_roi = np.zeros(self.meta.dataset_shape.nav, dtype=bool)\n", - " nav_y, nav_x = self.meta.dataset_shape.nav\n", - " select_roi[nav_y//2, nav_x//2] = True\n", - " return {\n", - " 'translation_matrix': translation_matrix,\n", - " 'select_roi': select_roi\n", - " }" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "f89fa72d", - "metadata": { - "scrolled": false - }, - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "%autoreload\n", - "size = 16\n", - "params = OverfocusParams(\n", - " overfocus=0.0001,\n", - " scan_pixel_size=0.00000001,\n", - " camera_length=1,\n", - " detector_pixel_size=0.0001,\n", - " semiconv=np.pi,\n", - " cy=size/2,\n", - " cx=size/2,\n", - " scan_rotation=0,\n", - " flip_y=False\n", - ")\n", - "obj = np.zeros((size, size))\n", - "obj[size//2, size//2] = 1\n", - "sim = project(obj, scan_shape=(size, size), detector_shape=(size, size), sim_params=params)\n", - "assert sim[size//2, size//2, size//2, size//2] == 1\n", - "\n", - "ref_udf = RefOverfocusUDF(params)\n", - "res_udf = OverfocusUDF(params)\n", - "ctx = Context.make_with('inline')\n", - "ds = ctx.load('memory', data=sim)\n", - "\n", - "res = ctx.run_udf(dataset=ds, udf=(ref_udf, res_udf), plots=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "8a47c3a8", - "metadata": { - "scrolled": false - }, - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "C:\\Users\\weber\\Documents\\src\\LiberTEM\\src\\libertem\\viz\\mpl.py:74: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`.\n", - " self.fig, self.axes = plt.subplots()\n" - ] - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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" + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " ], "text/plain": [ - "" + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" ] }, "metadata": {}, "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", - " // 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", + } + ], + "source": [ + "fig, axes = plt.subplots()\n", + "axes.imshow(sim[:, :, size//2 + 1, size//2 + 1])" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "c2f86c2f", + "metadata": {}, + "outputs": [], + "source": [ + "def get_translation_matrix(params: OverfocusParams, nav_shape):\n", + " a = []\n", + " b = []\n", + "\n", + " for det_y in (-10, 10):\n", + " for det_x in (-10, 10):\n", + " spec_y, spec_x = detector_px_to_specimen_px(\n", + " y_px=float(det_y),\n", + " x_px=float(det_x),\n", + " fov_size_y=float(nav_shape[0]),\n", + " fov_size_x=float(nav_shape[1]),\n", + " transformation_matrix=get_transformation_matrix(params),\n", + " cy=params['cy'],\n", + " cx=params['cx'],\n", + " detector_pixel_size=float(params['detector_pixel_size']),\n", + " scan_pixel_size=float(params['scan_pixel_size']),\n", + " camera_length=float(params['camera_length']),\n", + " overfocus=float(params['overfocus']),\n", + " )\n", + " for scan_y in (-10, 10):\n", + " for scan_x in (-10, 10): \n", + " offset_y = scan_y - nav_shape[0] / 2\n", + " offset_x = scan_x - nav_shape[1] / 2\n", + " image_px_y = spec_y + offset_y\n", + " image_px_x = spec_x + offset_x\n", + " a.append((\n", + " image_px_y,\n", + " image_px_x,\n", + " scan_y,\n", + " scan_x,\n", + " 1\n", + " ))\n", + " b.append((det_y, det_x))\n", + " #print(a)\n", + " #print(b)\n", + " res = np.linalg.lstsq(a, b, rcond=None)\n", + " return res[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "1aa7bd4b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1.00010000e+00, 2.35830457e-16],\n", + " [ 1.55431223e-15, 1.00010000e+00],\n", + " [-1.00010000e+00, -1.58206781e-15],\n", + " [-8.65092273e-16, -1.00010000e+00],\n", + " [ 1.60000000e+01, 1.60000000e+01]])" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "params = OverfocusParams(\n", + " overfocus=0.0001,\n", + " scan_pixel_size=0.00000001,\n", + " camera_length=1,\n", + " detector_pixel_size=0.0001,\n", + " semiconv=np.pi,\n", + " cy=size/2,\n", + " cx=size/2,\n", + " scan_rotation=0,\n", + " flip_y=False\n", + ")\n", + "\n", + "get_translation_matrix(params, nav_shape=(32, 32))" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f7857d5e", + "metadata": {}, + "outputs": [], + "source": [ + "class RefOverfocusUDF(OverfocusUDF):\n", + " def get_task_data(self):\n", + " overfocus_params = self.params.overfocus_params\n", + " translation_matrix = get_translation_matrix(\n", + " params=overfocus_params,\n", + " nav_shape=self._get_fov()\n", + " )\n", + " select_roi = np.zeros(self.meta.dataset_shape.nav, dtype=bool)\n", + " nav_y, nav_x = self.meta.dataset_shape.nav\n", + " select_roi[nav_y//2, nav_x//2] = True\n", + " return {\n", + " 'translation_matrix': translation_matrix,\n", + " 'select_roi': select_roi\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "f89fa72d", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b671e485f50f4050b7d5d7f01defe434", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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eeDAAd166606ePCgWrdurZCQwH0Hbdq0kfT3n0tlEhISAu6XfZzhxIkTioqKuuT5AVQPAQhcwTp37uzfc5WamqoePXropz/9qXbv3q369eurtLRUkvRv//Zv6tu3b4XP8U//9E8XfH6Px6OmTZtq+/btlc6xfft2NWvWzP8faLfbrdTUVOXk5OjVV1/V0aNH9bvf/U7Tp0/3P+ZSZouIiKh0jppyoRgrKSkpt93SpUu1adMmrVy5Uh988IFGjx6t559/Xps2bVL9+vX9Z79+//33FT5n2QkP1TlLtuykmsp+lrXFhfbwGmOCPAlgNwIQqCVCQ0OVlZWlXr166ZVXXtHkyZP9l2WpU6fOJe8JuvPOO7VgwQJt2LBBPXr0KLf+008/1YEDBwIOD0p/PQycnZ2tNWvWaOfOnTLG+A//Sross11I2RnNu3fvLrdu165daty4sSIjIxUREaGoqKiAs5IrUrYX6uTJkwGXm7nQHq1bb71Vt956q6ZNm6ZFixZpyJAhevfdd/Xggw+qSZMmqlevXoWzlc1cr149NW7cuCrfqkpKSrRo0SLVq1evwp/P5XL48GH/pXfK7NmzR5L8J9S0aNFC27dvV2lpacBewF27dvnXXw7VPTQPoPr4DCBQiyQnJ6tz586aPXu2zp49q5iYGCUnJ2vevHn65ptvym1fdu2/ykycOFERERF6+OGH9e233was++677/TII4+oXr16mjhxYsC6lJQURUdHa/HixVq8eLE6d+4ccAj3csx2IU2bNlXHjh2VnZ2tkydP+pfv2LFDH374oe644w5JUkhIiFJTU7Vy5Upt3bq13POU7XUqO8t0/fr1/nVllyL5oRMnTpTbU9WxY0dJUnFxsaS/hnqfPn20cuVKff311wHbfv3111q5cqX69OlTpc86lpSUKCMjQzt37lRGRka1DpFW5zIwkvSXv/xF8+bN898/d+6c5s2bpyZNmujmm2+WJN1xxx06cuSIFi9eHPC4l19+WfXr1y93VvilioyMDPi5Arj82AMI1DITJ07UoEGDtHDhQj3yyCOaM2eOevToofbt2+uhhx5Sy5YtdfToUW3cuFF//vOf9fnnn1f6fK1bt1Z2draGDBmi9u3bl/tLIMePH9c777xT7lIcderU0b333qt3331XRUVFFf7ps390tsrMnDlT/fr1U9euXfXAAw/4LwPj8XgCTnyYPn26PvzwQ/Xs2VNjxoxRmzZt9M033+i9997Thg0b1LBhQ/Xp00cJCQl64IEHNHHiRIWGhur1119XkyZNAiIuOztbr776qu655x61atVKp06d0oIFCxQVFeWPzrKveeutt+onP/mJxowZo8TERB04cEDz58+Xy+UKOFReprCwUG+99Zakv8Zb2V8C+eqrr3T//ffrqaeeqtbrU93LwHi9Xs2YMUMHDhzQtddeq8WLFysvL0/z58/3/wWSMWPGaN68eRo5cqS2bdumxMRELV26VL/73e80e/bsi55MVFU333yzPvroI82aNUter1dJSUnq0qXLZXluAH/j4BnIAC6g7PIjFV1upKSkxLRq1cq0atXKf8mUr776ygwfPtzExcWZOnXqmGbNmpk777zTLF261P+4i12eZPv27SYtLc00bdrU1KlTx8TFxZm0tDTzxRdfXHDO1atXG0nG5XIFXJrmh6oyW2Xf74UuA2OMMR999JHp3r27iYiIMFFRUWbAgAHmj3/8Y7ntDh48aIYPH+6/jE7Lli1Nenq6KS4u9m+zbds206VLFxMeHm4SEhLMrFmzyl0GJjc316SlpZmEhATjdrtNTEyMufPOO83WrVvLfc2dO3ea++67z8TExJiwsDATExNj7r//frNz585y25ZdhqXsVr9+fdO6dWszdOhQ8+GHH1b4urZo0cL079+/wnU/fN2qehmYtm3bmq1bt5quXbuaunXrmhYtWphXXnml3LZHjx41o0aNMo0bNzbh4eGmffv25o033ii33Y+/dtllYI4dOxaw3Y9fY2OM2bVrl7n99ttNRESEkcQlYYAa4DKGT94CgM2Sk5N1/Pjxi35WEsDVg88AAgAAWIYABAAAsAwBCAAAYBk+AwgAAGAZ9gACAABYhgAEAACwDAEIAABgGf4SCC5JaWmpDh8+rAYNGvB3OwGgFjLG6NSpU/J6vQF/2xl2IABxSQ4fPqz4+HinxwAA/IPy8/PVvHlzp8dAkBGAuCRlf/MzPz+/Wn+gHgBwZfD5fIqPj79sf8MZtQsBiEtSdtg3KiqKAASAWoyP8diJg/4AAACWIQABAAAsQwACAABYhgAEAACwDAFouTlz5igxMVF169ZVly5dtHnzZqdHAgAANYwAtNjixYs1YcIETZkyRbm5uerQoYP69u2rgoICp0cDAAA1iAC02KxZ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", + "text/html": [ "\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" + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " ], "text/plain": [ - "" + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" ] }, "metadata": {}, @@ -22867,11 +659,24 @@ }, { "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "bc8fdb19a3d146e7ab74f643287d3970", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAwrElEQVR4nO3de3xM56LG8WeSMIlIhiAiJBI5WnUp3XVp0eJI5WSjtEqpO73YTavKUZy9g15IVS9aVbe9i9NW6XbQcvauqmvtVl1SWq0qrUs2JdVWQlSQvOeP7szpNBeJyiy8v+/ns/6Yd62ZeWZlRh7vWrPiMsYYAQAAwBoBTgcAAACAf1EAAQAALEMBBAAAsAwFEAAAwDIUQAAAAMtQAAEAACxDAQQAALAMBRAAAMAyFEAAAADLUAABAAAsQwEEAACwDAUQAADAMhRAAAAAy1AAAQAALEMBBAAAsAwFEAAAwDIUQAAAAMtQAAEAACxDAQQAALAMBRAAAMAyFEAAAADLUAABAAAsQwEEAACwDAUQAADAMhRAAAAAy1AAAQAALEMBBAAAsAwFEAAAwDIUQAAAAMtQAAEAACxDAQQAALAMBRAAAMAyFEAAAADLUAABAAAsQwEEAACwDAUQcMjevXvVqVMneTweuVwuLV++3OlIpbJ161a1bt1aoaGhcrlc2rFjh9ORrONyufTQQw9dcLv58+fL5XLpwIEDPuNTp05VvXr1FBgYqGbNmpVPyH+ZOHGiXC5XuT4HgLKjAAIXUPBLtGAJCgpS7dq1NWjQIB0+fPiiH3fgwIH67LPPNGnSJL322mtq3ry5d93nn3+ufv36qXbt2nK73YqOjlbfvn31+eefX4qXdNHOnTunnj176ocfftALL7yg1157TXXr1nU0U0kOHDggl8ulZ599tsj1zz77bKGC1L59e+/POiAgQOHh4br22mvVv39/rV69usjHiYuL83mP/HI5c+ZMeby0i/bee+/pscceU5s2bTRv3jxNnjxZR44c0cSJEynzgEWCnA4AXCmeeOIJxcfH68yZM9q8ebPmz5+vTZs2adeuXQoODi7TY/3000/66KOP9Mc//rHQTM7SpUvVp08fRUREaOjQoYqPj9eBAwf0l7/8RUuWLNGiRYt0xx13XMqXVmpff/21Dh48qLlz5+ree+91JIM/1KlTR2lpaZKknJwc7du3T0uXLtXrr7+uXr166fXXX1eFChV87tOsWTONGjWq0GNVrFjRL5mL0r9/f/Xu3Vtut9s7tnbtWgUEBOgvf/mLN9u2bdv0+OOPKy4urtxnBAFcHiiAQCklJyd7Z+nuvfdeVa9eXVOmTNE777yjXr16lemxvvvuO0lSlSpVfMa//vpr9e/fX/Xq1dPGjRtVo0YN77pHHnlEt9xyi/r3769PP/1U9erV+20vqAxycnIUGhqqzMzMInNfbTwej/r16+cz9vTTT2v48OF65ZVXFBcXpylTpvisr127dqH7OC0wMFCBgYE+Y5mZmQoJCXG0mAJwHoeAgYt0yy23SPq5tP3Sl19+qbvuuksREREKDg5W8+bN9c4773jXT5w40XvYdPTo0XK5XIqLi5P087lZp0+f1pw5c3zKnyRVr15ds2fPVk5Ojp555hlJ0pIlS+RyubRhw4ZC+WbPni2Xy6Vdu3aVOpv0/4e8N2zYoAcffFCRkZGqU6eOBg0apHbt2kmSevbsKZfLpfbt23vvt3btWt1yyy0KDQ1VlSpV1K1bN+3evbtQrsOHD2vo0KGKjo6W2+1WfHy8/vCHP+js2bPe/VPUOWNFnc+2bds2JSUlqXr16goJCVF8fLyGDBlS6L6XQmBgoF566SU1bNhQL7/8srKyskp939OnT+vLL7/U8ePHL7jt3r171aNHD0VFRSk4OFh16tRR7969i3y+5cuXq3HjxnK73WrUqJHeffddn/W/3mcul0vz5s1TTk6O9xD1/Pnz1aJFC0nS4MGDfcYLfPzxx/qP//gPeTweVapUSe3atdM//vGPQnk2bdqkFi1aKDg4WAkJCZo9e3ap99EvHT16VIMHD1adOnXkdrtVq1YtdevWzedn73K5NHHixEL3jYuL06BBgwrtg02bNmn48OGqUaOGqlSpogceeEBnz57ViRMnNGDAAFWtWlVVq1bVY489JmPMReUGriTMAAIXqeCXUdWqVb1jn3/+udq0aaPatWtr7NixCg0N1VtvvaXu3bvrf/7nf3THHXfozjvvVJUqVfToo4+qT58++v3vf6/KlStLklasWKG4uDhvufy1W2+9VXFxcfrf//1fSVLnzp1VuXJlvfXWW95yVmDx4sVq1KiRGjduXOpsv/Tggw+qRo0aGj9+vHJycnTrrbeqdu3amjx5soYPH64WLVqoZs2akqT3339fycnJqlevniZOnKiffvpJ06dPV5s2bZSenu4tuEeOHFHLli114sQJ3X///WrQoIEOHz6sJUuW6PTp02WalcrMzFSnTp1Uo0YNjR07VlWqVNGBAwe0dOnSUj9GWQUGBqpPnz5KTU3Vpk2b1LlzZ++6c+fOFSp4lSpVUqVKlbRlyxZ16NBBEyZMKLK0FDh79qySkpKUm5urhx9+WFFRUTp8+LBWrlypEydOyOPxeLfdtGmTli5dqgcffFBhYWF66aWX1KNHDx06dEjVqlUr8vFfe+01zZkzR1u2bNGf//xnSVL9+vX1xBNPaPz48br//vu9773WrVtL+rnYJycn68Ybb9SECRMUEBCgefPm6d///d/1wQcfqGXLlpKkzz77zPvzmDhxos6fP68JEyZ43yNl0aNHD33++ed6+OGHFRcXp8zMTK1evVqHDh3yvpfKqmB/Pv7449q8ebPmzJmjKlWq6MMPP1RsbKwmT56sv/3tb5o6daoaN26sAQMGXNTzAFcMA6BE8+bNM5LM+++/b7777juTkZFhlixZYmrUqGHcbrfJyMjwbtuxY0fTpEkTc+bMGe9Yfn6+ad26talfv753bP/+/UaSmTp1qnfsxIkTRpLp1q1biXluv/12I8lkZ2cbY4zp06ePiYyMNOfPn/du8+2335qAgADzxBNPlDlbwett27atz2MaY8y6deuMJPPXv/7VZ7xZs2YmMjLSfP/9996xnTt3moCAADNgwADv2IABA0xAQIDZunVrodeVn59vjDFmwoQJpqh/mgpy7d+/3xhjzLJly4ykIh+rQFH7+ZemTp3q85jGGNOuXTvTqFGjYh+z4HlffPFF71jdunWNpELLhAkTjDH/v98Kbhfnk08+KXL//pokU7FiRbNv3z7v2M6dO40kM336dO/Yr/eZMcYMHDjQhIaG+jze1q1bjSQzb948n/H8/HxTv359k5SU5P35GGPM6dOnTXx8vLntttu8Y927dzfBwcHm4MGD3rEvvvjCBAYGFvnzLM6PP/5Y4s+sQHH7s27dumbgwIHe2wX74Nev4eabbzYul8sMGzbMO3b+/HlTp04d065du1LnBa5UHAIGSikxMVE1atRQTEyM7rrrLoWGhuqdd95RnTp1JEk//PCD1q5dq169eunkyZM6fvy4jh8/ru+//15JSUnau3dvid8aPnnypCQpLCysxBwF67OzsyVJd999tzIzM7V+/XrvNkuWLFF+fr7uvvvui8523333FTp/rCjffvutduzYoUGDBikiIsI7fv311+u2227T3/72N0lSfn6+li9frq5du/p847lAWS8VUnAe4sqVK3Xu3Lky3fe3KJitLfh5FWjVqpVWr17tsxTMIrVv317GmBJn/yR5Z/hWrVql06dPl7htYmKiEhISvLevv/56hYeH65tvvinrSyrWjh07tHfvXt1zzz36/vvvve+bnJwcdezYURs3blR+fr7y8vK0atUqde/eXbGxsd77X3fddUpKSirTcxacn7h+/Xr9+OOPl+y1DB061Oc91qpVKxljNHToUO9YYGCgmjdvfkn3IXC54hAwUEozZszQNddco6ysLL366qvauHGjz7cr9+3bJ2OMUlNTlZqaWuRjZGZmqnbt2kWuKyh2vy4Wv/brolhwbtbixYvVsWNHST8f/m3WrJmuueaai84WHx9fYo4CBw8elCRde+21hdZdd911WrVqlXJycnTq1CllZ2d7D0n/Vu3atVOPHj30+OOP64UXXlD79u3VvXt33XPPPT4/l9IoS/k8deqUpMJFvXr16kpMTCzT8/5afHy8Ro4cqeeff15vvPGGbrnlFt1+++3q16+fz+FfST5Fq0DVqlUvaWnau3evpJ8vWVScrKws5ebm6qefflL9+vULrb/22mu9/wkoDbfbrSlTpmjUqFGqWbOmbrrpJnXp0kUDBgxQVFRU2V/Ev/x6fxXsz5iYmELjl3IfApcrCiBQSi1btvTOXHXv3l1t27bVPffcoz179qhy5crKz8+XJP3nf/5nsbMe//Zv/1bs43s8HtWqVUuffvppiTk+/fRT1a5dW+Hh4ZJ+/oXZvXt3LVu2TK+88oqOHTumf/zjH5o8ebL3PheTLSQkpMQc5aW4MpaXl1douyVLlmjz5s1asWKFVq1apSFDhui5557T5s2bVblyZe/leX766aciH7Nglq0sl/Ep+FJNST/L3+K5557ToEGD9Pbbb+u9997T8OHDlZaWps2bN3tnmyUVOztrLuEXGAreN1OnTi328jCVK1dWbm7uJXtOSRoxYoS6du2q5cuXa9WqVUpNTVVaWprWrl2rG264ocT7/vp9UqC4/VXU+KXch8DligIIXITAwEClpaWpQ4cOevnllzV27FjvZVkqVKhw0TNBXbp00dy5c7Vp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sGFDn7HrrrtOhw4dcihR6YwePVpjx45V79691aRJE/Xv31+PPvqo0tLSnI5WagWfxSv5c1pQ/g4ePKjVq1df9rN/H3zwgTIzMxUbG+v9rB48eFCjRo1SXFyc0/FgCQogyk3FihV14403as2aNd6x/Px8rVmzRjfffLODyS7MGKOHHnpIy5Yt09q1axUfH+90pAvq2LGjPvvsM+3YscO7NG/eXH379tWOHTsUGBjodMRitWnTptBldr766ivVrVvXoUSlc/r0aQUE+P4zGhgYqPz8fIcSlV18fLyioqJ8PqfZ2dn6+OOPL/vPqfT/5W/v3r16//33Va1aNacjXVD//v316aef+nxWo6OjNXr0aK1atcrpeLAEh4BRrkaOHKmBAweqefPmatmypaZNm6acnBwNHjzY6WglSklJ0cKFC/X2228rLCzMey6Ux+NRSEiIw+mKFhYWVugcxdDQUFWrVu2yP3fx0UcfVevWrTV58mT16tVLW7Zs0Zw5czRnzhyno5Woa9eumjRpkmJjY9WoUSN98sknev755zVkyBCno/k4deqU9u3b5729f/9+7dixQxEREYqNjdWIESP01FNPqX79+oqPj1dqaqqio6PVvXt350L/S0nZa9Wqpbvuukvp6elauXKl8vLyvJ/ViIgIVaxY0anYF9znvy6qFSpUUFRUlK699lp/R4WtnP4aMq5+06dPN7GxsaZixYqmZcuWZvPmzU5HuiBJRS7z5s1zOlqZXCmXgTHGmBUrVpjGjRsbt9ttGjRoYObMmeN0pAvKzs42jzzyiImNjTXBwcGmXr165o9//KPJzc11OpqPdevWFfl+HjhwoDHm50vBpKammpo1axq32206duxo9uzZ42zofykp+/79+4v9rK5bt+6yzV0ULgMDf3MZc5ldsh4AAADlinMAAQAALEMBBAAAsAwFEAAAwDIUQAAAAMtQAAEAACxDAQQAALAMBRAAAMAyFEAAAADLUAABAAAsQwEEAACwDAUQAADAMhRAAAAAy1AAAQAALEMBBAAAsAwFEAAAwDIUQAAAAMtQAAEAACxDAQQAALAMBRAAAMAyFEAAAADLUAABAAAsQwEEAACwDAUQAADAMhRAAAAAy1AAAQAALEMBBAAAsAwFEAAAwDIUQAAAAMtQAAEAACxDAQQAALAMBRAAAMAy/wdMeTAyUv7fDAAAAABJRU5ErkJggg==", "text/html": [ - "" + "\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " ], "text/plain": [ - "" + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" ] }, "metadata": {}, @@ -22879,964 +684,99 @@ }, { "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", + "application/vnd.jupyter.widget-view+json": { + "model_id": "8ac1972cd2fe46b18a576dcdc8dd151d", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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9OhiP9jw008/qUOHDsrNzdXDDz+s6OhoHTx4UEuXLtXx48fl8XgkSWPGjFFqaqp69OihwYMH67vvvtOrr76qW2+9VVu3bi32CO2QIUM0ffp0DRw4UCkpKdq3b59ee+01bd26VR9//LHv1Pb06dM1aNAgNWjQQKNGjVLFihW1detWffDBB+rdu7eeeOIJZWVl6ZtvvtGECRMkyfdz7PV61aVLF61fv17333+/rrvuOu3YsUMTJkzQF1984feBp8GDB2vmzJnq3bu3WrZsqVWrVvm9rgCKYQCUmrfeestIMitWrDDfffedyczMNPPnzzdVq1Y1brfbZGZm+vZt166dSUhIMGfOnPGt83q9pmXLlqZevXq+dfv27TOSzAsvvOBbd/z4cSPJdO3atdh5unTpYiSZ7OxsY4wxvXr1MlFRUebs2bO+fb799lsTFBRk/vrXv17wbAVfb6tWrfwe0xhjVq9ebSSZd999129948aNTVRUlPn+++9967Zv326CgoJM//79fev69+9vgoKCzKZNmwp9XV6v1xhjzOjRo01Rf9YK5tq3b58xxpiFCxcaSUU+VoGiXudfeuGFF/we0xhjWrdubRo0aHDOxyx43pdfftm3rlatWkZSoWX06NHGmP+8bgW3z2Xr1q1Fvr6/tH//fhMcHGzGjBnjt37Hjh0mJCTEb/2AAQNMrVq1fLc/+ugjI8nMmjXL774ffPCB3/rjx4+b8PBw06JFC3P69Gm/fQu+T8YY06lTJ7/HL/D222+boKAg89FHH/mtnzJlipFkPv74Y2OMMdu2bTOSzIMPPui3X+/evUv0egG24xQwEABJSUmqWrWqYmNjdddddyksLEyLFy9WzZo1JUk//PCDVq1apR49eujEiRM6duyYjh07pu+//14dOnRQRkZGsZ8aPnHihCQpPDy82DkKtmdnZ0uS7r77bh09elRr1qzx7TN//nx5vV7dfffdFz3bfffdp+Dg4PO+Lt9++622bdume+65R5GRkb71N9xwg/7whz/oH//4h6SfjwotWrRInTt39vvEc4GiTvsWp+Ao19KlS5WXl3dB9/0tCo5yFXy/CrRo0ULLly/3W/r37y/p59OlxpjzXtak4AjfsmXLdOrUqSL3WbBggbxer3r06OH7Ph47dkzR0dGqV6+eVq9efc7Hf/fdd+XxePSHP/zB775NmjRRhQoV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", + "text/html": [ "\n", - "mpl.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", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2d29bd22cb4b45e9b9f15201e35731d6", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAsO0lEQVR4nO3de3hU9Z3H8c/kwiSEZDCEkAQSElgKChFsIyigQM3CRkDwAspyiYCiNRoRywLbBmwVAt6KF+S2W2BVBMsKCm1VRC6yFblERCxXBUxBCChkIEgMyW//aDN1TAgJkjmE3/v1POePOefM5DsDk+f9nDNz4jLGGAEAAMAaQU4PAAAAgMAiAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACltqzZ4969uwpj8cjl8ulZcuWOT1StWzatEmdO3dWRESEXC6Xtm7d6vRIAFDnEIDAJW7+/PlyuVy+JSQkRE2bNtXdd9+tgwcPXvDjZmZm6tNPP9XkyZP18ssvKy0tzbfts88+05AhQ9S0aVO53W4lJCRo8ODB+uyzzy7GU7pgJSUlGjBggL755hv97ne/08svv6zmzZs7OlNV9u/fL5fLpaeffrrS7U8//bRcLpf279/vW9e9e3ffv3VQUJCioqLUunVrDR06VCtXrqz0cZKTk/3+j3x/OXPmTG08NQB1XIjTAwCont/+9rdKSUnRmTNntGHDBs2fP1/r16/X9u3bFRYWVqPH+vbbb/Xhhx/qV7/6lR588EG/bW+88YYGDRqk6OhojRw5UikpKdq/f7/++7//W0uWLNGiRYt06623XsynVm2ff/65Dhw4oLlz5+qee+5xZIZAaNasmXJzcyVJRUVF2rt3r9544w298sorGjhwoF555RWFhob63adDhw569NFHKzxWvXr1AjIzgLqFAATqiIyMDN9RunvuuUcxMTGaNm2a3nrrLQ0cOLBGj3X06FFJUsOGDf3Wf/755xo6dKhatGihdevWqXHjxr5tDz/8sG644QYNHTpU27ZtU4sWLX7cE6qBoqIiRUREqKCgoNK5Lzcej0dDhgzxWzd16lRlZ2frpZdeUnJysqZNm+a3vWnTphXuAwDnwilgoI664YYbJP092r5v586duuOOOxQdHa2wsDClpaXprbfe8m1/7LHHfKdNx44dK5fLpeTkZEnSU089pdOnT2vOnDl+8SdJMTExmj17toqKivTkk09KkpYsWSKXy6W1a9dWmG/27NlyuVzavn17tWeT/nnKe+3atXrggQcUGxurZs2a6e6771a3bt0kSQMGDJDL5VL37t1993v//fd1ww03KCIiQg0bNlS/fv20Y8eOCnMdPHhQI0eOVEJCgtxut1JSUvSLX/xC3333ne/1cblcFe5XPtf3T9du3rxZvXr1UkxMjMLDw5WSkqIRI0ZUuO/FEBwcrOeff15XXXWVXnzxRRUWFlb7vqdPn9bOnTt17Nix8+67Z88e3X777YqLi1NYWJiaNWumu+66y/fzyk9rz58/v8J9XS6XHnvsMd/t8tdy9+7dGjJkiDwejxo3bqycnBwZY5Sfn69+/fopKipKcXFxeuaZZ6r9nAD8OBwBBOqo8hC54oorfOs+++wzdenSRU2bNtX48eMVERGh119/Xf3799f//u//6tZbb9Vtt92mhg0b6pFHHtGgQYN08803q0GDBpKk5cuXKzk52ReXP3TjjTcqOTlZf/zjHyVJvXv3VoMGDfT666/74qzc4sWL1bZtW7Vr167as33fAw88oMaNG2vixIkqKirSjTfeqKZNm2rKlCnKzs7WtddeqyZNmkiS3nvvPWVkZKhFixZ67LHH9O233+qFF15Qly5dlJeX5wvcQ4cOqWPHjjpx4oRGjRqlNm3a6ODBg1qyZIlOnz5do9OlBQUF6tmzpxo3bqzx48erYcOG2r9/v954441qP0ZNBQcHa9CgQcrJydH69evVu3dv37aSkpIKgVe/fn3Vr19fGzduVI8ePTRp0iS/QPuh7777Tr169VJxcbEeeughxcXF6eDBg1qxYoVOnDghj8dzQXPfeeeduvLKKzV16lT98Y9/1BNPPKHo6GjNnj1bP//5zzVt2jS9+uqr+uUvf6lrr71WN9544wX9HAA1YABc0ubNm2ckmffee88cPXrU5OfnmyVLlpjGjRsbt9tt8vPzffvedNNNJjU11Zw5c8a3rqyszHTu3Nm0atXKt27fvn1Gknnqqad8606cOGEkmX79+lU5zy233GIkGa/Xa4wxZtCgQSY2NtacPXvWt89XX31lgoKCzG9/+9saz1b+fLt27er3mMYYs3r1aiPJ/OEPf/Bb36FDBxMbG2u+/vpr37pPPvnEBAUFmWHDhvnWDRs2zAQFBZlNmzZVeF5lZWXGGGMmTZpkKvvVWD7Xvn37jDHGLF261Eiq9LHKVfY6f99TTz3l95jGGNOtWzfTtm3bcz5m+c997rnnfOuaN29uJFVYJk2aZIz55+tWfvtcPv7440pf38qe07x58yps++HPKH8tR40a5Vt39uxZ06xZM+NyuczUqVN9648fP27Cw8NNZmZmlTMCuDg4BQzUEenp6WrcuLESExN1xx13KCIiQm+99ZaaNWsmSfrmm2/0/vvva+DAgTp58qSOHTumY8eO6euvv1avXr20Z8+eKr81fPLkSUlSZGRklXOUb/d6vZL+fnSnoKBAa9as8e2zZMkSlZWV6c4777zg2e69914FBwef93X56quvtHXrVt19992Kjo72rb/66qv1r//6r/rTn/4kSSorK9OyZcvUt29fv288l6vstG9Vyj+HuGLFCpWUlNTovj9G+dHa8n+vcp06ddLKlSv9lmHDhkn6+zeLjTFVHv2T5DvC98477+j06dMXbebvf2EnODhYaWlpMsZo5MiRvvUNGzZU69at9cUXX1y0nwvg3AhAoI6YMWOGVq5cqSVLlujmm2/WsWPH5Ha7fdv37t0rY4xycnLUuHFjv2XSpEmS5PsSRWXKw+6HYfFDPwzFf/u3f5PH49HixYt9+yxevFgdOnTQT37ykwueLSUlpVqvy4EDByRJrVu3rrDtyiuv1LFjx1RUVKSjR4/K6/X6Tkn/WN26ddPtt9+u3/zmN4qJiVG/fv00b948FRcX1/ixahKfp06dklQx1GNiYpSenu631PSLOikpKRozZoz+67/+SzExMerVq5dmzJhRo88bViYpKcnvtsfjUVhYmGJiYiqsP378+I/6WQCqh88AAnVEx44dfUeu+vfvr65du+rf//3ftWvXLjVo0EBlZWWSpF/+8pfq1atXpY/xL//yL+d8fI/Ho/j4eG3btq3KObZt26amTZsqKipKkuR2u9W/f38tXbpU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", + "text/html": [ "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " fig.ondownload(fig, null);\n", - "};\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6576a79ed36d410891936727d4b64188", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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Kjo6OuBdyVWpOAp1+vTpgPWXOqL1ox/9SDNnzlROTo5ef/11ffrpp1q5cqUkKTY2VvXr169ytoqZ69evryZNmlx2pgplZWVasWKF6tevrx49elTrPtfi2LFjKikpCVh38OBBSfK/oaZFixY6dOiQP+4r7N+/37/9erjaU/MAgocABOqISZMmKTIyUo8++qi+/PLLgG1fffWVHnvsMdWvX1+TJk0K2JaamqqYmBitWrVKq1atUufOnQNO4cbFxalXr15atGiRvvjii0o/9+TJk9c8c9OmTdWxY0ctW7YsINr27t2rd999V/fee68kKSQkRIMGDdL69euVk5NT6XEqjjpVvMt069at/m0VH0Xy977++utKR6o6duwoSf7TwKGhoerTp4/Wr1+vzz//PGDfzz//XOvXr1efPn2qda1jWVmZMjIytG/fPmVkZPiPwFbH1XwMjCR9++23WrRokf/2hQsXtGjRIsXGxuqOO+6QJN177706fvx4wKn/b7/9Vi+//LIaNGhQ6V3h1yoqKqpSjAO4MXAKGKgjWrVqpWXLlmno0KFq3759pW8COXXqlN54441KH8VRr149/fjHP9bKlStVUlJS5VefzZ8/Xz169FD79u31yCOPqGXLljpx4oS2b9+uv/zlL/r444+vee45c+aoX79+6tq1q8aOHev/GBiPxxPwxodZs2bp3XffVc+ePTVu3Di1adNGX3zxhd58801t27ZNjRo1Up8+fZSUlKSxY8dq0qRJCg0N1a9+9SvFxsYGRNyyZcv06quv6oEHHtDNN9+sM2fOaMmSJYqOjvZHZ8XP/NGPfqQf/vCHGjdunJKTk3XkyBEtXrxYLpcr4FR5heLiYi1fvlzSX+Ot4ptAPvvsMz388MN6+umnr+r5udqPgfF6vZo9e7aOHDmiH/zgB1q1apXy8vK0ePFi/zeQjBs3TosWLdKoUaO0e/duJScna82aNfr973+vefPmXfMR3e+644479N5772nu3Lnyer1KSUlRly5drstjA/ienHwLMoDrb8+ePSYtLc00bdrU1KtXzyQkJJi0tDTzySefXPI+GzduNJKMy+UyhYWFVe7z2WefmREjRpiEhARTr14906xZM3PfffeZNWvW+Pep+LiVqj5e5VIfA2OMMe+9957p3r27iYyMNNHR0WbAgAHmT3/6U6X9CgoKzIgRI0xsbKxx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", + "text/html": [ "\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", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f298d9f6cd664eccac4e1c550ec55b05", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAvGUlEQVR4nO3df1xUdb7H8fcAOiDBKCoCCoJcNxNJ2/xRUqlXkss107JMrymp/dooMrum3rv+aCvJrNYy81e76q1MW68/0rtl5s/cMn+QlmWm5Q9WU7ISFBIRvvePltkdARVX5qjf1/PxmD/mnDPDh8Ogr8c5ZwaXMcYIAAAA1ghwegAAAAD4FwEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIGCpTZs2qWPHjgoNDZXL5dLWrVudHsk6LpdLDz/88Fm3mz17tlwul/bu3euzfOLEiWrWrJkCAwPVpk2bmhnyb8aNGyeXy1WjXwOA/xCAQA364osvdPfdd6tx48Zyu92KiYlR//799cUXXzg6V0lJie688079+OOP+v3vf6/XX39dTZs2dXSmM9m7d69cLpeef/75Stc///zzFQKpc+fOcrlccrlcCggIUHh4uK688koNGDBAK1asqPR54uPjvY85/XbixIma+NbO2/vvv68nnnhCKSkpmjVrlsaPH6+DBw9q3LhxxDyAswpyegDgcrVw4UL169dPERERGjJkiBISErR371794Q9/0IIFCzRv3jzddtttjsz2zTffaN++fZo5c6buvfdeR2bwhyZNmig7O1uSVFhYqN27d2vhwoV644031KdPH73xxhuqVauWz2PatGmjxx9/vMJz1a5d2y8zV2bAgAHq27ev3G63d9mqVasUEBCgP/zhD97ZNm/erCeffFLx8fE1fkQQwKWNAARqwDfffKMBAwaoWbNmWrdunRo2bOhd9+ijj+rGG2/UgAED9Nlnn6lZs2Z+m6uwsFChoaHKy8uTJNWtW9dvX9sJHo9Hd999t8+yZ599VllZWXr11VcVHx+vCRMm+Kxv3Lhxhcc4LTAwUIGBgT7L8vLyFBIS4miYArh0cQoYqAETJ05UUVGRZsyY4RN/ktSgQQNNnz5dhYWFeu655yRJCxYskMvl0tq1ays81/Tp0+VyubR9+3bvsq+++kp33HGHIiIiFBwcrLZt2+qdd97xeVz5dWNr167VQw89pMjISDVp0kT33HOPOnXqJEm688475XK51LlzZ+/jVq1apRtvvFGhoaGqW7euevbsqR07dlSY68CBAxoyZIhiYmLkdruVkJCg3/zmNzp58qSkqq8Zq+x6ts2bNystLU0NGjRQSEiIEhISNHjw4LPs5fMTGBiol19+WS1bttQrr7yi/Pz8c35sUVGRvvrqKx05cuSs2+7atUu9e/dWVFSUgoOD1aRJE/Xt27fSr7d48WK1atVKbrdbSUlJeu+993zWn77PXC6XZs2apcLCQu8p6tmzZ6tdu3aSpEGDBvksL/fJJ5/o3/7t3+TxeFSnTh116tRJf/nLXyrMs379erVr107BwcFKTEzU9OnTz3kf/aNDhw5p0KBBatKkidxut6Kjo9WzZ0+fn73L5dK4ceMqPDY+Pl733HNPhX2wfv16ZWVlqWHDhqpbt64eeOABnTx5UkePHtXAgQNVr1491atXT0888YSMMec1N2ADjgACNWDp0qWKj4/XjTfeWOn6m266SfHx8fq///s/SVL37t11xRVX6O233/bGWbn58+crKSlJrVq1kvTLdYUpKSlq3LixRo4cqdDQUL399tvq1auX/vd//7fCaeWHHnpIDRs21JgxY1RYWKibbrpJjRs31vjx45WVlaV27dqpUaNGkqQPPvhA6enpatasmcaNG6eff/5ZkydPVkpKinJychQfHy9JOnjwoNq3b6+jR4/q/vvvV4sWLXTgwAEtWLBARUVF1ToqlZeXp27duqlhw4YaOXKk6tatq71792rhwoXn/BzVFRgYqH79+mn06NFav369unfv7l1XUlJSIfDq1KmjOnXqaOPGjerSpYvGjh1babSUO3nypNLS0lRcXKxHHnlEUVFROnDggJYtW6ajR4/K4/F4t12/fr0WLlyohx56SGFhYXr55ZfVu3dv7d+/X/Xr16/0+V9//XXNmDFDGzdu1GuvvSZJat68uX73u99pzJgxuv/++72vvY4dO0r6JezT09N17bXXauzYsQoICNCsWbP0r//6r/rwww/Vvn17SdLnn3/u/XmMGzdOp06d0tixY72vkero3bu3vvjiCz3yyCOKj49XXl6eVqxYof3793tfS9VVvj+ffPJJbdiwQTNmzFDdunX10UcfKS4uTuPHj9ef//xnTZw4Ua1atdLAgQPP6+sAlz0D4II6evSokWR69ux5xu1uvfVWI8kUFBQYY4zp16+fiYyMNKdOnfJu891335mAgADzu9/9zrusa9euJjk52Zw4ccK7rKyszHTs2NE0b97cu2zWrFlGkrnhhht8ntMYY1avXm0kmT/96U8+y9u0aWMiIyPNDz/84F22bds2ExAQYAYOHOhdNnDgQBMQEGA2bdpU4fsqKyszxhgzduxYU9k/MeVz7dmzxxhjzKJFi4ykSp+r3J49e4wkM3HixErXT5w40ec5jTGmU6dOJikpqcrnLP+6L730kndZ06ZNjaQKt7Fjxxpj/r7fyu9X5dNPP610/55Okqldu7bZvXu3d9m2bduMJDN58mTvstP3mTHGZGRkmNDQUJ/n27Rpk5FkZs2a5bO8rKzMNG/e3KSlpXl/PsYYU1RUZBISEszNN9/sXdarVy8THBxs9u3b51325ZdfmsDAwEp/nlX56aefzvgzK1fV/mzatKnJyMjw3i/fB6d/D9dff71xuVzmwQcf9C47deqUadKkienUqdM5zwvYhlPAwAV27NgxSVJYWNgZtytfX1BQIEm66667lJeXpzVr1ni3WbBggcrKynTXXXdJkn788UetWrVKffr00bFjx3TkyBEdOXJEP/zwg9LS0rRr1y4dOHDA5+vcd999Fa4fq8x3332nrVu36p577lFERIR3+dVXX62bb75Zf/7znyVJZWVlWrx4sXr06KG2bdtWeJ7qflRI+XWIy5YtU0lJSbUe+8+44oorJP3951WuQ4cOWrFihc+t/ChS586dZYw549E/Sd4jfMuXL1dRUdEZt01NTVViYqL3/tVXX63w8HB9++231f2WqrR161bt2rVL//Ef/6EffvjB+7opLCxU165dtW7dOpWVlam0tFTLly9Xr169FBcX5338VVddpbS0tGp9zfLrE9esWaOffvrpgn0vQ4YM8XmNdejQQcYYDRkyxLssMDBQbdu2vaD7ELjcEIDABVYedqeHxelOD8Xya7Pmz5/v3Wb+/Plq06aNfvWrX0mSdu/eLWOMRo8erYYNG/rcxo4dK0neN3iUS0hIOKe59+3bJ0m68sorK6y76qqrvMHw/fffq6CgwHtK+p/VqVMn9e7dW08++aQaNGignj17atasWSouLq72c1UnPo8fPy6pYqg3aNBAqampPrfqvlEnISFBw4YN02uvvaYGDRooLS1NU6ZMqfT6v38MrXL16tW7oNG0a9cuSVJGRkaF181rr72m4uJi5efn6/vvv9fPP/+s5s2bV3iOyl4XZ+J2uzVhwgS9++67atSokW666SY999xzOnTo0D/1vZy+v8pjOzY2tsLyC7kPgcsN1wACF5jH41F0dLQ+++yzM2732WefqXHjxgoPD5f0y3+YvXr10qJFi/Tqq6/q8OHD+stf/qLx48d7H1NWViZJ+s///M8qj8j8y7/8i8/9kJCQf+bbOW9VxVhpaWmF7RYsWKANGzZo6dKlWr58uQYPHqwXXnhBGzZs0BVXXKHg4GBJ0s8//1zpc5YfZSvf7lyUv6nm9P11obzwwgu65557tGTJEr3//vvKyspSdna2NmzYoCZNmni3q+rorLmAb2Aof91MnDixyo+HueKKK84rus9k6NCh6tGjhxYvXqzly5dr9OjRys7O1qpVq3TNNdec8bGnv07KVbW/Klt+IfchcLkhAIEacMstt2jmzJlav369brjhhgrrP/zwQ+3du1cPPPCAz/K77rpLc+bM0cqVK7Vjxw4ZY7ynfyV5j0TVqlVLqampF3Tm8g+C3rlzZ4V1X331lRo0aKDQ0FCFhIQoPDzc513JlalXr54k6ejRoz4fN1N+pPF01113na677jo988wzmjt3rvr376958+bp3nvvVcOGDVWnTp1KZyufuU6dOmrQoMG5fKsqLS3V3LlzVadOnUp/PhdKcnKykpOT9dvf/lYfffSRUlJSNG3aND399NM18vWqiu7yU8zh4eFnfN00bNhQISEh3iOG/6iqfX82iYmJevzxx/X4449r165datOmjV544QW98cYbkn55nRw9etTnMSdPntR33313Xl8PwLnhFDBQA4YPH66QkBA98MAD+uGHH3zW/fjjj3rwwQdVp04dDR8+3GddamqqIiIiNH/+fM2fP1/t27f3OYUbGRmpzp07a/r06ZX+B/n999+f98zR0dFq06aN5syZ4/Mf8vbt2/X+++/r3//93yVJAQEB6tWrl5YuXarNmzdXeJ7yoy7l0bFu3TrvusLCQs2ZM8dn+59++qnCkZryo1TlR6QCAwPVrVs3LV26VPv37/fZdv/+/Vq6dKm6det2Ttc6lpaWKisrSzt27FBWVpb3COy5ONePgSkoKNCpU6d8liUnJysgIOCCH2X7R6GhoZJUIaiuvfZaJSYm6vnnn/ee+v5H5a+bwMBApaWlafHixT77eceOHVq+fHm1ZikqKqrw11MSExMVFhbmsw8SExN9XiOSNGPGjCqPAAK4MDgCCNSA5s2ba86cOerfv7+Sk5Mr/CWQI0eO6K233vK5+F/65cje7bffrnnz5qmwsLDSP302ZcoU3XDDDUpOTtZ9992nZs2a6fDhw/r444/117/+Vdu2bTvvuSdOnKj09HRdf/31GjJkiPdjYDwej88bH8aPH6/3339fnTp10v3336+rrrpK3333nf70pz9p/fr1qlu3rrp166a4uDgNGTJEw4cPV2BgoP74xz+qYcOGPnExZ84cvfrqq7rtttuUmJioY8eOaebMmQoPD/dGZ/nXvO666/TrX/9a999/v+Lj47V3717NmDFDLpfL51R5ufz8fO+RpqKiIu9fAvnmm2/Ut29fPfXUU9XaP+f6MTCrVq3Sww8/rDvvvFO/+tWvdOrUKb3++usKDAxU7969q/U1qyMxMVF169bVtGnTFBYWptDQUHXo0EEJCQl67bXXlJ6erqSkJA0aNEiNGzfWgQMHtHr1aoWHh2vp0qWSpCeffFLvvfeebrzxRj300EM6deqUJk+erKSkpLNe1vCPvv76a3Xt2lV9+vRRy5YtFRQUpEWLFunw4cPq27evd7t7771XDz74oHr37q2bb75Z27Zt0/Lly8/5aC6A8+TcG5CBy99nn31m+vXrZ6Kjo02tWrVMVFSU6devn/n888+rfMyKFSuMJONyuUxubm6l23zzzTdm4MCBJioqytSqVcs0btzY3HLLLWbBggXebco/NqOyj1ep6mNgjDHmgw8+MCkpKSYkJMSEh4ebHj16mC+//LLCdvv27TMDBw40DRs2NG632zRr1sxkZmaa4uJi7zZbtmwxHTp0MLVr1zZxcXHmxRdfrPCRJjk5OaZfv34mLi7OuN1uExkZaW655RazefPmCl9zx44d5q677jKRkZEmKCjIREZGmr59+5odO3ZU2LZTp04+H+VyxRVXmObNm5u7777bvP/++5Xu16ZNm5ru3btXuu4f99vZPgbm22+/NYMHDzaJiYkmODjYREREmC5dupgPPvjAZztJJjMzs9I5KvsIlLN9DIwxxixZssS0bNnSBAUFVfhImE8//dTcfvvtpn79+sbtdpumTZuaPn36mJUrV/o8x9q1a821115rateubZo1a2amTZtW5cf6VOXIkSMmMzPTtGjRwoSGhhqPx2M6dOhg3n77bZ/tSktLzYgRI0yDBg1MnTp1TFpamtm9e3eV++D013P5XN9//73P8qr2D4BfuIzhKlkAAACbcA0gAACAZbgGEABQLfn5+VV+JE+5qKgoP00D4HxwChgAUC333HNPhXdzn47/WoCLGwEIAKiWL7/8UgcPHjzjNhf6cyoBXFgEIAAAgGV4EwgAAIBleBMIzktZWZkOHjyosLCwKv/8FADg4mWM0bFjxxQTE6OAAI4H2YYAxHk5ePCgYmNjnR4DAPBPys3NVZMmTZweA35GAOK8hIWFSZJu0L8rSLUcngYAUF2nVKL1+rP333PYhQDEeSk/7RukWgpyEYAAcMn521tAuYzHTpz0BwAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQMtNmTJF8fHxCg4OVocOHbRx40anRwIAADWMALTY/PnzNWzYMI0dO1Y5OTlq3bq10tLSlJeX5/RoAACgBhGAFnvxxRd13333adCgQWrZsqWmTZumOnXq6I9//KPTowEAgBpEAFrq5MmT2rJli1JTU73LAgIClJqaqo8//rjC9sXFxSooKPC5AQCASxMBaKkjR46otLRUjRo18lneqFEjHTp0qML22dnZ8ng83ht/Bg4AgEsXAYhzMmrUKOXn53tvubm5To8EAADOE38KzlINGjRQYGCgDh8+7LP88OHDioqKqrC92+2W2+3213gAAKAGcQTQUrVr19a1116rlStXepeVlZVp5cqVuv766x2cDAAA1DSOAFps2LBhysjIUNu2bdW+fXtNmjRJhYWFGjRokNOjAQCAGkQAWuyuu+7S999/rzFjxujQoUNq06aN3nvvvQpvDAEAAJcXlzHGOD0ELj0FBQXyeDzqrJ4KctVyehwAQDWdMiVaoyXKz89XeHi40+PAz7gGEAAAwDIEIAAAgGUIQAAA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", + "text/html": [ "\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" + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " ], "text/plain": [ - "" + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" ] }, "metadata": {}, @@ -23844,11 +784,24 @@ }, { "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ba728075f6004e4a96a56a42006b2c5a", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAuP0lEQVR4nO3de3jMd97/8dfkYEQkQxAREglrqyWl69SKFrcst1sdelJnpQfdpk1VV/HbTbV3S6oH9KCU695yF0UtWnZbVYeqbtUhorWLoqEpJdVWhqg0Mp/fH93MvdNEHFbmi8/zcV3zx3y/35l5ZyKu5/X5zsFljDECAACANUKcHgAAAADBRQACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABHDeNm/erPbt2ysyMlIul0s5OTlOj4QzuOuuu5SUlOT0GBfE5XLpiSeecHoM4IpEAAKXqL///e8aNGiQ6tevL7fbrfj4eA0cOFB///vfHZ2ruLhYd9xxh77//ntNmTJFb7zxhho2bOjoTBXZv3+/XC6Xnn/++XL3P//883K5XNq/f79/W6dOneRyueRyuRQSEqLo6GhdddVVGjx4sFatWlXu/SQlJflv88vLqVOnKuNHuyTMnz9fU6dOdXoMAOcpzOkBAJS1ZMkS9e/fXzExMbr77ruVnJys/fv363/+53+0ePFiLViwQLfccosjs+3bt08HDhzQrFmzdM899zgyQzA0aNBAWVlZkqTCwkLt3btXS5Ys0dy5c9W3b1/NnTtX4eHhAbdp2bKlHn300TL3VaVKlaDM7IT58+drx44dGjlypNOjADgPBCBwidm3b58GDx6sRo0aaf369apTp45/38MPP6wbb7xRgwcP1meffaZGjRoFba7CwkJFRkYqPz9fklSjRo2gPbYTPB6PBg0aFLDtmWeeUUZGhl599VUlJSVp0qRJAfvr169f5jYAcCniFDBwiXnuued08uRJzZw5MyD+JKl27dp67bXXVFhYqGeffVaStHjxYrlcLn344Ydl7uu1116Ty+XSjh07/Nt27dql22+/XTExMapatapat26td955J+B2s2fP9t/nAw88oNjYWDVo0EB33XWXOnbsKEm644475HK51KlTJ//t1qxZoxtvvFGRkZGqUaOGevfurZ07d5aZ6+DBg7r77rsVHx8vt9ut5ORk/e53v9NPP/0kSXriiSfkcrnK3K50rn89XbtlyxZ169ZNtWvXVkREhJKTkzV8+PCzPMsXJjQ0VC+99JKuueYavfLKKyooKDjn2548eVK7du3S0aNHz3rsnj17dNtttykuLk5Vq1ZVgwYN1K9fvzKPN3fuXLVq1UoRERGKiYlRv379lJeXd9b79/l8mjp1qpo1a6aqVauqbt26GjFihH744Ycyx7777rvq2LGjoqKiFB0drTZt2mj+/PmSfj5V/pe//EUHDhzwn+7+19cbFhUVafz48frVr34lt9uthIQEPfbYYyoqKgp4jKKiIj3yyCOqU6eOoqKi1KtXL3399ddn/TkAXDhWAIFLzPLly5WUlKQbb7yx3P033XSTkpKS9Je//EWS1KNHD1WvXl2LFi3yx1mphQsXqlmzZmrevLmkn19XmJqaqvr162vs2LGKjIzUokWL1KdPH/35z38uc1r5gQceUJ06dfT444+rsLBQN910k+rXr6+JEycqIyNDbdq0Ud26dSVJH3zwgbp3765GjRrpiSee0I8//qiXX35Zqampys7O9ofBoUOH1LZtWx07dkz33XefmjZtqoMHD2rx4sU6efLkeZ0uzc/PV9euXVWnTh2NHTtWNWrU0P79+7VkyZJzvo/zFRoaqv79+yszM1MbNmxQjx49/PuKi4vLBF61atVUrVo1bdq0SZ07d9b48eMrfGPDTz/9pG7duqmoqEgPPfSQ4uLidPDgQa1YsULHjh2Tx+ORJE2YMEGZmZnq27ev7rnnHn377bd6+eWXddNNN2nbtm0VrtCOGDFCs2fP1rBhw5SRkaHc3Fy98sor2rZtmz7++GP/qe3Zs2dr+PDhatasmcaNG6caNWpo27Zteu+99zRgwAD94Q9/UEFBgb7++mtNmTJFklS9enVJP0dmr169tGHDBt133326+uqr9fnnn2vKlCn64osvtGzZMv8899xzj+bOnasBAwao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wsJCSVL37t0lSS+99FLAMXy7CFC5WAEELjFNmjTRnDlzNHDgQKWkpJT5JpCjR4/qzTffLPOaqfDwcN16661asGCBCgsLy/3qs2nTpqlDhw5KSUnRvffeq0aNGunIkSP65JNP9PXXX2v79u0XPPdzzz2n7t2764YbbtDdd9/t/xgYj8cT8MaHiRMn6v3331fHjh39Hw/yzTff6K233tKGDRtUo0YNde3aVYmJibr77rs1evRohYaG6k9/+pPq1KkTEHFz5szRq6++qltuuUWNGzfW8ePHNWvWLEVHR/ujs/Qxr7/+ev3mN7/Rfffdp6SkJO3fv18zZ86Uy+UKOFVeqqCgQHPnzpX0c7yVfhPIvn371K9fv3IDqiLn+jEwa9as0YMPPqg77rhDv/71r3X69Gm98cYbCg0N1W233Sbp50B++umnNW7cOO3fv199+vRRVFSUcnNztXTpUt133336/e9/X+79d+zYUSNGjFBWVpZycnLUtWtXhYeHa8+ePXrrrbf04osv6vbbb1d0dLSmTJmie+65R23atNGAAQNUs2ZNbd++XSdPnvTHeKtWrbRw4UKNGjVKbdq0UfXq1dWzZ08NHjxYixYt0v3336+1a9cqNTVVJSUl2rVrlxYtWqSVK1eqdevWatmypfr3769XX31VBQUFat++vVavXq29e/ee1/ML4Dw59fZjABX77LPPTP/+/U29evVMeHi4iYuLM/379zeff/75GW+zatUqI8m4XC6Tl5dX7jH79u0zQ4YMMXFxcSY8PNzUr1/f3HzzzWbx4sX+Y0o/bqW8j1c508fAGGPMBx98YFJTU01ERISJjo42PXv2NP/4xz/KHHfgwAEzZMgQU6dOHeN2u02jRo1Menq6KSoq8h+zdetW065dO1OlShWTmJhoJk+eXOZjYLKzs03//v1NYmKicbvdJjY21tx8881my5YtZR5z586d5s477zSxsbEmLCzMxMbGmn79+pmdO3eWObZjx44BH+VSvXp106RJEzNo0CDz/vvvl/u8NmzY0PTo0aPcff/6vJ3tY02+/PJLM3z4cNO4cWNTtWpVExMTYzp37mw++OCDMsf++c9/Nh06dDCRkZEmMjLSNG3a1KSnp5vdu3f7j/nlx8CUmjlzpmnVqpWJiIgwUVFRJiUlxTz22GPm0KFDAce98847pn379v7fadu2bc2bb77p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GQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEALXbw4EENGjRItWrVUkREhFJSUrRlyxanxwIAAJUszOkB4IwffvhBqamp6ty5s959913VqVNHe/bsUc2aNZ0eDQAAVDIC0FKTJk1SQkKCXn/9df+25ORkBycCAADBwilgS73zzjtq3bq17rjjDsXGxuq6667TrFmznB4LAAAEAQFoqS+//FLTp09XkyZNtHLlSv3ud79TRkaG5syZU+7xRUVF8nq9ARcAAHB54hSwpXw+n1q3bq2JEydKkq677jrt2LFDM2bM0NChQ8scn5WVpSeffDLYYwIAgErACqCl6tWrp2uuuSZg29VXX62vvvqq3OPHjRungoIC/yUvLy8YYwIAgErACqClUlNTtXv37oBtX3zxhRo2bFju8W63W263OxijAQCASsYKoKUeeeQRbdy4URMnTtTevXs1f/58zZw5U+np6U6PBgAAKhkBaKk2bdpo6dKlevPNN9W8eXM99dRTmjp1qgYOHOj0aAAAoJJxCthiN998s26++WanxwAAAEHGCiAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEALVVSUqLMzEwlJycrIiJCjRs31lNPPSVjjNOjAQCAShbm9ABwxqRJkzR9+nTNmTNHzZo105YtWzRs2DB5PB5lZGQ4PR4AAKhEBKCl/va3v6l3797q0aOHJCkpKUlvvvmmNm3a5PBkAACgsnEK2FLt27fX6tWr9cUXX0iS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", "text/html": [ - "" + "\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " ], "text/plain": [ - "" + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" ] }, "metadata": {}, @@ -23856,964 +809,241 @@ }, { "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_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", - "\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", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\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", - " fig.rubberband_canvas.style.cursor = msg['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", - " 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", - "\n", - "// from https://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", - " * https://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.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", - "\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\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\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.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", - "\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", + "application/vnd.jupyter.widget-view+json": { + "model_id": "73435e28960b47aea3761c64bb37fc52", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAqk0lEQVR4nO3de3hU9Z3H8c/kwiTEZDCEkAQSElgKCAjWABVQYM3CpoBgldvDrYBSazAglgW6jdhVCIhavCC33QJbQVAWUGirIlfZBblERCxXDRCDEFHIQJAYkt/+YTPtmHAtmQP5vV/Pc/6Yc87MfDManvfzOzMTlzHGCAAAANYIcnoAAAAABBYBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhCAY7Zv36727dsrIiJCLpdLu3btcnokALACAQhUc59++qkGDRqkevXqye12KyEhQQMHDtSnn37q6FwlJSXq06ePvvnmG/3ud7/TH/7wBzVo0MDRmS7l8OHDcrlceu655yo9/txzz8nlcunw4cO+fZ07d5bL5ZLL5VJQUJCioqLUpEkTDR48WGvWrKn0cZKTk333+eF2/vz5qvjRAFgoxOkBAFSd5cuXa8CAAYqOjtaIESOUkpKiw4cP67/+67+0bNkyLVmyRPfff78js3322Wc6cuSI5s2bp4ceesiRGQKhfv36ys7OliQVFRXp0KFDWr58uV577TX17dtXr732mkJDQ/3u07p1az3xxBMVHqtGjRoBmRlA9UcAAtXUZ599psGDB6thw4batGmT6tSp4zs2evRo3X333Ro8eLB2796thg0bBmyuoqIiRUREqKCgQJJUq1atgD23EzwejwYNGuS3b+rUqcrMzNSrr76q5ORkTZs2ze94vXr1KtwHAK4nLgED1dT06dN17tw5zZ071y/+JCkmJkZz5sxRUVGRnn32WUnSsmXL5HK5tHHjxgqPNWfOHLlcLu3Zs8e3b9++fXrwwQcVHR2tsLAwpaam6u233/a734IFC3yP+eijjyo2Nlb169fXz3/+c3Xq1EmS1KdPH7lcLnXu3Nl3v3Xr1unuu+9WRESEatWqpV69emnv3r0V5srPz9eIESOUkJAgt9utlJQU/fKXv9R3330nSXrqqafkcrkq3K98rr+/XLtjxw5169ZNMTExCg8PV0pKioYPH36ZV/naBAcH66WXXtJtt92mV155RYWFhVd833Pnzmnfvn06efLkZc89ePCgHnjgAcXFxSksLEz169dX//79fc9Xfll7wYIFFe7rcrn01FNP+W6Xv5YHDhzQoEGD5PF4VKdOHWVlZckYo7y8PPXq1UtRUVGKi4vT888/f8U/E4DAYwUQqKZWrVql5ORk3X333ZUev+eee5ScnKw//vGPkqTu3bvrlltu0RtvvOGLs3JLly5V8+bN1aJFC0nfv6+wQ4cOqlevniZMmKCIiAi98cYb6t27t/7nf/6nwmXlRx99VHXq1NGTTz6poqIi3XPPPapXr56mTJmizMxMtWnTRnXr1pUkvf/++0pPT1fDhg311FNP6dtvv9XLL7+sDh06KCcnR8nJyZKkY8eOqW3btjp9+rRGjhyppk2bKj8/X8uWLdO5c+eu6nJpQUGBunbtqjp16mjChAmqVauWDh8+rOXLl1/xY1yt4OBgDRgwQFlZWdq8ebO6d+/uO1ZSUlIh8GrWrKmaNWtq27Zt6tKliyZNmuQXaD/03XffqVu3biouLtZjjz2muLg45efna/Xq1Tp9+rQ8Hs81zd2vXz81a9ZMU6dO1R//+Ec988wzio6O1pw5c/TP//zPmjZtmhYtWqRf/epXatOmje65555reh4AVcwAqHZOnz5tJJlevXpd8rz77rvPSDJer9cYY8yAAQNMbGysuXDhgu+cL7/80gQFBZn/+I//8O279957TcuWLc358+d9+8rKykz79u1N48aNffvmz59vJJmOHTv6PaYxxqxfv95IMm+++abf/tatW5vY2Fjz9ddf+/Z9/PHHJigoyAwZMsS3b8iQISYoKMhs3769ws9VVlZmjDFm0qRJprJ/5srnys3NNcYYs2LFCiOp0scql5ubaySZ6dOnV3p8+vTpfo9pjDGdOnUyzZs3v+hjlj/viy++6NvXoEEDI6nCNmnSJGPM31638tsX89FHH1X6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", + "text/html": [ "\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", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%autoreload\n", + "size = 16\n", + "params = OverfocusParams(\n", + " overfocus=0.0001,\n", + " scan_pixel_size=0.00000001,\n", + " camera_length=1,\n", + " detector_pixel_size=0.0001,\n", + " semiconv=np.pi,\n", + " cy=size/2,\n", + " cx=size/2,\n", + " scan_rotation=0,\n", + " flip_y=False\n", + ")\n", + "obj = np.zeros((size, size))\n", + "obj[size//2, size//2] = 1\n", + "sim = project(obj, scan_shape=(size, size), detector_shape=(size, size), sim_params=params)\n", + "assert sim[size//2, size//2, size//2, size//2] == 1\n", + "\n", + "ref_udf = RefOverfocusUDF(params)\n", + "res_udf = OverfocusUDF(params)\n", + "ctx = Context.make_with('inline')\n", + "ds = ctx.load('memory', data=sim)\n", + "\n", + "res = ctx.run_udf(dataset=ds, udf=(ref_udf, res_udf), plots=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "8a47c3a8", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "358daf45005e410ea1a7e88f68a6c072", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAp6klEQVR4nO3df3RNd77/8ddJIkdEchQJEpGEoX7T+lX1s0O5qm5jbjEZKvGjysSgbq3LuqtDZ+6IXtOOmVYV04ZV19DmlqF3jKIVo8MqsYwfg2L8yKCCkhOpHib5fP/oN2d6mohEk2zxeT7W2mv17LPPyTsnWceze++z4zLGGAEAAMAaQU4PAAAAgOpFAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAELHL8+HENGjRIHo9HLpdL69evd3qkctmzZ48effRRhYeHy+Vyaf/+/U6PhDtwuVyaN2+e02MAuA0CELgHrVixQi6Xy7+EhIQoNjZWqampOnfu3F0/b0pKig4ePKhf/OIXeuedd9S1a1f/fYcPH9aYMWMUGxsrt9utmJgYjR49WocPH66Mb+mu3bp1SyNGjNAXX3yhX/3qV3rnnXcUHx/v6ExlOX36tFwul375y1+Wev8vf/lLuVwunT592r+uf//+/p91UFCQIiMj9eCDD+qZZ57Rli1bSn2ehISEgN+Rby5fffVVVXxr1Wb+/Pk15n9OgJoqxOkBANzez372MyUmJuqrr77S7t27tWLFCu3cuVOHDh1S7dq1K/RcN27c0K5du/Sf//mfmjp1asB977//vpKTk1W/fn1NmDBBiYmJOn36tN566y1lZmZqzZo1Gj58eGV+a+V28uRJnTlzRsuXL9fEiRMdmaE6NG3aVOnp6ZKkgoICnThxQu+//75WrVqlkSNHatWqVapVq1bAYzp37qx///d/L/FcoaGh1TJzWW7cuKGQkLv7J2b+/Pl6+umnlZSUVLlDAfAjAIF72JAhQ/x76SZOnKiGDRvq5Zdf1oYNGzRy5MgKPdelS5ckSfXq1QtYf/LkST3zzDNq3ry5duzYoaioKP9906dPV58+ffTMM8/owIEDat68+Xf7hiqgoKBA4eHhys3NLXXu+43H49GYMWMC1i1YsEDTpk3TG2+8oYSEBL388ssB98fGxpZ4zL2iov+DAqB6cQgYqEH69Okj6eto+6ajR4/q6aefVv369VW7dm117dpVGzZs8N8/b948/2HTWbNmyeVyKSEhQZK0cOFCffnll1q2bFlA/ElSw4YNtXTpUhUUFOi///u/JUmZmZlyuVzKysoqMd/SpUvlcrl06NChcs8m/fOQd1ZWln784x8rOjpaTZs2VWpqqvr16ydJGjFihFwul/r37+9/3EcffaQ+ffooPDxc9erV01NPPaUjR46UmOvcuXOaMGGCYmJi5Ha7lZiYqClTpujmzZv+18flcpV4XPFc3zxcu3fvXg0ePFgNGzZUWFiYEhMTNX78+BKPrQzBwcH6zW9+o7Zt2+r1119XXl5euR/75Zdf6ujRo7p8+fIdt+3fv7/at2+v7OxsPfroo/7v68033yyxbW5uriZMmKBGjRqpdu3a6tSpk1auXFliu2+fA1j8Gp84cUKpqamqV6+ePB6Pxo0bpy+//DLgcQUFBVq5cqX/kHZqamq5v28A5cMeQKAGKQ6RBx54wL/u8OHD6tWrl2JjYzV79myFh4fr3XffVVJSkv73f/9Xw4cP1w9+8APVq1dPzz//vJKTk/XEE0+obt26kqSNGzcqISHBH5ff1rdvXyUkJOj//u//JElDhw5V3bp19e677/rjrNjatWvVrl07tW/fvtyzfdOPf/xjRUVF6ac//akKCgrUt29fxcbGav78+Zo2bZq6deumRo0aSZK2bt2qIUOGqHnz5po3b55u3Lih1157Tb169dK+ffv8gXv+/Hl1795d165d06RJk9S6dWudO3dOmZmZ+vLLLyt0uDQ3N1eDBg1SVFSUZs+erXr16un06dN6//33y/0cFRUcHKzk5GS9+OKL2rlzp4YOHeq/79atWyUCr06dOqpTp44+/fRTPfbYY5o7d265Poxx9epVPfHEExo5cqSSk5P17rvvasqUKQoNDfUH7o0bN9S/f3+dOHFCU6dOVWJiot577z2lpqbq2rVrmj59+h2/zsiRI5WYmKj09HTt27dPv/3tbxUdHe3fu/nOO+9o4sSJ6t69uyZNmiRJatGiRXlfLgDlZQDcczIyMowks3XrVnPp0iWTk5NjMjMzTVRUlHG73SYnJ8e/7YABA0yHDh3MV1995V9XVFRkHn30UdOyZUv/ulOnThlJZuHChf51165dM5LMU089VeY8//qv/2okGa/Xa4wxJjk52URHR5t//OMf/m0uXLhggoKCzM9+9rMKz1b8/fbu3TvgOY0x5uOPPzaSzHvvvRewvnPnziY6OtpcuXLFv+4vf/mLCQoKMmPHjvWvGzt2rAkKCjJ79uwp8X0VFRUZY4yZO3euKe3tsHiuU6dOGWOMWbdunZFU6nMVK+11/qaFCxcGPKcxxvTr18+0a9futs9Z/HV//etf+9fFx8cbSSWWuXPnGmP++boV3y5Lv379jCTzyiuv+Nf5fD7/a3zz5k1jjDGLFi0yksyqVav82928edP07NnT1K1b1//7YYwp8bWLX+Px48cHfO3hw4ebBg0aBKwLDw83KSkpd5wbwN3jEDBwDxs4cKCioqIUFxenp59+WuHh4dqwYYOaNm0qSfriiy/00UcfaeTIkcrPz9fly5d1+fJlXblyRYMHD9bx48fL/NRwfn6+JCkiIqLMOYrv93q9kqRRo0YpNzdX27dv92+TmZmpoqIijRo16q5ne/bZZxUcHHzH1+XChQvav3+/UlNTVb9+ff/6jh076vHHH9cf/vAHSVJRUZHWr1+vYcOGBXziuVhph33LUnwe4gcffKBbt25V6LHfRfHe2uKfV7EePXpoy5YtAcvYsWMlfX1Y1xhT7kuxhISE6LnnnvPfDg0N1XPPPafc3FxlZ2dLkv7whz+ocePGSk5O9m9Xq1YtTZs2TdevXy/1tIBvmzx5csDtPn366MqVK/7fLQDVg0PAwD1s8eLFatWqlfLy8vT2229rx44dcrvd/vtPnDghY4xefPFFvfjii6U+R25urmJjY0u9rzjsvh0W3/btUPyXf/kXeTwerV27VgMGDJD09eHfzp07q1WrVnc9W2JiYplzFDtz5owk6cEHHyxxX5s2bbR582YVFBTo+vXr8nq9/kPS31W/fv30b//2b3rppZf0q1/9Sv3791dSUpJ+9KMfBfxcyqMi8Xn9+nVJJUO9YcOGGjhwYIW+7u3ExMQoPDw8YF3xz/L06dN65JFHdObMGbVs2VJBQYH7Dtq0aSPpnz+XsjRr1izgdvHpDFevXlVkZORdzw+gYghA4B7WvXt3/56rpKQk9e7dWz/60Y907Ngx1a1bV0VFRZKkF154QYMHDy71Ob73ve/d9vk9Ho+aNGmiAwcOlDnHgQMHFBsb6/8H2u12KykpSevWrdMbb7yhixcv6pNPPtH8+fP9j7mb2cLCwsqco6rcLsYKCwtLbJeZmandu3dr48aN2rx5s8aPH69XXnlFu3fvVt26df2ffr1x40apz1n8gYeKfEq2+EM1Zf0sa4rb7eE1xlTzJIDdCECghggODlZ6eroee+wxvf7665o9e7b/siy1atW66z1BTz75pJYvX66dO3eqd+/eJe7/05/+pNOnTwccHpS+Pgy8cuVKbdu2TUeOHJExxn/4V1KlzHY7xZ9oPnbsWIn7jh49qoYNGyo8PFxhYWGKjIwM+FRyaYr3Ql27di3gcjO326P1yCOP6JFHHtEvfvELrV69WqNHj9aaNWs0ceJERUVFqU6dOqXOVjxznTp11LBhw/J8qyosLNTq1atVp06dUn8+leX8+fP+S+8U++yzzyTJ/4Ga+Ph4HThwQEVFRQF7AY8ePeq/vzJU9NA8gIrjHECgBunfv7+6d++uRYsW6auvvlJ0dLT69++vpUuX6sKFCyW2L772X1lmzZqlsLAwPffcc7py5UrAfV988YUmT56sOnXqaNasWQH3DRw4UPXr19fatWu1du1ade/ePeAQbmXMdjtNmjRR586dtXLlSl27ds2//tChQ/rwww/1xBNPSJKCgoKUlJSkjRs3au/evSWep3ivU/GnTHfs2OG/r/hSJN909erVEnuqOnfuLEny+XySvg71QYMGaePGjTp79mzAtmfPntXGjRs1aNCgcp3rWFhYqGnTpunIkSOaNm1ahQ6RVuQyMJL0j3/8Q0uXLvXfvnnzppYuXaqoqCh16dJFkvTEE0/o888/19q1awMe99prr6lu3bolPhV+t8LDwwN+rgAqH3sAgRpm1qxZGjFihFasWKHJkydr8eLF6t27tzp06KBnn31WzZs318WLF7Vr1y79/e9/11/+8pcyn69ly5ZauXKlRo8erQ4dOpT4SyCXL1/W7373uxKX4qhVq5Z+8IMfaM2aNSooKCj1T59919nKsnDhQg0ZMkQ9e/bUhAkT/JeB8Xg8AR98mD9/vj788EP169dPkyZNUps2bXThwgW999572rlzp+rVq6dBgwapWbNmmjBhgmbNmqXg4GC9/fbbioqKCoi4lStX6o033tDw4cPVokUL5efna/ny5YqMjPRHZ/HXfOSRR/Twww9r0qRJSkhI0OnTp7Vs2TK5XK6AQ+XF8vLytGrVKklfx1vxXwI5efKkfvjDH+rnP/95hV6fil4GJiYmRi+//LJOnz6tVq1aae3atdq/f7+WLVvm/wskkyZN0tKlS5Wamqrs7GwlJCQoMzNTn3zyiRYtWnTHDxOVV5cuXbR161a9+uqriomJUWJionr06FEpzw3g/3PwE8gAbqP48iOlXW6ksLDQtGjRwrRo0cJ/yZSTJ0+asWPHmsaNG5tatWqZ2NhY8+STT5rMzEz/4+50eZIDBw6Y5ORk06RJE1OrVi3TuHFjk5ycbA4ePHjbObds2WIkGZfLFXBpmm8qz2xlfb+3uwyMMcZs3brV9OrVy4SFhZnIyEgzbNgw89e//rXEdmfOnDFjx471X0anefPmJi0tzfh8Pv822dnZpkePHiY0NNQ0a9bMvPrqqyUuA7Nv3z6TnJxsmjVrZtxut4mOjjZPPvmk2bt3b4mveeTIETNq1CgTHR1tQkJCTHR0tPnhD39ojhw5UmLb4suwFC9169Y1LVu2NGPGjDEffvhhqa9rfHy8GTp0aKn3ffN1K+9lYNq1a2f27t1revbsaWrXrm3i4+PN66+/XmLbixcvmnHjxpmGDRua0NBQ06FDB5ORkVFiu29/7eLLwFy6dClgu2+/xsYYc/ToUdO3b18TFhZmJHFJGKAKuIzhzFsAsFn//v11+fLlO54rCeD+wTmAAAAAliEAAQAALEMAAgAAWIZzAAEAACzDHkAAAADLEIAAAACWIQABAAAsw18CwV0pKirS+fPnFRERwd/tBIAayBij/Px8xcTEBPxtZ9iBAMRdOX/+vOLi4pweAwDwHeXk5Khp06ZOj4FqRgDirhT/zc+cnJwK/YF6AMC9wev1Ki4urtL+hjNqFgIQd6X4sG9kZCQBCAA1GKfx2ImD/gAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAyy1evFgJCQmqXbu2evTooU8//dTpkQAAQBUjAC22du1azZw5U3PnztW+ffvUqVMnDR48WLm5uU6PBgAAqhABaLFXX31Vzz77rMaNG6e2bdvqzTffVJ06dfT22287PRoAAKhCBKClbt68qezsbA0cONC/LigoSAMHDtSuXbscnAwAAFS1EKcHgDMuX76swsJCNWrUKGB9o0aNdPTo0RLb+3w++Xw+/22v11vlMwIAgKrBHkCUS3p6ujwej3+Ji4tzeiQAAHCXCEBLNWzYUMHBwbp48WLA+osXL6px48Yltp8zZ47y8vL8S05OTnWNCgAAKhkBaKnQ0FB16dJF27Zt868rKirStm3b1LNnzxLbu91uRUZGBiwAAKBm4hxAi82cOVMpKSnq2rWrunfvrkWLFqmgoEDjxo1zejQAAFCFCECLjRo1SpcuXdJPf/pTff755+rcubP++Mc/lvhgCAAAuL+4jDHG6SFQ83i9Xnk8HuXl5XE4GABqIN7H7cY5gAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgC01I4dOzRs2DDFxMTI5XJp/fr1To8EAACqCQFoqYKCAnXq1EmLFy92ehQAAFDNQpweAM4YMmSIhgwZ4vQYAADAAewBBAAAsAx7AFEuPp9PPp/Pf9vr9To4DQAA+C7YA4hySU9Pl8fj8S9xcXFOjwQAAO4SAYhymTNnjvLy8vxLTk6O0yMBAIC7xCFglIvb7Zbb7XZ6DAAAUAkIQEtdv35dJ06c8N8+deqU9u/fr/r166tZs2YOTgYAAKoaAWipvXv36rHHHvPfnjlzpiQpJSVFK1ascGgqAABQHQhAS/Xv31/GGKfHAAAADuBDIAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAFoqfT0dHXr1k0RERGKjo5WUlKSjh075vRYAACgGhCAlsrKylJaWpp2796tLVu26NatWxo0aJAKCgqcHg0AAFQxlzHGOD0EnHfp0iVFR0crKytLffv2veP2Xq9XHo9HeXl5ioyMrIYJAQCVifdxu4U4PQDuDXl5eZKk+vXrl3q/z+eTz+fz3/Z6vdUyFwAAqHwcAoaKioo0Y8YM9erVS+3bty91m/T0dHk8Hv8SFxdXzVMCAIDKwiFgaMqUKdq0aZN27typpk2blrpNaXsA4+LiOHQAADUUh4DtxiFgy02dOlUffPCBduzYcdv4kyS32y23212NkwEAgKpCAFrKGKOf/OQnWrdunbZv367ExESnRwIAANWEALRUWlqaVq9erd///veKiIjQ559/LknyeDwKCwtzeDoAAFCVOAfQUi6Xq9T1GRkZSk1NvePjOXcEAGo23sftxh5AS9H9AADYi8vAAAAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAtBSS5YsUceOHRUZGanIyEj17NlTmzZtcnosAABQDQhASzVt2lQLFixQdna29u7dq+9///t66qmndPjwYadHAwAAVcxljDFOD4F7Q/369bVw4UJNmDDhjtt6vV55PB7l5eUpMjKyGqYDAFQm3sftFuL0AHBeYWGh3nvvPRUUFKhnz56lbuPz+eTz+fy3vV5vdY0HAAAqGYeALXbw4EHVrVtXbrdbkydP1rp169S2bdtSt01PT5fH4/EvcXFx1TwtAACoLBwCttjNmzd19uxZ5eXlKTMzU7/97W+VlZVVagSWtgcwLi6OQwcAUENxCNhuBCD8Bg4cqBYtWmjp0qV33JY3DgCo2XgftxuHgOFXVFQUsJcPAADcn/gQiKXmzJmjIUOGqFmzZsrPz9fq1au1fft2bd682enRAABAFSMALZWbm6uxY8fqwoUL8ng86tixozZv3qzHH3/c6dEAAEAVIwAt9dZbbzk9AgAAcAjnAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQWrBggVwul2bMmOH0KAAAoBoQgJbbs2ePli5dqo4dOzo9CgAAqCYEoMWuX7+u0aNHa/ny5XrggQecHgcAAFQTAtBiaWlpGjp0qAYOHOj0KAAAoBqFOD0AnLFmzRrt27dPe/bsKdf2Pp9PPp/Pf9vr9VbVaAAAoIqxB9BCOTk5mj59uv7nf/5HtWvXLtdj0tPT5fF4/EtcXFwVTwkAAKqKyxhjnB4C1Wv9+vUaPny4goOD/esKCwvlcrkUFBQkn88XcJ9U+h7AuLg45eXlKTIystpmBwBUDq/XK4/Hw/u4pTgEbKEBAwbo4MGDAevGjRun1q1b6z/+4z9KxJ8kud1uud3u6hoRAABUIQLQQhEREWrfvn3AuvDwcDVo0KDEegAAcP/hHEAAAADLsAcQkqTt27c7PQIAAKgm7AEEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEoKXmzZsnl8sVsLRu3drpsQAAQDUIcXoAOKddu3baunWr/3ZICL8OAADYgH/xLRYSEqLGjRs7PQYAAKhmHAK22PHjxxUTE6PmzZtr9OjROnv2rNMjAQCAasAeQEv16NFDK1as0IMPPqgLFy7opZdeUp8+fXTo0CFFRESU2N7n88nn8/lve73e6hwXAABUIpcxxjg9BJx37do1xcfH69VXX9WECRNK3D9v3jy99NJLJdbn5eUpMjKyOkYEAFQir9crj8fD+7ilOAQMSVK9evXUqlUrnThxotT758yZo7y8PP+Sk5NTzRMCAIDKQgBCknT9+nWdPHlSTZo0KfV+t9utyMjIgAUAANRMBKClXnjhBWVlZen06dP685//rOHDhys4OFjJyclOjwYAAKoYHwKx1N///nclJyfrypUrioqKUu/evbV7925FRUU5PRoAAKhiBKCl1qxZ4/QIAADAIRwCBgAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBKDFzp07pzFjxqhBgwYKCwtThw4dtHfvXqfHAgAAVSzE6QHgjKtXr6pXr1567LHHtGnTJkVFRen48eN64IEHnB4NAABUMQLQUi+//LLi4uKUkZHhX5eYmOjgRAAAoLpwCNhSGzZsUNeuXTVixAhFR0froYce0vLly50eCwAAVAMC0FJ/+9vftGTJErVs2VKbN2/WlClTNG3aNK1cubLU7X0+n7xeb8ACAABqJpcxxjg9BKpfaGiounbtqj//+c/+ddOmTdOePXu0a9euEtvPmzdPL730Uon1eXl5ioyMrNJZAQCVz+v1yuPx8D5uKfYAWqpJkyZq27ZtwLo2bdro7NmzpW4/Z84c5eXl+ZecnJzqGBMAAFQBPgRiqV69eunYsWMB6z777DPFx8eXur3b7Zbb7a6O0QAAQBVjD6Clnn/+ee3evVvz58/XiRMntHr1ai1btkxpaWlOjwYAAKoYAWipbt26ad26dfrd736n9u3b6+c//7kWLVqk0aNHOz0aAACoYnwIBHeFk4cBoGbjfdxu7AEEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQEslJCTI5XKVWNLS0pweDQAAVLEQpweAM/bs2aPCwkL/7UOHDunxxx/XiBEjHJwKAABUBwLQUlFRUQG3FyxYoBYtWqhfv34OTQQAAKoLAQjdvHlTq1at0syZM+VyuUrdxufzyefz+W97vd7qGg8AAFQyzgGE1q9fr2vXrik1NfW226Snp8vj8fiXuLi46hsQAABUKpcxxjg9BJw1ePBghYaGauPGjbfdprQ9gHFxccrLy1NkZGR1jAkAqERer1cej4f3cUtxCNhyZ86c0datW/X++++XuZ3b7Zbb7a6mqQAAQFXiELDlMjIyFB0draFDhzo9CgAAqCYEoMWKioqUkZGhlJQUhYSwMxgAAFsQgBbbunWrzp49q/Hjxzs9CgAAqEbs9rHYoEGDxGeAAACwD3sAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLhDg9AGomY4wkyev1OjwJAOBuFL9/F7+fwy4EIO5Kfn6+JCkuLs7hSQAA30V+fr48Ho/TY6CauQzpj7tQVFSk8+fPKyIiQi6Xq1Kf2+v1Ki4uTjk5OYqMjKzU565KNXVuqebOztzVq6bOLdXc2atybmOM8vPzFRMTo6AgzgizDXsAcVeCgoLUtGnTKv0akZGRNeqNulhNnVuqubMzd/WqqXNLNXf2qpqbPX/2IvkBAAAsQwACAABYhgDEPcftdmvu3Llyu91Oj1IhNXVuqebOztzVq6bOLdXc2Wvq3Lj38SEQAAAAy7AHEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAHHPWbx4sRISElS7dm316NFDn376qdMj3dGOHTs0bNgwxcTEyOVyaf369U6PdEfp6enq1q2bIiIiFB0draSkJB07dszpscplyZIl6tixo//iuD179tSmTZucHqtCFixYIJfLpRkzZjg9yh3NmzdPLpcrYGndurXTY5XLuXPnNGbMGDVo0EBhYWHq0KGD9u7d6/RYZUpISCjxertcLqWlpTk9Gu4jBCDuKWvXrtXMmTM1d+5c7du3T506ddLgwYOVm5vr9GhlKigoUKdOnbR48WKnRym3rKwspaWlaffu3dqyZYtu3bqlQYMGqaCgwOnR7qhp06ZasGCBsrOztXfvXn3/+9/XU089pcOHDzs9Wrns2bNHS5cuVceOHZ0epdzatWunCxcu+JedO3c6PdIdXb16Vb169VKtWrW0adMm/fWvf9Urr7yiBx54wOnRyrRnz56A13rLli2SpBEjRjg8Ge4nXAYG95QePXqoW7duev311yV9/TeH4+Li9JOf/ESzZ892eLrycblcWrdunZKSkpwepUIuXbqk6OhoZWVlqW/fvk6PU2H169fXwoULNWHCBKdHKdP169f18MMP64033tB//dd/qXPnzlq0aJHTY5Vp3rx5Wr9+vfbv3+/0KBUye/ZsffLJJ/rTn/7k9CjfyYwZM/TBBx/o+PHjlf6312Ev9gDinnHz5k1lZ2dr4MCB/nVBQUEaOHCgdu3a5eBkdsjLy5P0dUjVJIWFhVqzZo0KCgrUs2dPp8e5o7S0NA0dOjTg97wmOH78uGJiYtS8eXONHj1aZ8+edXqkO9qwYYO6du2qESNGKDo6Wg899JCWL1/u9FgVcvPmTa1atUrjx48n/lCpCEDcMy5fvqzCwkI1atQoYH2jRo30+eefOzSVHYqKijRjxgz16tVL7du3d3qccjl48KDq1q0rt9utyZMna926dWrbtq3TY5VpzZo12rdvn9LT050epUJ69OihFStW6I9//KOWLFmiU6dOqU+fPsrPz3d6tDL97W9/05IlS9SyZUtt3rxZU6ZM0bRp07Ry5UqnRyu39evX69q1a0pNTXV6FNxnQpweAIDz0tLSdOjQoRpxXlexBx98UPv371deXp4yMzOVkpKirKysezYCc3JyNH36dG3ZskW1a9d2epwKGTJkiP+/O3bsqB49eig+Pl7vvvvuPX3IvaioSF27dtX8+fMlSQ899JAOHTqkN998UykpKQ5PVz5vvfWWhgwZopiYGKdHwX2GPYC4ZzRs2FDBwcG6ePFiwPqLFy+qcePGDk11/5s6dao++OADffzxx2ratKnT45RbaGiovve976lLly5KT09Xp06d9Otf/9rpsW4rOztbubm5evjhhxUSEqKQkBBlZWXpN7/5jUJCQlRYWOj0iOVWr149tWrVSidOnHB6lDI1adKkxP8QtGnTpkYcvpakM2fOaOvWrZo4caLTo+A+RADinhEaGqouXbpo27Zt/nVFRUXatm1bjTi3q6Yxxmjq1Klat26dPvroIyUmJjo90ndSVFQkn8/n9Bi3NWDAAB08eFD79+/3L127dtXo0aO1f/9+BQcHOz1iuV2/fl0nT55UkyZNnB6lTL169SpxaaPPPvtM8fHxDk1UMRkZGYqOjtbQoUOdHgX3IQ4B454yc+ZMpaSkqGvXrurevbsWLVqkgoICjRs3zunRynT9+vWAvSGnTp3S/v37Vb9+fTVr1szByW4vLS1Nq1ev1u9//3tFRET4z7P0eDwKCwtzeLqyzZkzR0OGDFGzZs2Un5+v1atXa/v27dq8ebPTo91WREREifMrw8PD1aBBg3v+vMsXXnhBw4YNU3x8vM6fP6+5c+cqODhYycnJTo9Wpueff16PPvqo5s+fr5EjR+rTTz/VsmXLtGzZMqdHu6OioiJlZGQoJSVFISH8U40qYIB7zGuvvWaaNWtmQkNDTffu3c3u3budHumOPv74YyOpxJKSkuL0aLdV2rySTEZGhtOj3dH48eNNfHy8CQ0NNVFRUWbAgAHmww8/dHqsCuvXr5+ZPn2602Pc0ahRo0yTJk1MaGioiY2NNaNGjTInTpxweqxy2bhxo2nfvr1xu92mdevWZtmyZU6PVC6bN282ksyxY8ecHgX3Ka4DCAAAYBnOAQQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAs8/8ArEEi55NbWW4AAAAASUVORK5CYII=", + "text/html": [ "\n", - "mpl.figure.prototype._root_extra_style = function (el) {\n", - " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", - "};\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3378b4a2dff248fe93515c6f09969e62", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAtsElEQVR4nO3de1SVdb7H8c8GZIsIeANvICDj/ZLmhQxNTdPDqKPmqJkm3ioLM7OayXVOqc2M2LGapjJvFbpyHDWPonYqvKVm5fE2lpqZWiqjplkJirVV+J0/OuzTjotgwCP93q+19lrtZz9svmxY8u73PPvBZYwxAgAAgDX8nB4AAAAA5YsABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhBwyOHDh9WrVy+FhYXJ5XIpLS3N6ZGKZefOnbr11lsVHBwsl8ulvXv3Oj2SdVwulyZMmHDN/RYuXCiXy6Vjx475bJ81a5YaNmwof39/tWnTpmyG/D/Tpk2Ty+Uq088BoOQIQOAa8n6J5t0CAgJUv359jRo1SidPnrzu501KStK+ffv0l7/8RW+88Ybat2/vfezAgQMaMWKE6tevL7fbrXr16mn48OE6cOBAaXxJ1+3KlSsaPHiwvv32W/31r3/VG2+8oejoaEdnKsqxY8fkcrn07LPPFvj4s88+my+QunXr5v1e+/n5KTQ0VE2aNNE999yj9evXF/g8MTExPj8jP7398MMPZfGlXbd169bpD3/4gxISEpSamqoZM2bo1KlTmjZtGjEPWCTA6QGAiuLpp59WbGysfvjhB23fvl0LFy7Utm3btH//flWuXLlEz/X999/ro48+0r//+7/nW8lZuXKlhg0bpho1amjs2LGKjY3VsWPH9Nprr2nFihVaunSpBg4cWJpfWrEdPXpUx48f14IFCzRu3DhHZigPkZGRSklJkSRlZ2fryJEjWrlypRYvXqwhQ4Zo8eLFqlSpks/HtGnTRo8++mi+5woMDCyXmQtyzz336K677pLb7fZu27Rpk/z8/PTaa695Z9u1a5emT5+umJiYMl8RBHBjIACBYkpMTPSu0o0bN061atXSM888ozVr1mjIkCEleq6vv/5aklStWjWf7UePHtU999yjhg0bauvWrQoPD/c+9vDDD6tLly6655579Mknn6hhw4a/7AsqgezsbAUHB+vs2bMFzv1rExYWphEjRvhsmzlzpiZOnKhXXnlFMTExeuaZZ3wer1+/fr6PcZq/v7/8/f19tp09e1ZBQUGOhikA53EIGLhOXbp0kfRjtP3UZ599pt///veqUaOGKleurPbt22vNmjXex6dNm+Y9bPr444/L5XIpJiZG0o/nZl26dEnz58/3iT9JqlWrlubNm6fs7Gz953/+pyRpxYoVcrlc2rJlS7755s2bJ5fLpf379xd7Nun/D3lv2bJFDz74oCIiIhQZGalRo0apa9eukqTBgwfL5XKpW7du3o/btGmTunTpouDgYFWrVk39+/fXwYMH88118uRJjR07VvXq1ZPb7VZsbKweeOABXb582fv6FHTOWEHns+3atUu9e/dWrVq1FBQUpNjYWI0ZMybfx5YGf39/vfjii2revLlefvllZWZmFvtjL126pM8++0znzp275r6HDx/WoEGDVKdOHVWuXFmRkZG66667Cvx8aWlpatmypdxut1q0aKF3333X5/Gfv2Yul0upqanKzs72HqJeuHChOnToIEkaPXq0z/Y8//M//6N/+7d/U1hYmKpUqaKuXbvqgw8+yDfPtm3b1KFDB1WuXFlxcXGaN29esV+jn/rqq680evRoRUZGyu12q27duurfv7/P997lcmnatGn5PjYmJkajRo3K9xps27ZNEydOVHh4uKpVq6b7779fly9f1vnz5zVy5EhVr15d1atX1x/+8AcZY65rbqAiYQUQuE55v4yqV6/u3XbgwAElJCSofv36euKJJxQcHKzly5drwIAB+q//+i8NHDhQd955p6pVq6ZHHnlEw4YN029/+1tVrVpVkrR27VrFxMR44/LnbrvtNsXExOi///u/JUl9+vRR1apVtXz5cm+c5Vm2bJlatGihli1bFnu2n3rwwQcVHh6up556StnZ2brttttUv359zZgxQxMnTlSHDh1Uu3ZtSdKGDRuUmJiohg0batq0afr+++/10ksvKSEhQXv27PEG7qlTp9SxY0edP39e9913n5o2baqTJ09qxYoVunTpUolWpc6ePatevXopPDxcTzzxhKpVq6Zjx45p5cqVxX6OkvL399ewYcP05JNPatu2berTp4/3sStXruQLvCpVqqhKlSrasWOHunfvrqlTpxYYLXkuX76s3r17y+Px6KGHHlKdOnV08uRJvfXWWzp//rzCwsK8+27btk0rV67Ugw8+qJCQEL344osaNGiQTpw4oZo1axb4/G+88Ybmz5+vHTt26NVXX5UkNWrUSE8//bSeeuop3Xfffd6fvVtvvVXSj2GfmJiodu3aaerUqfLz81Nqaqpuv/12vf/+++rYsaMkad++fd7vx7Rp03T16lVNnTrV+zNSEoMGDdKBAwf00EMPKSYmRmfPntX69et14sQJ789SSeW9ntOnT9f27ds1f/58VatWTR9++KEaNGigGTNm6O2339asWbPUsmVLjRw58ro+D1BhGABFSk1NNZLMhg0bzNdff20yMjLMihUrTHh4uHG73SYjI8O7b48ePUyrVq3MDz/84N2Wm5trbr31VtOoUSPvti+//NJIMrNmzfJuO3/+vJFk+vfvX+Q8v/vd74wkk5WVZYwxZtiwYSYiIsJcvXrVu8/p06eNn5+fefrpp0s8W97X27lzZ5/nNMaY9957z0gyb775ps/2Nm3amIiICPPNN994t3388cfGz8/PjBw50rtt5MiRxs/Pz+zcuTPf15Wbm2uMMWbq1KmmoH+a8ub68ssvjTHGrFq1ykgq8LnyFPQ6/9SsWbN8ntMYY7p27WpatGhR6HPmfd6//e1v3m3R0dFGUr7b1KlTjTH//7rl3S/MP//5zwJf35+TZAIDA82RI0e82z7++GMjybz00kvebT9/zYwxJikpyQQHB/s8386dO40kk5qa6rM9NzfXNGrUyPTu3dv7/THGmEuXLpnY2Fhzxx13eLcNGDDAVK5c2Rw/fty77dNPPzX+/v4Ffj8L89133xX5PctT2OsZHR1tkpKSvPfzXoOffw2dOnUyLpfLjB8/3rvt6tWrJjIy0nTt2rXY8wIVFYeAgWLq2bOnwsPDFRUVpd///vcKDg7WmjVrFBkZKUn69ttvtWnTJg0ZMkQXLlzQuXPndO7cOX3zzTfq3bu3Dh8+XOS7hi9cuCBJCgkJKXKOvMezsrIkSUOHDtXZs2e1efNm7z4rVqxQbm6uhg4det2z3XvvvfnOHyvI6dOntXfvXo0aNUo1atTwbm/durXuuOMOvf3225Kk3NxcpaWlqV+/fj7veM5T0kuF5J2H+NZbb+nKlSsl+thfIm+1Nu/7lSc+Pl7r16/3ueWtInXr1k3GmCJX/yR5V/jS09N16dKlIvft2bOn4uLivPdbt26t0NBQffHFFyX9kgq1d+9eHT58WHfffbe++eYb789Ndna2evTooa1btyo3N1c5OTlKT0/XgAED1KBBA+/HN2vWTL179y7R58w7P3Hz5s367rvvSu1rGTt2rM/PWHx8vIwxGjt2rHebv7+/2rdvX6qvIXCj4hAwUEyzZ89W48aNlZmZqddff11bt271eXflkSNHZIzRk08+qSeffLLA5zh79qzq169f4GN5YffzsPi5n4di3rlZy5YtU48ePST9ePi3TZs2aty48XXPFhsbW+QceY4fPy5JatKkSb7HmjVrpvT0dGVnZ+vixYvKysryHpL+pbp27apBgwZp+vTp+utf/6pu3bppwIABuvvuu32+L8VRkvi8ePGipPyhXqtWLfXs2bNEn/fnYmNjNXnyZD3//PP6+9//ri5duuh3v/udRowY4XP4V5JPaOWpXr16qUbT4cOHJf14yaLCZGZmyuPx6Pvvv1ejRo3yPd6kSRPv/wQUh9vt1jPPPKNHH31UtWvX1i233KK+fftq5MiRqlOnTsm/iP/z89cr7/WMiorKt700X0PgRkUAAsXUsWNH78rVgAED1LlzZ9199906dOiQqlatqtzcXEnSY489Vuiqx29+85tCnz8sLEx169bVJ598UuQcn3zyierXr6/Q0FBJP/7CHDBggFatWqVXXnlFZ86c0QcffKAZM2Z4P+Z6ZgsKCipyjrJSWIzl5OTk22/FihXavn271q5dq/T0dI0ZM0bPPfectm/frqpVq3ovz/P9998X+Jx5q2wluYxP3ptqivpe/hLPPfecRo0apdWrV2vdunWaOHGiUlJStH37du9qs6RCV2dNKb6BIe/nZtasWYVeHqZq1aryeDyl9jkladKkSerXr5/S0tKUnp6uJ598UikpKdq0aZPatm1b5Mf+/OckT2GvV0HbS/M1BG5UBCBwHfz9/ZWSkqLu3bvr5Zdf1hNPPOG9LEulSpWueyWob9++WrBg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", + "text/html": [ "\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", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0b97dc1c12864d3aab4eb1bc9c4192be", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAsyUlEQVR4nO3de3RNd/7/8ddJwhGRhFTilghSqiVoBSWUlvI1KL2gQcWt1Taaqm/NlzXfDmZa0a9pqxdVfFusqrpNKZ3RFC2qU6su1YpRDXVJUZe2TiL0IOfz+6O/nG9PExEq2fTzfKy115qz9z7nvHNZ+py999lxGWOMAAAAYI0gpwcAAABA+SIAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAALXoOzsbHXt2lWRkZFyuVxavny50yOVyubNm9WuXTuFhYXJ5XJp+/btTo+ECxgyZIjq1avn9BiXxeVyaeLEiU6PAVzVCECgDM2dO1cul8u/hISEqE6dOhoyZIgOHTp02a+bmpqqHTt26JlnntGbb76ppKQk/7adO3dq0KBBqlOnjtxut2rXrq2BAwdq586dV+JLumznzp1T37599cMPP+iFF17Qm2++qfj4eEdnKsn+/fvlcrn0t7/9rdjtf/vb3+RyubR//37/uk6dOvl/1kFBQYqIiNANN9ygBx54QKtXry72derVqxfwO/LL5aeffiqLL+2qsGDBAk2bNs3pMQBrhTg9AGCDv/zlL6pfv75++uknbdq0SXPnztXGjRuVlZWlSpUqXdJrnTlzRp9++qn+9Kc/adSoUQHb3nnnHaWkpCgqKkrDhw9X/fr1tX//fr3++utaunSpFi5cqLvvvvtKfmmltnfvXh04cECzZ8/WiBEjHJmhPMTGxiojI0OSlJ+frz179uidd97R/Pnz1a9fP82fP18VKlQIeE6LFi30n//5n0Veq2LFiuUysxMWLFigrKwsjR492ulRACsRgEA56N69u/8o3YgRI1S9enU9++yzWrFihfr163dJr3X8+HFJUtWqVQPW7927Vw888IAaNGigDRs2KDo62r/t8ccfV4cOHfTAAw/oyy+/VIMGDX7bF3QJ8vPzFRYWpmPHjhU79+9NZGSkBg0aFLBuypQpSk9P16uvvqp69erp2WefDdhep06dIs8BgLLEKWDAAR06dJD0c7T90ldffaX77rtPUVFRqlSpkpKSkrRixQr/9okTJ/pPm44dO1Yul8t/ndbUqVN1+vRpzZo1KyD+JKl69eqaOXOm8vPz9T//8z+SpKVLl8rlcmn9+vVF5ps5c6ZcLpeysrJKPZv0f6e8169fr0cffVQxMTGKjY3VkCFD1LFjR0lS37595XK51KlTJ//zPvzwQ3Xo0EFhYWGqWrWqevfurV27dhWZ69ChQxo+fLhq164tt9ut+vXr65FHHtHZs2f93x+Xy1XkeYVz/fJ07ZYtW9StWzdVr15doaGhql+/voYNG1bkuVdCcHCwXnrpJd1000165ZVX5PF4Sv3c06dP66uvvtKJEycuum92drbuvfde1axZU5UqVVJsbKzuv//+Iu83f/58tWzZUqGhoYqKitL999+vnJyci76+z+fTtGnT1KRJE1WqVEk1atTQyJEj9eOPPxbZd9WqVerYsaPCw8MVERGhVq1aacGCBZJ+PlX+j3/8QwcOHPCf7v7l9YZer1cTJkzQ9ddfL7fbrbi4OP3xj3+U1+sNeA+v16snnnhC0dHRCg8P11133aVvv/32ol8HAI4AAo4oDJFq1ar51+3cuVPJycmqU6eOxo0bp7CwMC1evFh9+vTR3//+d91999265557VLVqVT3xxBNKSUnRH/7wB1WpUkWStHLlStWrV88fl7922223qV69evrHP/4hSerRo4eqVKmixYsX++Os0KJFi9SkSRM1bdq01LP90qOPPqro6Gj9+c9/Vn5+vm677TbVqVNHkydPVnp6ulq1aqUaNWpIktasWaPu3burQYMGmjhxos6cOaOXX35ZycnJ2rZtmz8MDh8+rNatW+vkyZN66KGH1LhxYx06dEhLly7V6dOnL+l06bFjx9S1a1dFR0dr3Lhxqlq1qvbv36933nmn1K9xqYKDg5WSkqKnnnpKGzduVI8ePfzbzp07VyTwKleurMqVK+uzzz7T7bffrgkTJpT4wYazZ8+qW7du8nq9euyxx1SzZk0dOnRI7733nk6ePKnIyEhJ0jPPPKOnnnpK/fr104gRI3T8+HG9/PLLuu222/T555+XeIR25MiRmjt3roYOHar09HTt27dPr7zyij7//HN98skn/lPbc+fO1bBhw9SkSRONHz9eVatW1eeff673339fAwYM0J/+9Cd5PB59++23euGFFyTJ/3vs8/l01113aePGjXrooYd04403aseOHXrhhRf09ddfB3zgacSIEZo/f74GDBigdu3a6cMPPwz4vgIogQFQZubMmWMkmTVr1pjjx4+bnJwcs3TpUhMdHW3cbrfJycnx79u5c2eTmJhofvrpJ/86n89n2rVrZxo2bOhft2/fPiPJTJ061b/u5MmTRpLp3bt3ifPcddddRpLJzc01xhiTkpJiYmJizPnz5/37HDlyxAQFBZm//OUvlzxb4dfbvn37gNc0xpiPPvrISDJLliwJWN+iRQsTExNjvv/+e/+6L774wgQFBZnBgwf71w0ePNgEBQWZzZs3F/m6fD6fMcaYCRMmmOL+WSuca9++fcYYY5YtW2YkFftahYr7Pv/S1KlTA17TGGM6duxomjRpcsHXLHzfF1980b8uPj7eSCqyTJgwwRjzf9+3wscX8vnnnxf7/f2l/fv3m+DgYPPMM88ErN+xY4cJCQkJWJ+ammri4+P9jz/++GMjybz11lsBz33//fcD1p88edKEh4ebNm3amDNnzgTsW/hzMsaYHj16BLx+oTfffNMEBQWZjz/+OGD9a6+9ZiSZTz75xBhjzPbt240k8+ijjwbsN2DAgFJ9vwDbcQoYKAddunRRdHS04uLidN999yksLEwrVqxQbGysJOmHH37Qhx9+qH79+ikvL08nTpzQiRMn9P3336tbt27Kzs4u8VPDeXl5kqTw8PAS5yjcnpubK0nq37+/jh07pnXr1vn3Wbp0qXw+n/r373/Zsz344IMKDg6+6PflyJEj2r59u4YMGaKoqCj/+mbNmunOO+/UP//5T0k/HxVavny5evXqFfCJ50LFnfYtSeFRrvfee0/nzp27pOf+FoVHuQp/XoXatGmj1atXByyDBw+W9PPpUmPMRW9rUniELzMzU6dPny52n3feeUc+n0/9+vXz/xxPnDihmjVrqmHDhvroo48u+PpLlixRZGSk7rzzzoDntmzZ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", + "text/html": [ "\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", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/weber/LiberTEM/LiberTEM/src/libertem/viz/mpl.py:92: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`.\n", + " self.fig, self.axes = plt.subplots()\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "730e60043dbb4f3ea0a72122ef89036d", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAApQklEQVR4nO3df3RU9Z3/8dckgSFAMhiTACGBBIr8kF9qADH81AgbgQVqAbMgQUCrDSKychbOrgVbS3CpXdoKCNQCR0pBs4JAq/xSoLRy5MdSgSIC8iMF5IdCEoIOkNzvH/1m6pgQEkxyie/n45x7jnPnzuQ9gweffu6dicdxHEcAAAAwI8TtAQAAAFC9CEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEAAAABjCEDAqEOHDqlv377y+XzyeDxatWqV2yOVy44dO3TfffepXr168ng82rNnj9sjAUCNQwACt7jFixfL4/EEtrCwMDVp0kSjR4/WyZMnb/p5MzIytHfvXv3sZz/T66+/ruTk5MB9+/fv18iRI9WkSRN5vV7FxcVpxIgR2r9/f2W8pJt29epVDR06VF988YX+53/+R6+//rqaNWvm6kxlOXbsmDwej37+85+Xev/Pf/5zeTweHTt2LLCvd+/egT/rkJAQRUZGqlWrVnr00Ue1YcOGUp8nMTEx6N+Rr29fffVVVbw0ADVcmNsDACifn/zkJ0pKStJXX32l7du3a/Hixdq2bZv27dunOnXqVOi5vvzyS33wwQf6z//8T40fPz7ovrfeekvp6emKiorS2LFjlZSUpGPHjum1115Tdna2li9friFDhlTmSyu3I0eO6Pjx41q4cKHGjRvnygzVIT4+XllZWZKkgoICHT58WG+99ZaWLl2qYcOGaenSpapVq1bQYzp16qR///d/L/FctWvXrpaZAdQsBCBQQ6SlpQVW6caNG6fo6Gi99NJLWr16tYYNG1ah5zp37pwkqUGDBkH7jxw5okcffVTNmzfX1q1bFRMTE7jvmWeeUY8ePfToo4/qo48+UvPmzb/dC6qAgoIC1atXT2fPni117u8an8+nkSNHBu2bOXOmJkyYoLlz5yoxMVEvvfRS0P1NmjQp8RgAuB5OAQM1VI8ePST9I9q+7uOPP9YPfvADRUVFqU6dOkpOTtbq1asD90+fPj1w2nTy5MnyeDxKTEyUJM2aNUuXL1/WggULguJPkqKjozV//nwVFBTov//7vyVJ2dnZ8ng82rJlS4n55s+fL4/Ho3379pV7Numfp7y3bNmiH/3oR4qNjVV8fLxGjx6tXr16SZKGDh0qj8ej3r17Bx733nvvqUePHqpXr54aNGigQYMG6cCBAyXmOnnypMaOHau4uDh5vV4lJSXpqaee0pUrVwLvj8fjKfG44rm+frp2586d6tevn6KjoxUeHq6kpCSNGTOmxGMrQ2hoqH71q1+pbdu2euWVV5Sbm1vux16+fFkff/yxzp8/f8NjDx06pIcffliNGjVSnTp1FB8fr0ceeSTw84pPay9evLjEYz0ej6ZPnx64XfxefvLJJxo5cqR8Pp9iYmL0/PPPy3Ec5eTkaNCgQYqMjFSjRo308ssvl/s1Afh2WAEEaqjiELntttsC+/bv36+UlBQ1adJEU6ZMUb169fTGG29o8ODB+t///V8NGTJE3//+99WgQQM9++yzSk9P10MPPaT69etLktasWaPExMRAXH5Tz549lZiYqD/84Q+SpP79+6t+/fp64403AnFWbMWKFbrzzjvVrl27cs/2dT/60Y8UExOjH//4xyooKFDPnj3VpEkTzZgxQxMmTFDnzp3VsGFDSdLGjRuVlpam5s2ba/r06fryyy/161//WikpKdq9e3cgcE+dOqUuXbro4sWLeuKJJ9S6dWudPHlS2dnZunz5coVOl549e1Z9+/ZVTEyMpkyZogYNGujYsWN66623yv0cFRUaGqr09HQ9//zz2rZtm/r37x+47+rVqyUCr27duqpbt64+/PBD9enTR9OmTQsKtG+6cuWK+vXrJ7/fr6efflqNGjXSyZMntXbtWl28eFE+n++m5h4+fLjatGmjmTNn6g9/+INefPFFRUVFaf78+br//vv10ksv6Xe/+52ee+45de7cWT179rypnwOgAhwAt7RFixY5kpyNGzc6586dc3Jycpzs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sGFDffzxxyWO9/v98vv9gdt5eXlVPiMAAKgarACiXLKysuTz+QJbQkKC2yMBAICbRAAaFR0drdDQUJ05cyZo/5kzZ9SoUaMSx0+dOlW5ubmBLScnp7pGBQAAlYwANKp27dq65557tGnTpsC+oqIibdq0Sd26dStxvNfrVWRkZNAGAABqJq4BNGzSpEnKyMhQcnKyunTpotmzZ6ugoECPPfaY26MBAIAqRAAaNnz4cJ07d04//vGP9dlnn6lTp0569913S3wwBAAAfLd4HMdx3B4CNU9eXp58Pp96a5DCPLXcHgcAUEHXnKvarLeVm5vLZT0GcQ0gAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQQgAACAMQSgUVu3btXAgQMVFxcnj8ejVatWuT0SAACoJgSgUQUFBerYsaPmzJnj9igAAKCahbk9ANyRlpamtLQ0t8cAAAAuYAUQAADAGFYAUS5+v19+vz9wOy8vz8VpAADAt8EKIMolKytLPp8vsCUkJLg9EgAAuEkEIMpl6tSpys3NDWw5OTlujwQAAG4Sp4BRLl6vV16v1+0xAABAJSAAjbp06ZIOHz4cuH306FHt2bNHUVFRatq0qYuTAQCAqkYAGrVz50716dMncHvSpEmSpIyMDC1evNilqQAAQHUgAI3q3bu3HMdxewwAAOACPgQCAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAEIAABgDAFoVFZWljp37qyIiAjFxsZq8ODBOnjwoNtjAQCAakAAGrVlyxZlZmZq+/bt2rBhg65evaq+ffuqoKDA7dEAAEAVC3N7ALjj3XffDbq9ePFixcbGateuXerZs6dLUwEAgOpAAEKSlJubK0mKiooq9X6/3y+/3x+4nZeXVy1zAQCAyscpYKioqEgTJ05USkqK2rVrV+oxWVlZ8vl8gS0hIaGapwQAAJWFAIQyMzO1b98+LV++/LrHTJ06Vbm5uYEtJyenGicEAACViVPAxo0fP15r167V1q1bFR8ff93jvF6vvF5vNU4GAACqCgFolOM4evrpp7Vy5Upt3rxZSUlJbo8EAACqCQFoVGZmppYtW6a3335bERER+uyzzyRJPp9P4eHhLk8HAACqEtcAGjVv3jzl5uaqd+/eaty4cWBbsWKF26MBAIAqxgqgUY7juD0CAABwCSuAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCAAAAAxhCARs2bN08dOnRQZGSkIiMj1a1bN73zzjtujwUAAKoBAWhUfHy8Zs6cqV27dmnnzp26//77NWjQIO3fv9/t0QAAQBXzOI7juD0Ebg1RUVGaNWuWxo4de8Nj8/Ly5PP51FuDFOapVQ3TAQAq0zXnqjbrbeXm5ioyMtLtcVDNwtweAO4rLCzUm2++qYKCAnXr1q3UY/x+v/x+f+B2Xl5edY0HAAAqGaeADdu7d6/q168vr9erJ598UitXrlTbtm1LPTYrK0s+ny+wJSQkVPO0AACgsnAK2LArV67oxIkTys3NVXZ2tn7zm99oy5YtpUZgaSuACQkJnAIGgBqKU8C2EYAISE1NVYsWLTR//vwbHss1gABQsxGAtnEKGAFFRUVBq3wAAOC7iQ+BGDV16lSlpaWpadOmys/P17Jly7R582atW7fO7dEAAEAVIwCNOnv2rEaNGqXTp0/L5/OpQ4cOWrdunR588EG3RwMAAFWMADTqtddec3sEAADgEq4BBAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYABAAAMIYAhGbOnCmPx6OJEye6PQoAAKgGBKBxO3bs0Pz589WhQwe3RwEAANWEADTs0qVLGjFihBYuXKjbbrvN7XEAAEA1IQANy8zMVP/+/ZWamur2KAAAoBqFuT0A3LF8+XLt3r1bO3bsKNfxfr9ffr8/cDsvL6+qRgMAAFWMFUCDcnJy9Mwzz+h3v/ud6tSpU67HZGVlyefzBbaEhIQqnhIAAFQVj+M4jttDoHqtWrVKQ4YMUWhoaGBfYWGhPB6PQkJC5Pf7g+6TSl8BTEhIUG8NUpinVrXNDgCoHNecq9qst5Wbm6vIyEi3x0E14xSwQQ888ID27t0btO+xxx5T69at9R//8R8l4k+SvF6vvF5vdY0IAACqEAFoUEREhNq1axe0r169err99ttL7AcAAN89XAMIAABgDCuAkCRt3rzZ7REAAEA1YQUQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGALQqOnTp8vj8QRtrVu3dnssAABQDcLcHgDuufPOO7Vx48bA7bAw/nUAAMAC/otvWFhYmBo1auT2GAAAoJpxCtiwQ4cOKS4uTs2bN9eIESN04sQJt0cCAADVgBVAo7p27arFixerVatWOn36tF544QX16NFD+/btU0RERInj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", + "text/html": [ "\n", - "mpl.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", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1fb3d687dec541f19d8ac793ce271d55", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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7eDBg2rWrJni4uKUmJiohISECp9Krkr5UahLly5VWH+1I1rf/va39R//8R/Kz8/Xr3/9ax04cECrVq2SJCUmJqphw4ZVzlY+c8OGDdWsWbNrzlSutLRUK1euVMOGDXX//fdX6z434/Tp0youLq6w7pNPPpGk8AdqUlNTdfjw4XDclzt48GB4e0240VPzACKHAARuE88884waNGigJ554QhcvXqyw7bPPPtOTTz6phg0b6plnnqmwbdCgQWrSpIlWr16t1atXq1evXhVO4SYlJWngwIFasmSJzpw5U+l5z58/f9Mzt2zZUt27d9fy5csrRNv+/fv1zjvv6OGHH5YkRUVFaeTIkdqwYYPy8/MrPU75UafyT5lu3749vK38q0j+v88//7zSkaru3btLUvg0cHR0tAYPHqwNGzbo5MmTFfY9efKkNmzYoMGDB1frWsfS0lJNnz5dH3/8saZPnx4+AlsdN/I1MJL01VdfacmSJeHbJSUlWrJkiRITE9WjRw9J0sMPP6xPP/20wqn/r776Si+99JIaNWpU6VPhNysuLq5SjAO4NXAKGLhNtGvXTsuXL9e4cePUpUuXSr8EcuHCBf3mN7+p9FUc9erV0z/90z9p1apVKi4urvKnzxYtWqT7779fXbp00eOPP662bdvq7Nmz+uCDD/TXv/5Vf/rTn2567gULFmjo0KHq06ePpkyZEv4amEAgUOGDD/PmzdM777yjAQMGaOrUqerQoYPOnDmjNWvWaMeOHWrcuLEGDx6sNm3aaMqUKXrmmWcUHR2tX/7yl0pMTKwQccuXL9crr7yiUaNG6c4771RRUZGWLVumhISEcHSWP+e3v/1t3XvvvZo6darS0tJ0/PhxLV26VD6fr8Kp8nKFhYVasWKFpL/HW/kvgRw9elTf+9739JOf/OSGXp8b/RqY5ORkPf/88zp+/LjuuusurV69Wnv37tXSpUvDv0AydepULVmyRBMnTtTu3buVlpamtWvX6v3339fChQtv+oju1/Xo0UNbtmzRiy++qOTkZKWnp6t379418tgAviEvP4IMoOZ99NFHLjMz07Vs2dLVq1fPtWjRwmVmZrp9+/Zd9T6bN292kpzP53MFBQVV7nP06FE3YcIE16JFC1evXj3XqlUr98gjj7i1a9eG9yn/upWqvl7lal8D45xzW7ZscX379nUNGjRwCQkJbvjw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Wz179tTLL78s6e+/OZySkqIf/OAHevbZZz2ernp8Pp/WrVunkSNHej3KDTl//rySkpKUl5en/v37ez3ODWvSpIkWLFigKVOmeD3KNV2+fFn33nuvXnnlFf37v/+7unfvroULF3o91jXNnTtX69ev1969e70e5YY8++yzev/99/WHP/zB61G+kZkzZ+rtt9/W4cOHa/y312EXRwBxyygpKdHu3bs1aNCg8LqoqCgNGjRIH3zwgYeT2VBYWCjp7yFVl5SWlmrVqlUqLi5Wnz59vB7nurKzszVs2LAKf8/rgsOHDys5OVlt27bVuHHjdPLkSa9Huq633npLGRkZGj16tJKSknTPPfdo2bJlXo91Q0pKSrRixQpNnjyZ+EONIgBxy7hw4YJKS0vVvHnzCuubN2+uTz/91KOpbCgrK9PMmTPVt29fde7c2etxqmXfvn1q1KiR/H6/nnzySa1bt04dO3b0eqxrWrVqlfbs2aOcnByvR7khvXv31uuvv67f//73Wrx4sY4dO6Z+/fqpqKjI69Gu6S9/+YsWL16sdu3aadOmTZo2bZqmT5+u5cuXez1ata1fv16XLl3SxIkTvR4Ft5kYrwcA4L3s7Gzt37+/TlzXVe7uu+/W3r17VVhYqLVr1yorK0t5eXm3bAQWFBRoxowZ2rx5s+rXr+/1ODdk6NCh4f/dtWtX9e7dW6mpqXrjjTdu6VPuZWVlysjI0Lx58yRJ99xzj/bv369XX31VWVlZHk9XPa+99pqGDh2q5ORkr0fBbYYjgLhlNGvWTNHR0Tp79myF9WfPnlWLFi08mur299RTT+ntt9/We++9p9atW3s9TrXFxsbqW9/6lnr06KGcnBx169ZNP/vZz7we66p2796tc+fO6d5771VMTIxiYmKUl5enn//854qJiVFpaanXI1Zb48aNddddd+nIkSNej3JNLVu2rPR/CDp06FAnTl9L0okTJ7RlyxY99thjXo+C2xABiFtGbGysevTooa1bt4bXlZWVaevWrXXi2q66xjmnp556SuvWrdO7776r9PR0r0f6RsrKyhQKhbwe46oefPBB7du3T3v37g0vGRkZGjdunPbu3avo6GivR6y2y5cv6+jRo2rZsqXXo1xT3759K3210SeffKLU1FSPJroxubm5SkpK0rBhw7weBbchTgHjljJr1ixlZWUpIyNDvXr10sKFC1VcXKxJkyZ5Pdo1Xb58ucLRkGPHjmnv3r1q0qSJ2rRp4+FkV5edna2VK1fqt7/9reLj48PXWQYCATVo0MDj6a5t9uzZGjp0qNq0aaOioiKtXLlS27Zt06ZNm7we7ari4+MrXV8ZFxenpk2b3vLXXT799NMaPny4UlNTdfr0ac2ZM0fR0dHKzMz0erRr+uEPf6j77rtP8+bN05gxY/Thhx9q6dKlWrp0qdejXVdZWZlyc3OVlZWlmBj+qUYtcMAt5qWXXnJt2rRxsbGxrlevXm7nzp1ej3Rd7733npNUacnKyvJ6tKuqal5JLjc31+vRrmvy5MkuNTXVxcbGusTERPfggw+6d955x+uxbtiAAQPcjBkzvB7jusaOHetatmzpYmNjXatWrdzYsWPdkSNHvB6rWjZs2OA6d+7s/H6/a9++vVu6dKnXI1XLpk2bnCR36NAhr0fBbYrvAQQAADCGawABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACM+V9+RKoIqzg7fAAAAABJRU5ErkJggg==", + "text/html": [ "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " fig.ondownload(fig, null);\n", - "};\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c80bb2b9aa174699933167938e73097e", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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", + "text/html": [ "\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", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ec1c8eb3a3874591b9b0d1c7e4e9ac29", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAArSElEQVR4nO3de3xNd77/8fdOwhaRhJC4JRJU604rpITSUo5B6XTQoO6ttmlTddo5PM7p4EwrekxLL+6ng0c1dRu0zLhfq1OPujStdFDUJUWptnYizEb29/dHf9lndhOEShb9vp6Px3o8utdae+1PEg9eXWvtHZcxxggAAADWCHJ6AAAAAJQuAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQgAACAZQhAAAAAyxCAAAAAliEAAQAALEMAAgAAWIYABAAAsAwBCAAAYBkCEAAAwDIEIAAAgGUIQAAAAMsQgAAAAJYhAAEAACxDAAIAAFiGAAQAALAMAQgAAGAZAhAAAMAyBCAAAIBlCEAAAADLEIAAAACWIQABAAAsQwACAABYhgAEAACwDAEIAABgGQIQAADAMgQggOu2Y8cOtWnTRmFhYXK5XMrMzHR6JFzB4MGDlZCQ4PQYN8TlcmncuHFOjwH8KhGAwC3qyy+/1IABA1SzZk253W7VqFFD/fv315dffunoXJcuXVLv3r31ww8/aPLkyXr33XcVHx/v6ExXc+TIEblcLv3pT38qcvuf/vQnuVwuHTlyxL+uQ4cOcrlccrlcCgoKUkREhO666y499thjWrduXZHHSUhI8D/n58s///nPkvjSbgkZGRmaMmWK02MAuE4hTg8AoLClS5cqJSVFUVFRGjZsmGrXrq0jR47onXfe0ZIlS7RgwQI9/PDDjsx26NAhHT16VLNnz9bw4cMdmaE0xMbGKj09XZKUl5engwcPaunSpZo/f7769Omj+fPnq0yZMgHPad68uf793/+90LHKli1bKjM7ISMjQ1lZWRo5cqTTowC4DgQgcIs5dOiQHnvsMdWpU0dbt25VdHS0f9tzzz2ndu3a6bHHHtMXX3yhOnXqlNpceXl5CgsL0+nTpyVJFStWLLXXdkJkZKQGDBgQsG7ixIlKS0vTtGnTlJCQoFdffTVge82aNQs9BwBuRVwCBm4xkyZN0vnz5zVr1qyA+JOkKlWqaObMmcrLy9P//M//SJKWLFkil8ulLVu2FDrWzJkz5XK5lJWV5V+3b98+/e53v1NUVJTKlSunxMREffjhhwHPmzt3rv+YTz/9tGJiYhQbG6vBgwerffv2kqTevXvL5XKpQ4cO/udt3LhR7dq1U1hYmCpWrKiePXtq7969heY6fvy4hg0bpho1asjtdqt27dp66qmndPHiRUnSuHHj5HK5Cj2vYK5/vVy7c+dOdenSRVWqVFFoaKhq166toUOHXuO7fGOCg4P15ptvqmHDhnr77bfl8XiK/dzz589r3759OnPmzDX3PXDggB555BFVq1ZN5cqVU2xsrB599NFCrzd//ny1aNFCoaGhioqK0qOPPqrs7OxrHt/n82nKlClq1KiRypUrp6pVq2rEiBH68ccfC+27atUqtW/fXuHh4YqIiFDLli2VkZEh6adL5X/961919OhR/+Xuf73f0Ov1auzYsbrjjjvkdrsVFxen3//+9/J6vQGv4fV69fzzzys6Olrh4eF66KGH9M0331zz6wBw4zgDCNxiVqxYoYSEBLVr167I7ffdd58SEhL017/+VZLUrVs3VahQQYsWLfLHWYGFCxeqUaNGaty4saSf7itMTk5WzZo1NXr0aIWFhWnRokXq1auX/vKXvxS6rPz0008rOjpaf/jDH5SXl6f77rtPNWvW1IQJE5SWlqaWLVuqatWqkqT169era9euqlOnjsaNG6cLFy7orbfeUnJysnbv3u0PgxMnTqhVq1Y6e/asnnjiCdWvX1/Hjx/XkiVLdP78+eu6XHr69Gl17txZ0dHRGj16tCpWrKgjR45o6dKlxT7G9QoODlZKSopeeuklbdu2Td26dfNvu3TpUqHAK1++vMqXL69PP/1U999/v8aOHXvVNzZcvHhRXbp0kdfr1bPPPqtq1arp+PHjWrlypc6ePavIyEhJ0iuvvKKXXnpJffr00fDhw/Xdd9/prbfe0n333afPPvvsqmdoR4wYoblz52rIkCFKS0vT4cOH9fbbb+uzzz7Txx9/7L+0PXfuXA0dOlSNGjXSmDFjVLFiRX322WdavXq1+vXrp//8z/+Ux+PRN998o8mTJ0uSKlSoIOmnyHzooYe0bds2PfHEE2rQoIH27NmjyZMn66uvvtLy5cv98wwfPlzz589Xv3791KZNG23cuDHg+wqgBBgAt4yzZ88aSaZnz55X3e+hhx4ykkxOTo4xxpiUlBQTExNjLl++7N/n5MmTJigoyPz3f/+3f13Hjh1NkyZNzD//+U//Op/PZ9q0aWPq1avnXzdnzhwjybRt2zbgmMYYs2nTJiPJLF68OGB98+bNTUxMjPn+++/96z7//HMTFBRkBg4c6F83cOBAExQUZHbs2FHo6/L5fMYYY8aOHWuK+uupYK7Dhw8bY4xZtmyZkVTksQocPnzYSDKTJk0qcvukSZMCjmmMMe3btzeNGjW64jELXveNN97wr4uPjzeSCi1jx441xvzf963g8ZV89tlnRX5//9WRI0dMcHCweeWVVwLW79mzx4SEhASsHzRokImPj/c//uijj4wk89577wU8d/Xq1QHrz549a8LDw01SUpK5cOFCwL4FPydjjOnWrVvA8Qu8++67JigoyHz00UcB62fMmGEkmY8//tgYY0xmZqaRZJ5++umA/fr161es7xeAG8MlYOAWkpubK0kKDw+/6n4F23NyciRJffv21enTp7V582b/PkuWLJHP51Pfvn0lST/88IM2btyoPn36KDc3V2fOnNGZM2f0/fffq0uXLjpw4ICOHz8e8DqPP/64goODrzn3yZMnlZmZqcGDBysqKsq/vmnTpnrwwQf1t7/9TdJPZ4WWL1+uHj16KDExsdBxirrsezUFZ7lWrlypS5cuXddzf4mCs1wFP68CSUlJWrduXcAycOBAST9dLjXGXPNjTQrO8K1Zs0bnz58vcp+lS5fK5/OpT58+/p/jmTNnVK1aNdWrV0+bNm264vEXL16syMhIPfjggwHPbdGihSpUqOB/7rp165Sbm6vRo0erXLlyAccozs9p8eLFatCggerXrx/wOg888IAk+V+n4M9GWlpawPN5UwlQsrgEDNxCCsLu52Hxcz8PxX/7t39TZGSkFi5cqI4dO0r66fJv8+bNdeedd0qSDh48KGOMXnrpJb300ktFHvf06dOqWbOm/3Ht2rWLNffRo0clSXfddVehbQ0aNNCaNWuUl5enc+fOKScnx39J+pdq3769HnnkEY0fP16TJ09Whw4d1KtXL/Xr109ut/u6jnU98Xnu3DlJhUO9SpUq6tSp03W97s/Vrl1bo0aN0uuvv6733ntP7dq100MPPaQBAwb44/DAgQMyxqhevXpFHuPn707+VwcO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", + "text/html": [ "\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" + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " ], "text/plain": [ - "" + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" ] }, "metadata": {}, @@ -24821,11 +1051,24 @@ }, { "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "dd4541cf48b94d419ca97c37199dd7bb", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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JkyY4HTo0MGJiopy4uLinDvuuMNZs2ZN0HFnzpxx8vPzHZ/P58TExDj33Xefc+zYsQt+Dczx48eDHp+Xl+e0aNGi3p/9Yl+BA8BdHsfhKl0AAABLuAYQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGAIQAADAGH4TCK5ITU2NDh8+rJiYmAv+QnkAwLXLcRxVVlYqOTlZYWGsB1lDAOKKHD58WKmpqW6PAQD4jkpLS5WSkuL2GAgxAhBXJCYmRpJ0u36gCDVzeRoAwOU6r3PaqD8G/jyHLQQgrkjtad8INVOEhwAEgCbn//8iWC7jsYmT/gAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgAAAAMYQgMbNmjVLGRkZioqKUlZWlj766CO3RwIAAI2MADRsyZIlmjJliqZNm6atW7eqV69eGjp0qI4dO+b2aAAAoBERgIb9/Oc/1yOPPKKHHnpIXbt21csvv6zmzZvrt7/9rdujAQCARkQAGnX27Flt2bJFgwcPDuwLCwvT4MGD9eGHH7o4GQAAaGwRbg8Ad5w4cULV1dVq3bp10P7WrVvrk08+qXO83++X3+8P3K6oqGj0GQEAQONgBRANUlhYKJ/PF9hSU1PdHgkAAFwhAtCo+Ph4hYeH6+jRo0H7jx49qjZt2tQ5furUqSovLw9spaWloRoVAABcZQSgUZGRkbr11lu1du3awL6amhqtXbtW/fr1q3O81+tVbGxs0AYAAJomrgE0bMqUKcrLy1NmZqb69u2rF198UVVVVXrooYfcHg0AADQiAtCwMWPG6Pjx4/rxj3+sL774Qr1799Y777xT54MhAADg+uJxHMdxewg0PRUVFfL5fBqkkYrwNHN7HADAZTrvnNM6vany8nIu6zGIawABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQABAACMIQCN2rBhg0aMGKHk5GR5PB4tX77c7ZEAAECIEIBGVVVVqVevXpo1a5bbowAAgBCLcHsAuCMnJ0c5OTlujwEAAFzACiAAAIAxrACiQfx+v/x+f+B2RUWFi9MAAIDvghVANEhhYaF8Pl9gS01NdXskAABwhQhANMjUqVNVXl4e2EpLS90eCQAAXCFOAaNBvF6vvF6v22MAAICrgAA06vTp09q7d2/g9v79+7Vt2zbFxcUpLS3NxckAAEBjIwCNKikp0R133BG4PWXKFElSXl6e5s+f79JUAAAgFAhAowYNGiTHcdweAwAAuIAPgQAAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDABpVWFioPn36KCYmRomJiRo1apR2797t9lgAACAECECj1q9fr4KCAm3atEmrV6/WuXPnNGTIEFVVVbk9GgAAaGQRbg8Ad7zzzjtBt+fPn6/ExERt2bJFAwYMcGkqAAAQCgQgJEnl5eWSpLi4uHrv9/v98vv9gdsVFRUhmQsAAFx9nAKGampqNHnyZGVnZ6t79+71HlNYWCifzxfYUlNTQzwlAAC4WghAqKCgQDt37tTixYsveMzUqVNVXl4e2EpLS0M4IQAAuJo4BWzcxIkTtXLlSm3YsEEpKSkXPM7r9crr9YZwMgAA0FgIQKMcx9ETTzyhZcuWad26dWrXrp3bIwEAgBAhAI0qKCjQokWL9OabbyomJkZffPGFJMnn8yk6Otrl6QAAQGPiGkCjZs+erfLycg0aNEhJSUmBbcmSJW6PBgAAGhkrgEY5juP2CAAAwCWsAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhDAAIAABhD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", "text/html": [ - "" + "\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " ], "text/plain": [ - "" + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" ] }, "metadata": {}, @@ -24834,12 +1077,37 @@ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 15, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a72a4543ee224a29ae113bd99fed9840", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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+OKLyx6D/5BpbxSF3VE19kY1uQI4gvbt2xebN2+OuXPnDp0bNWpUzJ07N55//vkSJzs6+vr6IiJi3LhxJU8yvLq6uuKqq6464M+xWTz++OMxc+bMuO6662LChAkxY8aMuP/++8seK7VseyPC7qgae6OaBOAIeuutt2JgYCAmTpx4wPmJEyfGzp07S5rq6BgcHIxFixbFnDlzYtq0aWWPM2xWrlwZW7ZsiZ6enrJHOSpef/31WLZsWZx55pmxevXquPnmm+PWW2+NBx54oOzR0sq0NyLsjiqyN6qptewBaE5dXV2xbdu2eO6558oeZdj09vbGbbfdFmvWrImxY8eWPc5RMTg4GDNnzow777wzIiJmzJgR27Zti3vuuScWLlxY8nRkYHdUj71RTa4AjqCTTjopRo8eHbt27Trg/K5du+Lkk08uaarhd8stt8STTz4Zv/vd72LKlClljzNsNm/eHLt3747zzz8/Wltbo7W1NdavXx8//OEPo7W1NQYGBsoe8YhNmjQppk6desC5s88+O7Zv317SRGTZGxF2R1XZG9UkAEfQmDFj4oILLoi1a9cOnRscHIy1a9fG7NmzS5xseBRFEbfcckusWrUqfvvb38bpp59e9kjD6vLLL48XX3wxtm7dOnTMnDkzFixYEFu3bo3Ro0eXPeIRmzNnzvt+/MYrr7wSp556akkT0ex7I8LuqPrusDcqquzvQslm5cqVRa1WK1asWFG89NJLxVe+8pXi+OOPL3bu3Fn2aEfs5ptvLjo6Oop169YVb7755tDxr3/9q+zRjppm+k6+oiiKF154oWhtbS2+853vFK+++mrx0EMPFccdd1zx4IMPlj1aas28N4rC7qg6e6OaBGAJfvSjHxWnnHJKMWbMmOKiiy4qNmzYUPZIwyIiDnosX7687NGOmmZa4v/2xBNPFNOmTStqtVpx1llnFffdd1/ZI1E0794oCrujGdgb1dNSFEVRzrVHAADK4DOAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACQjAAEAkhGAAADJCEAAgGQEIABAMgIQACAZAQgAkIwABABIRgACACTz31c0oPcs+vDuAAAAAElFTkSuQmCC", + "text/html": [ + "\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ @@ -24883,9 +1151,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python (calib311)", "language": "python", - "name": "python3" + "name": "calib311" }, "language_info": { "codemirror_mode": { @@ -24897,7 +1165,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.11.5" } }, "nbformat": 4, diff --git a/src/microscope_calibration/util/stem_overfocus_sim.py b/src/microscope_calibration/util/stem_overfocus_sim.py index f2e88cf..a6e9ef4 100644 --- a/src/microscope_calibration/util/stem_overfocus_sim.py +++ b/src/microscope_calibration/util/stem_overfocus_sim.py @@ -55,6 +55,13 @@ def smiley(size): def get_transformation_matrix(sim_params: OverfocusParams): + ''' + Calculate a transformation matrix for :func:`detector_px_to_specimen_px` + from the provided parameters. + + Internally this uses :func:`libertem.analysis.com.apply_correction` to + transform unit vectors in order to determine the matrix. + ''' transformation_matrix = np.array(com_analysis.apply_correction( y_centers=np.array((1, 0)), x_centers=np.array((0, 1)), @@ -68,6 +75,32 @@ def get_transformation_matrix(sim_params: OverfocusParams): def detector_px_to_specimen_px( y_px, x_px, cy, cx, detector_pixel_size, scan_pixel_size, camera_length, overfocus, transformation_matrix, fov_size_y, fov_size_x): + ''' + Model Figure 2 of https://arxiv.org/abs/2403.08538 + + Parameters + ---------- + + y_px, x_px : float + Detector pixel coordinates to project + cy, cx : float + Detector center in detector pixel coordinates + detector_pixel_size, scan_pixel_size : float + Physical pixel sizes. This assumes a uniform scan and detector grid in x + and y direction + camera_length : float + Virtual distance from specimen to detector + overfocus : float + Virtual distance from focus point to specimen. Underfocus is specified + as a negative overfocus. + transformation_matrix : np.ndarray[float] + 2x2 transformation matrix for detector coordinates. This is used to + specify rotation and handedness change consistent with other methods in + LiberTEM. It can be calculated with :fun:`get_transformation_matrix`. + fov_size_y, fov_size_x : float + Size of the scan area (field of view) in scan pixels. The scan + coordinate system is centered in the middle of the field of view. + ''' position_y, position_x = (y_px - cy) * detector_pixel_size, (x_px - cx) * detector_pixel_size position_y, position_x = transformation_matrix @ np.array((position_y, position_x)) specimen_position_y = position_y / (overfocus + camera_length) * overfocus diff --git a/tests/test_overfocus.py b/tests/test_overfocus.py index 45095c9..3d1b729 100644 --- a/tests/test_overfocus.py +++ b/tests/test_overfocus.py @@ -52,73 +52,179 @@ def test_get_transformation_matrix(params): # params are relative to default parameters in function below 'params', [ ( - {}, + { + 'overfocus': 1, + 'scan_pixel_size': 1, + 'camera_length': 1, + 'detector_pixel_size': 1, + 'cy': 0, + 'cx': 0, + 'y_px': 0., + 'x_px': 0., + 'fov_size_y': 0, + 'fov_size_x': 0, + 'transformation_matrix': np.array(((1., 0.), (0., 1.))), + }, + # Straight through central beam (0, 0) ), ( { + 'overfocus': 1, + 'scan_pixel_size': 1, + 'camera_length': 0, + 'detector_pixel_size': 1, + 'cy': 0, + 'cx': 0, + 'y_px': 3., + 'x_px': -7., + 'fov_size_y': 0, + 'fov_size_x': 0, + 'transformation_matrix': np.array(((1., 0.), (0., 1.))), + }, + # Camera length 0, same grid and not transformation means detector + # and scan pixels are the same + (3., -7.) + ), + ( + { + 'overfocus': 1, + 'scan_pixel_size': 1, + 'camera_length': 1, + 'detector_pixel_size': 1, + 'cy': 0, + 'cx': 0, 'y_px': 3., 'x_px': -7., + 'fov_size_y': 0, + 'fov_size_x': 0, + 'transformation_matrix': np.array(((1., 0.), (0., 1.))), }, + # 2x demagnification from detector to specimen (1.5, -3.5) ), ( { + 'overfocus': -1, + 'scan_pixel_size': 1, + 'camera_length': 2, + 'detector_pixel_size': 1, + 'cy': 0, + 'cx': 0, + 'y_px': 3., + 'x_px': -7., + 'fov_size_y': 0, + 'fov_size_x': 0, + 'transformation_matrix': np.array(((1., 0.), (0., 1.))), + }, + # Negative overfocus means coordinates are inverted compared to positive + # overfocus + # Magnification overfocus/(overfocus + camera_length) is -1 here + (-3, 7) + ), + ( + { + 'overfocus': 1, + 'scan_pixel_size': 1, + 'camera_length': 1, + 'detector_pixel_size': 1, + 'cy': 0, + 'cx': 0, 'y_px': 3., 'x_px': -7., + 'fov_size_y': 0, + 'fov_size_x': 0, 'transformation_matrix': np.array(((-1., 0.), (0., -1.))), }, + # Transformation inverts both axes, 180 deg rotation (-1.5, 3.5) ), ( { + 'overfocus': 1, + 'scan_pixel_size': 1, + 'camera_length': 1, 'detector_pixel_size': 2, + 'cy': 0, + 'cx': 0, 'y_px': 3., 'x_px': -7., + 'fov_size_y': 0, + 'fov_size_x': 0, + 'transformation_matrix': np.array(((1., 0.), (0., 1.))), }, + # 2x demagnification and half the pixel size from detector to scan (3, -7) ), ( { + 'overfocus': 1, 'scan_pixel_size': 0.5, 'camera_length': 2, + 'detector_pixel_size': 1, + 'cy': 0, + 'cx': 0, 'y_px': 3., 'x_px': -7., + 'fov_size_y': 0, + 'fov_size_x': 0, + 'transformation_matrix': np.array(((1., 0.), (0., 1.))), }, - # Factor 2 from pixel size ratio, factor 3 from - # overfocus / (camera length + overfocus) + # Factor 2 magnification from pixel size ratio, factor 3 + # demagnification from overfocus / (camera length + overfocus) (3*2/3, -7*2/3) ), ( { 'overfocus': 0.1, 'scan_pixel_size': 0.1, + 'camera_length': 1, + 'detector_pixel_size': 1, + 'cy': 0, + 'cx': 0, 'y_px': 3., 'x_px': -7., + 'fov_size_y': 0, + 'fov_size_x': 0, + 'transformation_matrix': np.array(((1., 0.), (0., 1.))), }, - # Factor 10 from pixel size ratio, factor 0.11 from - # overfocus / (camera length + overfocus) - (3/1.1, -7/1.1) + # Factor 10 magnification from pixel size ratio, factor 0.11 + # demagnification from overfocus / (camera length + overfocus) + (3*10*0.1/1.1, -7*10*0.1/1.1) ), ( { + 'overfocus': 1, + 'scan_pixel_size': 1, + 'camera_length': 1, + 'detector_pixel_size': 1, 'cy': 1, 'cx': 5, 'y_px': 3., 'x_px': -7., + 'fov_size_y': 0, + 'fov_size_x': 0, + 'transformation_matrix': np.array(((1., 0.), (0., 1.))), }, # (y_px - cy) * overfocus / (camera length + overfocus) - ((3 - 1)/2, (-7 - 5)/2) + ((3 - 1)*1/(1 + 1), (-7 - 5)*1/(1 + 1)) ), ( { + 'overfocus': 1, + 'scan_pixel_size': 1, + 'camera_length': 1, + 'detector_pixel_size': 1, + 'cy': 0, + 'cx': 0, 'y_px': 3., 'x_px': -7., 'fov_size_y': 4, 'fov_size_x': 6, + 'transformation_matrix': np.array(((1., 0.), (0., 1.))), }, - # (y_px - fov_size_y) * overfocus / (camera length + overfocus) - ((3 + 4) / 2, (-7 + 6) / 2) + # y_px * overfocus / (camera length + overfocus) + fov_size / 2 + (3/2 + 4/2, -7/2 + 6/2) ), ( { @@ -134,49 +240,53 @@ def test_get_transformation_matrix(params): 'fov_size_x': 10, 'transformation_matrix': np.array(((-1., 0.), (0., -1.))), }, + # (y_px + cy) * detector_pixel_size / scan_pixel_size * \ + # overfocus / (camera length + overfocus) + fov_size / 2 ((-3 + 17) * 2/2 + 2, (7 + 19) * 2/2 + 5) ), ( { 'overfocus': 0.1, 'scan_pixel_size': 0.1, + 'camera_length': 1, + 'detector_pixel_size': 1, + 'cy': 0, + 'cx': 0, 'y_px': 3., 'x_px': -7., + 'fov_size_y': 0, + 'fov_size_x': 0, 'transformation_matrix': np.array(((-1., 0.), (0., 1.))), }, - (3 * -1 * 10 * 0.1/1.1, -7 * 1 * 10 * 0.1 / 1.1) + # flip_y: y axis inverted + # -1 * y_px * detector_pixel_size / scan_pixel_size * \ + # overfocus / (camera length + overfocus) + (-1 * 3 * 1/0.1 * 0.1/1.1, 1 * -7 * 1/0.1 * 0.1/1.1) ), ( { 'overfocus': 0.1, 'scan_pixel_size': 0.1, + 'camera_length': 1, + 'detector_pixel_size': 1, + 'cy': 6, + 'cx': 5, 'y_px': 3., 'x_px': -7., 'fov_size_y': 4, 'fov_size_x': 10, 'transformation_matrix': np.array(((-1., 0.), (0., 1.))), }, - (-1 * (3 * 10 * 0.1/1.1 - 4/2), 1 * (-7 * 10 * 0.1 / 1.1 + 10/2)), + # flip_y: y axis inverted + # -1 * (y_px - cy) * detector_pixel_size / scan_pixel_size * \ + # overfocus / (camera length + overfocus) + fov_size / 2 + (-1 * (3 - 6) * 1/0.1 * 0.1/1.1 + 4/2, 1 * (-7 - 5) * 1/0.1 * 0.1 / 1.1 + 10/2), ), ] ) def test_detector_specimen_px(params): inp, ref = params - func_params = { - 'overfocus': 1, - 'scan_pixel_size': 1, - 'camera_length': 1, - 'detector_pixel_size': 1, - 'cy': 0, - 'cx': 0, - 'y_px': 0., - 'x_px': 0., - 'fov_size_y': 0, - 'fov_size_x': 0, - 'transformation_matrix': np.array(((1., 0.), (0., 1.))), - } - func_params.update(inp) - res = detector_px_to_specimen_px(**func_params) + res = detector_px_to_specimen_px(**inp) assert_allclose(res, ref, atol=1e-8) @@ -204,6 +314,61 @@ def test_project(): assert_allclose(obj, projected[:, :, size//2, size//2]) +def test_project_zerocl(): + # Camera length is zero, 1:1 match of scan and detector + size = 16 + params = OverfocusParams( + overfocus=1, + scan_pixel_size=1, + camera_length=0, + detector_pixel_size=1, + semiconv=0.004, + cy=size/2, + cx=size/2, + scan_rotation=0, + flip_y=False + ) + obj = smiley(size) + projected = project( + image=obj, + scan_shape=(size, size), + detector_shape=(size, size), + sim_params=params, + ) + assert_allclose(obj, projected[size//2, size//2]) + assert_allclose(obj, projected[:, :, size//2, size//2]) + + +def test_project_scale(): + # With overfocus == 1 and cl == 1, the image is 2x magnified on the + # detector. With same pixel size and twice the number of pixels, every + # second detector pixel maps to a single scan pixel + size = 16 + detector_size = 2 * size + params = OverfocusParams( + overfocus=1, + scan_pixel_size=1, + camera_length=1, + detector_pixel_size=1, + semiconv=0.004, + cy=detector_size/2, + cx=detector_size/2, + scan_rotation=0, + flip_y=False + ) + obj = smiley(size) + projected = project( + image=obj, + scan_shape=(size, size), + detector_shape=(detector_size, detector_size), + sim_params=params, + ) + # Center of the scan, severy second detector pixel + assert_allclose(obj, projected[size//2, size//2, ::2, ::2]) + # Scan area, trace of center of detector + assert_allclose(obj, projected[:, :, size*2//2, size*2//2]) + + def test_project_2(): size = 16 params = OverfocusParams( From 85558795725a515f37dbf9a0dacb3edde25b1ea3 Mon Sep 17 00:00:00 2001 From: Dieter Weber Date: Tue, 16 Apr 2024 11:25:19 +0200 Subject: [PATCH 5/6] Save testbed, let's see if figures work --- prototypes/testbed.ipynb | 62 ++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/prototypes/testbed.ipynb b/prototypes/testbed.ipynb index 9df4bc0..9b9c477 100644 --- a/prototypes/testbed.ipynb +++ b/prototypes/testbed.ipynb @@ -46,7 +46,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 4, @@ -56,7 +56,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "85d84b7c7bc94036940db3ef4b17422f", + "model_id": "e071166dc865494b882623e951220bf1", "version_major": 2, "version_minor": 0 }, @@ -211,7 +211,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 8, @@ -221,7 +221,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "4fbcd821bab34487b59e05426d3d19ef", + "model_id": "4896eb20d98b4312bc3677be6d62b2ee", "version_major": 2, "version_minor": 0 }, @@ -246,7 +246,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "ffd126179d2b4f46881f1dcd4e2b25c9", + "model_id": "880558113c3748c195c70a45cf27ad27", "version_major": 2, "version_minor": 0 }, @@ -290,7 +290,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "5395aed8b71947529d3ddcf14f5fdd32", + "model_id": "ed13357a252148ab8c1988facd52d00e", "version_major": 2, "version_minor": 0 }, @@ -315,7 +315,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "35f010e01e9a469b8ca9dddc421a6131", + "model_id": "8bd9f6fa7eab4f7a8c460ed469f6c65c", "version_major": 2, "version_minor": 0 }, @@ -340,7 +340,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "77b74f8086de46b993bfd06a26689271", + "model_id": "33aa14789384459c813d2d205bf22714", "version_major": 2, "version_minor": 0 }, @@ -365,7 +365,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "af84e6c10e114c148d20f4e05081de16", + "model_id": "c24a48c6f3164f78bf662fb860153bff", "version_major": 2, "version_minor": 0 }, @@ -435,7 +435,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 10, @@ -445,7 +445,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "fa6f4397ead849b9bb3ab21015edd2fb", + "model_id": "b8eec9ed893e46d09beab7a1d67bad11", "version_major": 2, "version_minor": 0 }, @@ -482,7 +482,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 11, @@ -492,7 +492,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "f07f5767fdb648e19fc7d6377833bcc4", + "model_id": "a1de5a267c744b67adbc7ecd725ca4bc", "version_major": 2, "version_minor": 0 }, @@ -635,7 +635,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "b671e485f50f4050b7d5d7f01defe434", + "model_id": "f2f098809dc947b491585e45fbd21010", "version_major": 2, "version_minor": 0 }, @@ -660,7 +660,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "bc8fdb19a3d146e7ab74f643287d3970", + "model_id": "e4c38a70e2374d30b6008c667a63e90e", "version_major": 2, "version_minor": 0 }, @@ -685,7 +685,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "8ac1972cd2fe46b18a576dcdc8dd151d", + "model_id": "7fd8763831f143a19b42ab9ec7afc212", "version_major": 2, "version_minor": 0 }, @@ -710,7 +710,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "2d29bd22cb4b45e9b9f15201e35731d6", + "model_id": "23ffc7a615984b8fa7ae1ffdf3987127", "version_major": 2, "version_minor": 0 }, @@ -735,7 +735,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "6576a79ed36d410891936727d4b64188", + "model_id": "dfb85c3ea0514622a5cec9a4cf93760d", "version_major": 2, "version_minor": 0 }, @@ -760,7 +760,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "f298d9f6cd664eccac4e1c550ec55b05", + "model_id": "603a594e4fe34320aac65d874f6fa4c1", "version_major": 2, "version_minor": 0 }, @@ -785,7 +785,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "ba728075f6004e4a96a56a42006b2c5a", + "model_id": "e9814e14e8f449c189f9479d0d99c0ea", "version_major": 2, "version_minor": 0 }, @@ -810,7 +810,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "73435e28960b47aea3761c64bb37fc52", + "model_id": "7de9ffc913f5458abaf687e0f3fce4ae", "version_major": 2, "version_minor": 0 }, @@ -869,7 +869,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "358daf45005e410ea1a7e88f68a6c072", + "model_id": "bafb0b2b57c94f2383b338343eae4595", "version_major": 2, "version_minor": 0 }, @@ -894,7 +894,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "3378b4a2dff248fe93515c6f09969e62", + "model_id": "6fdb0b413ef745458b1fa588d170eb4a", "version_major": 2, "version_minor": 0 }, @@ -919,7 +919,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "0b97dc1c12864d3aab4eb1bc9c4192be", + "model_id": "2d976575634b41b3afbc9a522ae35f7d", "version_major": 2, "version_minor": 0 }, @@ -952,7 +952,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "730e60043dbb4f3ea0a72122ef89036d", + "model_id": "5e16e2d7c1db45ff930fcdf3ca3d5500", "version_major": 2, "version_minor": 0 }, @@ -977,7 +977,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "1fb3d687dec541f19d8ac793ce271d55", + "model_id": "e8ed7369587346a3bddc276db5e84481", "version_major": 2, "version_minor": 0 }, @@ -1002,7 +1002,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "c80bb2b9aa174699933167938e73097e", + "model_id": "553ebee3269b4d9492e1941be0b25e11", "version_major": 2, "version_minor": 0 }, @@ -1027,7 +1027,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "ec1c8eb3a3874591b9b0d1c7e4e9ac29", + "model_id": "46b3017bc2914cb0bc7d82c37551b534", "version_major": 2, "version_minor": 0 }, @@ -1052,7 +1052,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "dd4541cf48b94d419ca97c37199dd7bb", + "model_id": "df5e46b015344ffc95d40e1b314834f7", "version_major": 2, "version_minor": 0 }, @@ -1077,7 +1077,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 16, @@ -1087,7 +1087,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "a72a4543ee224a29ae113bd99fed9840", + "model_id": "d175c18e06ae402bb8df57910873ccbf", "version_major": 2, "version_minor": 0 }, From 6db5a14e2ddb27d94504bfc2e6fe60befcada12f Mon Sep 17 00:00:00 2001 From: Dieter Weber Date: Tue, 16 Apr 2024 15:13:05 +0200 Subject: [PATCH 6/6] Clarity, second review @sk1p Thx! :-) --- .../util/stem_overfocus_sim.py | 42 ++++++++++++++----- tests/test_overfocus.py | 26 +++++++++++- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/microscope_calibration/util/stem_overfocus_sim.py b/src/microscope_calibration/util/stem_overfocus_sim.py index a6e9ef4..453176b 100644 --- a/src/microscope_calibration/util/stem_overfocus_sim.py +++ b/src/microscope_calibration/util/stem_overfocus_sim.py @@ -78,28 +78,48 @@ def detector_px_to_specimen_px( ''' Model Figure 2 of https://arxiv.org/abs/2403.08538 + The pixel coordinates refer to the center of a pixel: In :func:`_project` + they are rounded to the nearest integer. This function is just transforming + coordinates independent of actual scan and detector sizes. Rounding and + bounds checks are performed in :func:`_project`. + + The specimen pixel coordinates calculated by this function are combined with + the scan coordinates in :func:`_project` to model the scan. + Parameters ---------- y_px, x_px : float - Detector pixel coordinates to project + Detector pixel coordinates to project. They are relative to (cy, cx), + where specifying pixel coordinates (0.0, 0.0) maps to physical + coordinates (-cy * detector_pixel_size, -cx *detector_pixel_size), and + pixel coordinates (cy, cx) map to physical coordinates (0.0. 0.0). cy, cx : float - Detector center in detector pixel coordinates + Detector center in detector pixel coordinates. This defines the position + of the "straight through" beam on the detector. detector_pixel_size, scan_pixel_size : float - Physical pixel sizes. This assumes a uniform scan and detector grid in x - and y direction + Physical pixel sizes in m. This assumes a uniform scan and detector grid + in x and y direction camera_length : float - Virtual distance from specimen to detector + Virtual distance from specimen to detector in m overfocus : float - Virtual distance from focus point to specimen. Underfocus is specified - as a negative overfocus. + Virtual distance from focus point to specimen in m. Underfocus is + specified as a negative overfocus. transformation_matrix : np.ndarray[float] - 2x2 transformation matrix for detector coordinates. This is used to - specify rotation and handedness change consistent with other methods in - LiberTEM. It can be calculated with :fun:`get_transformation_matrix`. + 2x2 transformation matrix for detector coordinates. It acts around (cy, + cx). This is used to specify rotation and handedness change consistent + with other methods in LiberTEM. It can be calculated with + :fun:`get_transformation_matrix`. fov_size_y, fov_size_x : float Size of the scan area (field of view) in scan pixels. The scan - coordinate system is centered in the middle of the field of view. + coordinate system is centered in the middle of this field of view, + meaning that the "straight through" beam (y_px, x_px) == (cy, cx) is + mapped to (fov_size_y/2, fov_size_x/2) + + Returns + ------- + specimen_px_y, specimen_px_x : float + Beam position on the specimen in scan pixel coordinates. ''' position_y, position_x = (y_px - cy) * detector_pixel_size, (x_px - cx) * detector_pixel_size position_y, position_x = transformation_matrix @ np.array((position_y, position_x)) diff --git a/tests/test_overfocus.py b/tests/test_overfocus.py index 3d1b729..f36628d 100644 --- a/tests/test_overfocus.py +++ b/tests/test_overfocus.py @@ -61,6 +61,8 @@ def test_get_transformation_matrix(params): 'cx': 0, 'y_px': 0., 'x_px': 0., + # fov_size_* == 0 means that (0, 0) in scan coordinates is + # (0, 0) in physical coordinates. 'fov_size_y': 0, 'fov_size_x': 0, 'transformation_matrix': np.array(((1., 0.), (0., 1.))), @@ -68,6 +70,26 @@ def test_get_transformation_matrix(params): # Straight through central beam (0, 0) ), + ( + { + 'overfocus': 0.1234, + 'scan_pixel_size': 0.987, + 'camera_length': 2.34, + 'detector_pixel_size': 0.71, + 'cy': 13, + 'cx': 14, + 'y_px': 13., + 'x_px': 14., + 'fov_size_y': 5, + 'fov_size_x': 6, + 'transformation_matrix': np.array(((0., 1.), (-1., 0.))), + }, + # Straight through central beam goes through center of fov. The + # straight through beam is not affected by scan rotation, flip_y, + # overfocus, scan pixel size, detector pixel size, or camera length + # fov_size_y/2, fov_size_x/2 + (2.5, 3) + ), ( { 'overfocus': 1, @@ -363,10 +385,10 @@ def test_project_scale(): detector_shape=(detector_size, detector_size), sim_params=params, ) - # Center of the scan, severy second detector pixel + # Center of the scan, every second detector pixel assert_allclose(obj, projected[size//2, size//2, ::2, ::2]) # Scan area, trace of center of detector - assert_allclose(obj, projected[:, :, size*2//2, size*2//2]) + assert_allclose(obj, projected[:, :, detector_size//2, detector_size//2]) def test_project_2():