{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "912ed572-1658-406b-976c-cd6de2d4e89e", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:35:53.616586Z", "iopub.status.busy": "2026-07-15T08:35:53.616364Z", "iopub.status.idle": "2026-07-15T08:35:57.472999Z", "shell.execute_reply": "2026-07-15T08:35:57.472477Z" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function(root) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " const force = true;\n", " const py_version = '3.7.3'.replace('rc', '-rc.').replace('.dev', '-dev.');\n", " const reloading = false;\n", " const Bokeh = root.Bokeh;\n", "\n", " // Set a timeout for this load but only if we are not already initializing\n", " if (typeof (root._bokeh_timeout) === \"undefined\" || (force || !root._bokeh_is_initializing)) {\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_failed_load = false;\n", " }\n", "\n", " function run_callbacks() {\n", " try {\n", " root._bokeh_onload_callbacks.forEach(function(callback) {\n", " if (callback != null)\n", " callback();\n", " });\n", " } finally {\n", " delete root._bokeh_onload_callbacks;\n", " }\n", " console.debug(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n", " if (css_urls == null) css_urls = [];\n", " if (js_urls == null) js_urls = [];\n", " if (js_modules == null) js_modules = [];\n", " if (js_exports == null) js_exports = {};\n", "\n", " root._bokeh_onload_callbacks.push(callback);\n", "\n", " if (root._bokeh_is_loading > 0) {\n", " // Don't load bokeh if it is still initializing\n", " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " } else if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n", " // There is nothing to load\n", " run_callbacks();\n", " return null;\n", " }\n", "\n", " function on_load() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", " run_callbacks()\n", " }\n", " }\n", " window._bokeh_on_load = on_load\n", "\n", " function on_error(e) {\n", " const src_el = e.srcElement\n", " console.error(\"failed to load \" + (src_el.href || src_el.src));\n", " }\n", "\n", " const skip = [];\n", " if (window.requirejs) {\n", " window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n", " root._bokeh_is_loading = css_urls.length + 0;\n", " } else {\n", " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n", " }\n", "\n", " const existing_stylesheets = []\n", " const links = document.getElementsByTagName('link')\n", " for (let i = 0; i < links.length; i++) {\n", " const link = links[i]\n", " if (link.href != null) {\n", " existing_stylesheets.push(link.href)\n", " }\n", " }\n", " for (let i = 0; i < css_urls.length; i++) {\n", " const url = css_urls[i];\n", " const escaped = encodeURI(url)\n", " if (existing_stylesheets.indexOf(escaped) !== -1) {\n", " on_load()\n", " continue;\n", " }\n", " const element = document.createElement(\"link\");\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.rel = \"stylesheet\";\n", " element.type = \"text/css\";\n", " element.href = url;\n", " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", " document.body.appendChild(element);\n", " } var existing_scripts = []\n", " const scripts = document.getElementsByTagName('script')\n", " for (let i = 0; i < scripts.length; i++) {\n", " var script = scripts[i]\n", " if (script.src != null) {\n", " existing_scripts.push(script.src)\n", " }\n", " }\n", " for (let i = 0; i < js_urls.length; i++) {\n", " const url = js_urls[i];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " const element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " for (let i = 0; i < js_modules.length; i++) {\n", " const url = js_modules[i];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " var element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " element.type = \"module\";\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " for (const name in js_exports) {\n", " const url = js_exports[name];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) >= 0 || root[name] != null) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " var element = document.createElement('script');\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.type = \"module\";\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " element.textContent = `\n", " import ${name} from \"${url}\"\n", " window.${name} = ${name}\n", " window._bokeh_on_load()\n", " `\n", " document.head.appendChild(element);\n", " }\n", " if (!js_urls.length && !js_modules.length) {\n", " on_load()\n", " }\n", " };\n", "\n", " function inject_raw_css(css) {\n", " const element = document.createElement(\"style\");\n", " element.appendChild(document.createTextNode(css));\n", " document.body.appendChild(element);\n", " }\n", "\n", " const js_urls = [\"https://cdn.holoviz.org/panel/1.7.5/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-3.7.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.7.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.7.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.7.3.min.js\", \"https://cdn.holoviz.org/panel/1.7.5/dist/panel.min.js\"];\n", " const js_modules = [];\n", " const js_exports = {};\n", " const css_urls = [];\n", " const inline_js = [ function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", "function(Bokeh) {} // ensure no trailing comma for IE\n", " ];\n", "\n", " function run_inline_js() {\n", " if ((root.Bokeh !== undefined) || (force === true)) {\n", " for (let i = 0; i < inline_js.length; i++) {\n", " try {\n", " inline_js[i].call(root, root.Bokeh);\n", " } catch(e) {\n", " if (!reloading) {\n", " throw e;\n", " }\n", " }\n", " }\n", " // Cache old bokeh versions\n", " if (Bokeh != undefined && !reloading) {\n", " var NewBokeh = root.Bokeh;\n", " if (Bokeh.versions === undefined) {\n", " Bokeh.versions = new Map();\n", " }\n", " if (NewBokeh.version !== Bokeh.version) {\n", " Bokeh.versions.set(NewBokeh.version, NewBokeh)\n", " }\n", " root.Bokeh = Bokeh;\n", " }\n", " } else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!root._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " root._bokeh_failed_load = true;\n", " }\n", " root._bokeh_is_initializing = false\n", " }\n", "\n", " function load_or_wait() {\n", " // Implement a backoff loop that tries to ensure we do not load multiple\n", " // versions of Bokeh and its dependencies at the same time.\n", " // In recent versions we use the root._bokeh_is_initializing flag\n", " // to determine whether there is an ongoing attempt to initialize\n", " // bokeh, however for backward compatibility we also try to ensure\n", " // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n", " // before older versions are fully initialized.\n", " if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n", " // If the timeout and bokeh was not successfully loaded we reset\n", " // everything and try loading again\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_is_initializing = false;\n", " root._bokeh_onload_callbacks = undefined;\n", " root._bokeh_is_loading = 0\n", " console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n", " load_or_wait();\n", " } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n", " setTimeout(load_or_wait, 100);\n", " } else {\n", " root._bokeh_is_initializing = true\n", " root._bokeh_onload_callbacks = []\n", " const bokeh_loaded = root.Bokeh != null && (root.Bokeh.version === py_version || (root.Bokeh.versions !== undefined && root.Bokeh.versions.has(py_version)));\n", " if (!reloading && !bokeh_loaded) {\n", " if (root.Bokeh) {\n", " root.Bokeh = undefined;\n", " }\n", " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " }\n", " load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n", " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", " }\n", " // Give older versions of the autoload script a head-start to ensure\n", " // they initialize before we start loading newer version.\n", " setTimeout(load_or_wait, 100)\n", "}(window));" ], "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n const force = true;\n const py_version = '3.7.3'.replace('rc', '-rc.').replace('.dev', '-dev.');\n const reloading = false;\n const Bokeh = root.Bokeh;\n\n // Set a timeout for this load but only if we are not already initializing\n if (typeof (root._bokeh_timeout) === \"undefined\" || (force || !root._bokeh_is_initializing)) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks;\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n if (js_exports == null) js_exports = {};\n\n root._bokeh_onload_callbacks.push(callback);\n\n if (root._bokeh_is_loading > 0) {\n // Don't load bokeh if it is still initializing\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n } else if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n // There is nothing to load\n run_callbacks();\n return null;\n }\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n window._bokeh_on_load = on_load\n\n function on_error(e) {\n const src_el = e.srcElement\n console.error(\"failed to load \" + (src_el.href || src_el.src));\n }\n\n const skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n root._bokeh_is_loading = css_urls.length + 0;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n }\n\n const existing_stylesheets = []\n const links = document.getElementsByTagName('link')\n for (let i = 0; i < links.length; i++) {\n const link = links[i]\n if (link.href != null) {\n existing_stylesheets.push(link.href)\n }\n }\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const escaped = encodeURI(url)\n if (existing_stylesheets.indexOf(escaped) !== -1) {\n on_load()\n continue;\n }\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n } var existing_scripts = []\n const scripts = document.getElementsByTagName('script')\n for (let i = 0; i < scripts.length; i++) {\n var script = scripts[i]\n if (script.src != null) {\n existing_scripts.push(script.src)\n }\n }\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (let i = 0; i < js_modules.length; i++) {\n const url = js_modules[i];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (const name in js_exports) {\n const url = js_exports[name];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) >= 0 || root[name] != null) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n var element = document.createElement('script');\n element.onerror = on_error;\n element.async = false;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n element.textContent = `\n import ${name} from \"${url}\"\n window.${name} = ${name}\n window._bokeh_on_load()\n `\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n const js_urls = [\"https://cdn.holoviz.org/panel/1.7.5/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-3.7.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.7.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.7.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.7.3.min.js\", \"https://cdn.holoviz.org/panel/1.7.5/dist/panel.min.js\"];\n const js_modules = [];\n const js_exports = {};\n const css_urls = [];\n const inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (let i = 0; i < inline_js.length; i++) {\n try {\n inline_js[i].call(root, root.Bokeh);\n } catch(e) {\n if (!reloading) {\n throw e;\n }\n }\n }\n // Cache old bokeh versions\n if (Bokeh != undefined && !reloading) {\n var NewBokeh = root.Bokeh;\n if (Bokeh.versions === undefined) {\n Bokeh.versions = new Map();\n }\n if (NewBokeh.version !== Bokeh.version) {\n Bokeh.versions.set(NewBokeh.version, NewBokeh)\n }\n root.Bokeh = Bokeh;\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n root._bokeh_is_initializing = false\n }\n\n function load_or_wait() {\n // Implement a backoff loop that tries to ensure we do not load multiple\n // versions of Bokeh and its dependencies at the same time.\n // In recent versions we use the root._bokeh_is_initializing flag\n // to determine whether there is an ongoing attempt to initialize\n // bokeh, however for backward compatibility we also try to ensure\n // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n // before older versions are fully initialized.\n if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n // If the timeout and bokeh was not successfully loaded we reset\n // everything and try loading again\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_is_initializing = false;\n root._bokeh_onload_callbacks = undefined;\n root._bokeh_is_loading = 0\n console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n load_or_wait();\n } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n setTimeout(load_or_wait, 100);\n } else {\n root._bokeh_is_initializing = true\n root._bokeh_onload_callbacks = []\n const bokeh_loaded = root.Bokeh != null && (root.Bokeh.version === py_version || (root.Bokeh.versions !== undefined && root.Bokeh.versions.has(py_version)));\n if (!reloading && !bokeh_loaded) {\n if (root.Bokeh) {\n root.Bokeh = undefined;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n }\n load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n }\n // Give older versions of the autoload script a head-start to ensure\n // they initialize before we start loading newer version.\n setTimeout(load_or_wait, 100)\n}(window));" }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", "}\n", "\n", "\n", " function JupyterCommManager() {\n", " }\n", "\n", " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", " comm_manager.register_target(comm_id, function(comm) {\n", " comm.on_msg(msg_handler);\n", " });\n", " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", " comm.onMsg = msg_handler;\n", " });\n", " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", " var messages = comm.messages[Symbol.asyncIterator]();\n", " function processIteratorResult(result) {\n", " var message = result.value;\n", " var content = {data: message.data, comm_id};\n", " var buffers = []\n", " for (var buffer of message.buffers || []) {\n", " buffers.push(new DataView(buffer))\n", " }\n", " var metadata = message.metadata || {};\n", " var msg = {content, buffers, metadata}\n", " msg_handler(msg);\n", " return messages.next().then(processIteratorResult);\n", " }\n", " return messages.next().then(processIteratorResult);\n", " })\n", " }\n", " }\n", "\n", " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", " if (comm_id in window.PyViz.comms) {\n", " return window.PyViz.comms[comm_id];\n", " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", " if (msg_handler) {\n", " comm.on_msg(msg_handler);\n", " }\n", " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", " let retries = 0;\n", " const open = () => {\n", " if (comm.active) {\n", " comm.open();\n", " } else if (retries > 3) {\n", " console.warn('Comm target never activated')\n", " } else {\n", " retries += 1\n", " setTimeout(open, 500)\n", " }\n", " }\n", " if (comm.active) {\n", " comm.open();\n", " } else {\n", " setTimeout(open, 500)\n", " }\n", " if (msg_handler) {\n", " comm.onMsg = msg_handler;\n", " }\n", " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", " comm_promise.then((comm) => {\n", " window.PyViz.comms[comm_id] = comm;\n", " if (msg_handler) {\n", " var messages = comm.messages[Symbol.asyncIterator]();\n", " function processIteratorResult(result) {\n", " var message = result.value;\n", " var content = {data: message.data};\n", " var metadata = message.metadata || {comm_id};\n", " var msg = {content, metadata}\n", " msg_handler(msg);\n", " return messages.next().then(processIteratorResult);\n", " }\n", " return messages.next().then(processIteratorResult);\n", " }\n", " })\n", " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", " return comm_promise.then((comm) => {\n", " comm.send(data, metadata, buffers, disposeOnDone);\n", " });\n", " };\n", " var comm = {\n", " send: sendClosure\n", " };\n", " }\n", " window.PyViz.comms[comm_id] = comm;\n", " return comm;\n", " }\n", " window.PyViz.comm_manager = new JupyterCommManager();\n", " \n", "\n", "\n", "var JS_MIME_TYPE = 'application/javascript';\n", "var HTML_MIME_TYPE = 'text/html';\n", "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", "var CLASS_NAME = 'output';\n", "\n", "/**\n", " * Render data to the DOM node\n", " */\n", "function render(props, node) {\n", " var div = document.createElement(\"div\");\n", " var script = document.createElement(\"script\");\n", " node.appendChild(div);\n", " node.appendChild(script);\n", "}\n", "\n", "/**\n", " * Handle when a new output is added\n", " */\n", "function handle_add_output(event, handle) {\n", " var output_area = handle.output_area;\n", " var output = handle.output;\n", " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", " return\n", " }\n", " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", " if (id !== undefined) {\n", " var nchildren = toinsert.length;\n", " var html_node = toinsert[nchildren-1].children[0];\n", " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", " var scripts = [];\n", " var nodelist = html_node.querySelectorAll(\"script\");\n", " for (var i in nodelist) {\n", " if (nodelist.hasOwnProperty(i)) {\n", " scripts.push(nodelist[i])\n", " }\n", " }\n", "\n", " scripts.forEach( function (oldScript) {\n", " var newScript = document.createElement(\"script\");\n", " var attrs = [];\n", " var nodemap = oldScript.attributes;\n", " for (var j in nodemap) {\n", " if (nodemap.hasOwnProperty(j)) {\n", " attrs.push(nodemap[j])\n", " }\n", " }\n", " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", " oldScript.parentNode.replaceChild(newScript, oldScript);\n", " });\n", " if (JS_MIME_TYPE in output.data) {\n", " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", " }\n", " output_area._hv_plot_id = id;\n", " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", " window.PyViz.plot_index[id] = Bokeh.index[id];\n", " } else {\n", " window.PyViz.plot_index[id] = null;\n", " }\n", " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", " var bk_div = document.createElement(\"div\");\n", " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", " var script_attrs = bk_div.children[0].attributes;\n", " for (var i = 0; i < script_attrs.length; i++) {\n", " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " }\n", " // store reference to server id on output_area\n", " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", " }\n", "}\n", "\n", "/**\n", " * Handle when an output is cleared or removed\n", " */\n", "function handle_clear_output(event, handle) {\n", " var id = handle.cell.output_area._hv_plot_id;\n", " var server_id = handle.cell.output_area._bokeh_server_id;\n", " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", " if (server_id !== null) {\n", " comm.send({event_type: 'server_delete', 'id': server_id});\n", " return;\n", " } else if (comm !== null) {\n", " comm.send({event_type: 'delete', 'id': id});\n", " }\n", " delete PyViz.plot_index[id];\n", " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", " var doc = window.Bokeh.index[id].model.document\n", " doc.clear();\n", " const i = window.Bokeh.documents.indexOf(doc);\n", " if (i > -1) {\n", " window.Bokeh.documents.splice(i, 1);\n", " }\n", " }\n", "}\n", "\n", "/**\n", " * Handle kernel restart event\n", " */\n", "function handle_kernel_cleanup(event, handle) {\n", " delete PyViz.comms[\"hv-extension-comm\"];\n", " window.PyViz.plot_index = {}\n", "}\n", "\n", "/**\n", " * Handle update_display_data messages\n", " */\n", "function handle_update_output(event, handle) {\n", " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", " handle_add_output(event, handle)\n", "}\n", "\n", "function register_renderer(events, OutputArea) {\n", " function append_mime(data, metadata, element) {\n", " // create a DOM node to render to\n", " var toinsert = this.create_output_subarea(\n", " metadata,\n", " CLASS_NAME,\n", " EXEC_MIME_TYPE\n", " );\n", " this.keyboard_manager.register_events(toinsert);\n", " // Render to node\n", " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", " render(props, toinsert[0]);\n", " element.append(toinsert);\n", " return toinsert\n", " }\n", "\n", " events.on('output_added.OutputArea', handle_add_output);\n", " events.on('output_updated.OutputArea', handle_update_output);\n", " events.on('clear_output.CodeCell', handle_clear_output);\n", " events.on('delete.Cell', handle_clear_output);\n", " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", "\n", " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", " safe: true,\n", " index: 0\n", " });\n", "}\n", "\n", "if (window.Jupyter !== undefined) {\n", " try {\n", " var events = require('base/js/events');\n", " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", " register_renderer(events, OutputArea);\n", " }\n", " } catch(err) {\n", " }\n", "}\n" ], "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n let retries = 0;\n const open = () => {\n if (comm.active) {\n comm.open();\n } else if (retries > 3) {\n console.warn('Comm target never activated')\n } else {\n retries += 1\n setTimeout(open, 500)\n }\n }\n if (comm.active) {\n comm.open();\n } else {\n setTimeout(open, 500)\n }\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n })\n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.holoviews_exec.v0+json": "", "text/html": [ "
\n", "
\n", "
\n", "" ] }, "metadata": { "application/vnd.holoviews_exec.v0+json": { "id": "65d243ee-b2d2-4cda-aebd-4eea09e6d928" } }, "output_type": "display_data" }, { "data": { "text/html": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function(root) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " const force = false;\n", " const py_version = '3.7.3'.replace('rc', '-rc.').replace('.dev', '-dev.');\n", " const reloading = true;\n", " const Bokeh = root.Bokeh;\n", "\n", " // Set a timeout for this load but only if we are not already initializing\n", " if (typeof (root._bokeh_timeout) === \"undefined\" || (force || !root._bokeh_is_initializing)) {\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_failed_load = false;\n", " }\n", "\n", " function run_callbacks() {\n", " try {\n", " root._bokeh_onload_callbacks.forEach(function(callback) {\n", " if (callback != null)\n", " callback();\n", " });\n", " } finally {\n", " delete root._bokeh_onload_callbacks;\n", " }\n", " console.debug(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n", " if (css_urls == null) css_urls = [];\n", " if (js_urls == null) js_urls = [];\n", " if (js_modules == null) js_modules = [];\n", " if (js_exports == null) js_exports = {};\n", "\n", " root._bokeh_onload_callbacks.push(callback);\n", "\n", " if (root._bokeh_is_loading > 0) {\n", " // Don't load bokeh if it is still initializing\n", " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " } else if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n", " // There is nothing to load\n", " run_callbacks();\n", " return null;\n", " }\n", "\n", " function on_load() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", " run_callbacks()\n", " }\n", " }\n", " window._bokeh_on_load = on_load\n", "\n", " function on_error(e) {\n", " const src_el = e.srcElement\n", " console.error(\"failed to load \" + (src_el.href || src_el.src));\n", " }\n", "\n", " const skip = [];\n", " if (window.requirejs) {\n", " window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n", " root._bokeh_is_loading = css_urls.length + 0;\n", " } else {\n", " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n", " }\n", "\n", " const existing_stylesheets = []\n", " const links = document.getElementsByTagName('link')\n", " for (let i = 0; i < links.length; i++) {\n", " const link = links[i]\n", " if (link.href != null) {\n", " existing_stylesheets.push(link.href)\n", " }\n", " }\n", " for (let i = 0; i < css_urls.length; i++) {\n", " const url = css_urls[i];\n", " const escaped = encodeURI(url)\n", " if (existing_stylesheets.indexOf(escaped) !== -1) {\n", " on_load()\n", " continue;\n", " }\n", " const element = document.createElement(\"link\");\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.rel = \"stylesheet\";\n", " element.type = \"text/css\";\n", " element.href = url;\n", " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", " document.body.appendChild(element);\n", " } var existing_scripts = []\n", " const scripts = document.getElementsByTagName('script')\n", " for (let i = 0; i < scripts.length; i++) {\n", " var script = scripts[i]\n", " if (script.src != null) {\n", " existing_scripts.push(script.src)\n", " }\n", " }\n", " for (let i = 0; i < js_urls.length; i++) {\n", " const url = js_urls[i];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " const element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " for (let i = 0; i < js_modules.length; i++) {\n", " const url = js_modules[i];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " var element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " element.type = \"module\";\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " for (const name in js_exports) {\n", " const url = js_exports[name];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) >= 0 || root[name] != null) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " var element = document.createElement('script');\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.type = \"module\";\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " element.textContent = `\n", " import ${name} from \"${url}\"\n", " window.${name} = ${name}\n", " window._bokeh_on_load()\n", " `\n", " document.head.appendChild(element);\n", " }\n", " if (!js_urls.length && !js_modules.length) {\n", " on_load()\n", " }\n", " };\n", "\n", " function inject_raw_css(css) {\n", " const element = document.createElement(\"style\");\n", " element.appendChild(document.createTextNode(css));\n", " document.body.appendChild(element);\n", " }\n", "\n", " const js_urls = [\"https://cdn.holoviz.org/panel/1.7.5/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\"];\n", " const js_modules = [];\n", " const js_exports = {};\n", " const css_urls = [];\n", " const inline_js = [ function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", "function(Bokeh) {} // ensure no trailing comma for IE\n", " ];\n", "\n", " function run_inline_js() {\n", " if ((root.Bokeh !== undefined) || (force === true)) {\n", " for (let i = 0; i < inline_js.length; i++) {\n", " try {\n", " inline_js[i].call(root, root.Bokeh);\n", " } catch(e) {\n", " if (!reloading) {\n", " throw e;\n", " }\n", " }\n", " }\n", " // Cache old bokeh versions\n", " if (Bokeh != undefined && !reloading) {\n", " var NewBokeh = root.Bokeh;\n", " if (Bokeh.versions === undefined) {\n", " Bokeh.versions = new Map();\n", " }\n", " if (NewBokeh.version !== Bokeh.version) {\n", " Bokeh.versions.set(NewBokeh.version, NewBokeh)\n", " }\n", " root.Bokeh = Bokeh;\n", " }\n", " } else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!root._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " root._bokeh_failed_load = true;\n", " }\n", " root._bokeh_is_initializing = false\n", " }\n", "\n", " function load_or_wait() {\n", " // Implement a backoff loop that tries to ensure we do not load multiple\n", " // versions of Bokeh and its dependencies at the same time.\n", " // In recent versions we use the root._bokeh_is_initializing flag\n", " // to determine whether there is an ongoing attempt to initialize\n", " // bokeh, however for backward compatibility we also try to ensure\n", " // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n", " // before older versions are fully initialized.\n", " if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n", " // If the timeout and bokeh was not successfully loaded we reset\n", " // everything and try loading again\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_is_initializing = false;\n", " root._bokeh_onload_callbacks = undefined;\n", " root._bokeh_is_loading = 0\n", " console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n", " load_or_wait();\n", " } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n", " setTimeout(load_or_wait, 100);\n", " } else {\n", " root._bokeh_is_initializing = true\n", " root._bokeh_onload_callbacks = []\n", " const bokeh_loaded = root.Bokeh != null && (root.Bokeh.version === py_version || (root.Bokeh.versions !== undefined && root.Bokeh.versions.has(py_version)));\n", " if (!reloading && !bokeh_loaded) {\n", " if (root.Bokeh) {\n", " root.Bokeh = undefined;\n", " }\n", " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " }\n", " load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n", " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", " }\n", " // Give older versions of the autoload script a head-start to ensure\n", " // they initialize before we start loading newer version.\n", " setTimeout(load_or_wait, 100)\n", "}(window));" ], "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n const force = false;\n const py_version = '3.7.3'.replace('rc', '-rc.').replace('.dev', '-dev.');\n const reloading = true;\n const Bokeh = root.Bokeh;\n\n // Set a timeout for this load but only if we are not already initializing\n if (typeof (root._bokeh_timeout) === \"undefined\" || (force || !root._bokeh_is_initializing)) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks;\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n if (js_exports == null) js_exports = {};\n\n root._bokeh_onload_callbacks.push(callback);\n\n if (root._bokeh_is_loading > 0) {\n // Don't load bokeh if it is still initializing\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n } else if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n // There is nothing to load\n run_callbacks();\n return null;\n }\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n window._bokeh_on_load = on_load\n\n function on_error(e) {\n const src_el = e.srcElement\n console.error(\"failed to load \" + (src_el.href || src_el.src));\n }\n\n const skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n root._bokeh_is_loading = css_urls.length + 0;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n }\n\n const existing_stylesheets = []\n const links = document.getElementsByTagName('link')\n for (let i = 0; i < links.length; i++) {\n const link = links[i]\n if (link.href != null) {\n existing_stylesheets.push(link.href)\n }\n }\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const escaped = encodeURI(url)\n if (existing_stylesheets.indexOf(escaped) !== -1) {\n on_load()\n continue;\n }\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n } var existing_scripts = []\n const scripts = document.getElementsByTagName('script')\n for (let i = 0; i < scripts.length; i++) {\n var script = scripts[i]\n if (script.src != null) {\n existing_scripts.push(script.src)\n }\n }\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (let i = 0; i < js_modules.length; i++) {\n const url = js_modules[i];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (const name in js_exports) {\n const url = js_exports[name];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) >= 0 || root[name] != null) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n var element = document.createElement('script');\n element.onerror = on_error;\n element.async = false;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n element.textContent = `\n import ${name} from \"${url}\"\n window.${name} = ${name}\n window._bokeh_on_load()\n `\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n const js_urls = [\"https://cdn.holoviz.org/panel/1.7.5/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\"];\n const js_modules = [];\n const js_exports = {};\n const css_urls = [];\n const inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (let i = 0; i < inline_js.length; i++) {\n try {\n inline_js[i].call(root, root.Bokeh);\n } catch(e) {\n if (!reloading) {\n throw e;\n }\n }\n }\n // Cache old bokeh versions\n if (Bokeh != undefined && !reloading) {\n var NewBokeh = root.Bokeh;\n if (Bokeh.versions === undefined) {\n Bokeh.versions = new Map();\n }\n if (NewBokeh.version !== Bokeh.version) {\n Bokeh.versions.set(NewBokeh.version, NewBokeh)\n }\n root.Bokeh = Bokeh;\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n root._bokeh_is_initializing = false\n }\n\n function load_or_wait() {\n // Implement a backoff loop that tries to ensure we do not load multiple\n // versions of Bokeh and its dependencies at the same time.\n // In recent versions we use the root._bokeh_is_initializing flag\n // to determine whether there is an ongoing attempt to initialize\n // bokeh, however for backward compatibility we also try to ensure\n // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n // before older versions are fully initialized.\n if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n // If the timeout and bokeh was not successfully loaded we reset\n // everything and try loading again\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_is_initializing = false;\n root._bokeh_onload_callbacks = undefined;\n root._bokeh_is_loading = 0\n console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n load_or_wait();\n } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n setTimeout(load_or_wait, 100);\n } else {\n root._bokeh_is_initializing = true\n root._bokeh_onload_callbacks = []\n const bokeh_loaded = root.Bokeh != null && (root.Bokeh.version === py_version || (root.Bokeh.versions !== undefined && root.Bokeh.versions.has(py_version)));\n if (!reloading && !bokeh_loaded) {\n if (root.Bokeh) {\n root.Bokeh = undefined;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n }\n load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n }\n // Give older versions of the autoload script a head-start to ensure\n // they initialize before we start loading newer version.\n setTimeout(load_or_wait, 100)\n}(window));" }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", "}\n", "\n", "\n", " function JupyterCommManager() {\n", " }\n", "\n", " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", " comm_manager.register_target(comm_id, function(comm) {\n", " comm.on_msg(msg_handler);\n", " });\n", " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", " comm.onMsg = msg_handler;\n", " });\n", " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", " var messages = comm.messages[Symbol.asyncIterator]();\n", " function processIteratorResult(result) {\n", " var message = result.value;\n", " var content = {data: message.data, comm_id};\n", " var buffers = []\n", " for (var buffer of message.buffers || []) {\n", " buffers.push(new DataView(buffer))\n", " }\n", " var metadata = message.metadata || {};\n", " var msg = {content, buffers, metadata}\n", " msg_handler(msg);\n", " return messages.next().then(processIteratorResult);\n", " }\n", " return messages.next().then(processIteratorResult);\n", " })\n", " }\n", " }\n", "\n", " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", " if (comm_id in window.PyViz.comms) {\n", " return window.PyViz.comms[comm_id];\n", " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", " if (msg_handler) {\n", " comm.on_msg(msg_handler);\n", " }\n", " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", " let retries = 0;\n", " const open = () => {\n", " if (comm.active) {\n", " comm.open();\n", " } else if (retries > 3) {\n", " console.warn('Comm target never activated')\n", " } else {\n", " retries += 1\n", " setTimeout(open, 500)\n", " }\n", " }\n", " if (comm.active) {\n", " comm.open();\n", " } else {\n", " setTimeout(open, 500)\n", " }\n", " if (msg_handler) {\n", " comm.onMsg = msg_handler;\n", " }\n", " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", " comm_promise.then((comm) => {\n", " window.PyViz.comms[comm_id] = comm;\n", " if (msg_handler) {\n", " var messages = comm.messages[Symbol.asyncIterator]();\n", " function processIteratorResult(result) {\n", " var message = result.value;\n", " var content = {data: message.data};\n", " var metadata = message.metadata || {comm_id};\n", " var msg = {content, metadata}\n", " msg_handler(msg);\n", " return messages.next().then(processIteratorResult);\n", " }\n", " return messages.next().then(processIteratorResult);\n", " }\n", " })\n", " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", " return comm_promise.then((comm) => {\n", " comm.send(data, metadata, buffers, disposeOnDone);\n", " });\n", " };\n", " var comm = {\n", " send: sendClosure\n", " };\n", " }\n", " window.PyViz.comms[comm_id] = comm;\n", " return comm;\n", " }\n", " window.PyViz.comm_manager = new JupyterCommManager();\n", " \n", "\n", "\n", "var JS_MIME_TYPE = 'application/javascript';\n", "var HTML_MIME_TYPE = 'text/html';\n", "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", "var CLASS_NAME = 'output';\n", "\n", "/**\n", " * Render data to the DOM node\n", " */\n", "function render(props, node) {\n", " var div = document.createElement(\"div\");\n", " var script = document.createElement(\"script\");\n", " node.appendChild(div);\n", " node.appendChild(script);\n", "}\n", "\n", "/**\n", " * Handle when a new output is added\n", " */\n", "function handle_add_output(event, handle) {\n", " var output_area = handle.output_area;\n", " var output = handle.output;\n", " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", " return\n", " }\n", " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", " if (id !== undefined) {\n", " var nchildren = toinsert.length;\n", " var html_node = toinsert[nchildren-1].children[0];\n", " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", " var scripts = [];\n", " var nodelist = html_node.querySelectorAll(\"script\");\n", " for (var i in nodelist) {\n", " if (nodelist.hasOwnProperty(i)) {\n", " scripts.push(nodelist[i])\n", " }\n", " }\n", "\n", " scripts.forEach( function (oldScript) {\n", " var newScript = document.createElement(\"script\");\n", " var attrs = [];\n", " var nodemap = oldScript.attributes;\n", " for (var j in nodemap) {\n", " if (nodemap.hasOwnProperty(j)) {\n", " attrs.push(nodemap[j])\n", " }\n", " }\n", " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", " oldScript.parentNode.replaceChild(newScript, oldScript);\n", " });\n", " if (JS_MIME_TYPE in output.data) {\n", " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", " }\n", " output_area._hv_plot_id = id;\n", " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", " window.PyViz.plot_index[id] = Bokeh.index[id];\n", " } else {\n", " window.PyViz.plot_index[id] = null;\n", " }\n", " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", " var bk_div = document.createElement(\"div\");\n", " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", " var script_attrs = bk_div.children[0].attributes;\n", " for (var i = 0; i < script_attrs.length; i++) {\n", " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " }\n", " // store reference to server id on output_area\n", " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", " }\n", "}\n", "\n", "/**\n", " * Handle when an output is cleared or removed\n", " */\n", "function handle_clear_output(event, handle) {\n", " var id = handle.cell.output_area._hv_plot_id;\n", " var server_id = handle.cell.output_area._bokeh_server_id;\n", " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", " if (server_id !== null) {\n", " comm.send({event_type: 'server_delete', 'id': server_id});\n", " return;\n", " } else if (comm !== null) {\n", " comm.send({event_type: 'delete', 'id': id});\n", " }\n", " delete PyViz.plot_index[id];\n", " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", " var doc = window.Bokeh.index[id].model.document\n", " doc.clear();\n", " const i = window.Bokeh.documents.indexOf(doc);\n", " if (i > -1) {\n", " window.Bokeh.documents.splice(i, 1);\n", " }\n", " }\n", "}\n", "\n", "/**\n", " * Handle kernel restart event\n", " */\n", "function handle_kernel_cleanup(event, handle) {\n", " delete PyViz.comms[\"hv-extension-comm\"];\n", " window.PyViz.plot_index = {}\n", "}\n", "\n", "/**\n", " * Handle update_display_data messages\n", " */\n", "function handle_update_output(event, handle) {\n", " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", " handle_add_output(event, handle)\n", "}\n", "\n", "function register_renderer(events, OutputArea) {\n", " function append_mime(data, metadata, element) {\n", " // create a DOM node to render to\n", " var toinsert = this.create_output_subarea(\n", " metadata,\n", " CLASS_NAME,\n", " EXEC_MIME_TYPE\n", " );\n", " this.keyboard_manager.register_events(toinsert);\n", " // Render to node\n", " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", " render(props, toinsert[0]);\n", " element.append(toinsert);\n", " return toinsert\n", " }\n", "\n", " events.on('output_added.OutputArea', handle_add_output);\n", " events.on('output_updated.OutputArea', handle_update_output);\n", " events.on('clear_output.CodeCell', handle_clear_output);\n", " events.on('delete.Cell', handle_clear_output);\n", " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", "\n", " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", " safe: true,\n", " index: 0\n", " });\n", "}\n", "\n", "if (window.Jupyter !== undefined) {\n", " try {\n", " var events = require('base/js/events');\n", " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", " register_renderer(events, OutputArea);\n", " }\n", " } catch(err) {\n", " }\n", "}\n" ], "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n let retries = 0;\n const open = () => {\n if (comm.active) {\n comm.open();\n } else if (retries > 3) {\n console.warn('Comm target never activated')\n } else {\n retries += 1\n setTimeout(open, 500)\n }\n }\n if (comm.active) {\n comm.open();\n } else {\n setTimeout(open, 500)\n }\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n })\n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function(root) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " const force = false;\n", " const py_version = '3.7.3'.replace('rc', '-rc.').replace('.dev', '-dev.');\n", " const reloading = true;\n", " const Bokeh = root.Bokeh;\n", "\n", " // Set a timeout for this load but only if we are not already initializing\n", " if (typeof (root._bokeh_timeout) === \"undefined\" || (force || !root._bokeh_is_initializing)) {\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_failed_load = false;\n", " }\n", "\n", " function run_callbacks() {\n", " try {\n", " root._bokeh_onload_callbacks.forEach(function(callback) {\n", " if (callback != null)\n", " callback();\n", " });\n", " } finally {\n", " delete root._bokeh_onload_callbacks;\n", " }\n", " console.debug(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n", " if (css_urls == null) css_urls = [];\n", " if (js_urls == null) js_urls = [];\n", " if (js_modules == null) js_modules = [];\n", " if (js_exports == null) js_exports = {};\n", "\n", " root._bokeh_onload_callbacks.push(callback);\n", "\n", " if (root._bokeh_is_loading > 0) {\n", " // Don't load bokeh if it is still initializing\n", " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " } else if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n", " // There is nothing to load\n", " run_callbacks();\n", " return null;\n", " }\n", "\n", " function on_load() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", " run_callbacks()\n", " }\n", " }\n", " window._bokeh_on_load = on_load\n", "\n", " function on_error(e) {\n", " const src_el = e.srcElement\n", " console.error(\"failed to load \" + (src_el.href || src_el.src));\n", " }\n", "\n", " const skip = [];\n", " if (window.requirejs) {\n", " window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n", " root._bokeh_is_loading = css_urls.length + 0;\n", " } else {\n", " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n", " }\n", "\n", " const existing_stylesheets = []\n", " const links = document.getElementsByTagName('link')\n", " for (let i = 0; i < links.length; i++) {\n", " const link = links[i]\n", " if (link.href != null) {\n", " existing_stylesheets.push(link.href)\n", " }\n", " }\n", " for (let i = 0; i < css_urls.length; i++) {\n", " const url = css_urls[i];\n", " const escaped = encodeURI(url)\n", " if (existing_stylesheets.indexOf(escaped) !== -1) {\n", " on_load()\n", " continue;\n", " }\n", " const element = document.createElement(\"link\");\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.rel = \"stylesheet\";\n", " element.type = \"text/css\";\n", " element.href = url;\n", " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", " document.body.appendChild(element);\n", " } var existing_scripts = []\n", " const scripts = document.getElementsByTagName('script')\n", " for (let i = 0; i < scripts.length; i++) {\n", " var script = scripts[i]\n", " if (script.src != null) {\n", " existing_scripts.push(script.src)\n", " }\n", " }\n", " for (let i = 0; i < js_urls.length; i++) {\n", " const url = js_urls[i];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " const element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " for (let i = 0; i < js_modules.length; i++) {\n", " const url = js_modules[i];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " var element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " element.type = \"module\";\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " for (const name in js_exports) {\n", " const url = js_exports[name];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) >= 0 || root[name] != null) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " var element = document.createElement('script');\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.type = \"module\";\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " element.textContent = `\n", " import ${name} from \"${url}\"\n", " window.${name} = ${name}\n", " window._bokeh_on_load()\n", " `\n", " document.head.appendChild(element);\n", " }\n", " if (!js_urls.length && !js_modules.length) {\n", " on_load()\n", " }\n", " };\n", "\n", " function inject_raw_css(css) {\n", " const element = document.createElement(\"style\");\n", " element.appendChild(document.createTextNode(css));\n", " document.body.appendChild(element);\n", " }\n", "\n", " const js_urls = [\"https://cdn.holoviz.org/panel/1.7.5/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\"];\n", " const js_modules = [];\n", " const js_exports = {};\n", " const css_urls = [];\n", " const inline_js = [ function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", "function(Bokeh) {} // ensure no trailing comma for IE\n", " ];\n", "\n", " function run_inline_js() {\n", " if ((root.Bokeh !== undefined) || (force === true)) {\n", " for (let i = 0; i < inline_js.length; i++) {\n", " try {\n", " inline_js[i].call(root, root.Bokeh);\n", " } catch(e) {\n", " if (!reloading) {\n", " throw e;\n", " }\n", " }\n", " }\n", " // Cache old bokeh versions\n", " if (Bokeh != undefined && !reloading) {\n", " var NewBokeh = root.Bokeh;\n", " if (Bokeh.versions === undefined) {\n", " Bokeh.versions = new Map();\n", " }\n", " if (NewBokeh.version !== Bokeh.version) {\n", " Bokeh.versions.set(NewBokeh.version, NewBokeh)\n", " }\n", " root.Bokeh = Bokeh;\n", " }\n", " } else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!root._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " root._bokeh_failed_load = true;\n", " }\n", " root._bokeh_is_initializing = false\n", " }\n", "\n", " function load_or_wait() {\n", " // Implement a backoff loop that tries to ensure we do not load multiple\n", " // versions of Bokeh and its dependencies at the same time.\n", " // In recent versions we use the root._bokeh_is_initializing flag\n", " // to determine whether there is an ongoing attempt to initialize\n", " // bokeh, however for backward compatibility we also try to ensure\n", " // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n", " // before older versions are fully initialized.\n", " if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n", " // If the timeout and bokeh was not successfully loaded we reset\n", " // everything and try loading again\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_is_initializing = false;\n", " root._bokeh_onload_callbacks = undefined;\n", " root._bokeh_is_loading = 0\n", " console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n", " load_or_wait();\n", " } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n", " setTimeout(load_or_wait, 100);\n", " } else {\n", " root._bokeh_is_initializing = true\n", " root._bokeh_onload_callbacks = []\n", " const bokeh_loaded = root.Bokeh != null && (root.Bokeh.version === py_version || (root.Bokeh.versions !== undefined && root.Bokeh.versions.has(py_version)));\n", " if (!reloading && !bokeh_loaded) {\n", " if (root.Bokeh) {\n", " root.Bokeh = undefined;\n", " }\n", " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " }\n", " load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n", " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", " }\n", " // Give older versions of the autoload script a head-start to ensure\n", " // they initialize before we start loading newer version.\n", " setTimeout(load_or_wait, 100)\n", "}(window));" ], "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n const force = false;\n const py_version = '3.7.3'.replace('rc', '-rc.').replace('.dev', '-dev.');\n const reloading = true;\n const Bokeh = root.Bokeh;\n\n // Set a timeout for this load but only if we are not already initializing\n if (typeof (root._bokeh_timeout) === \"undefined\" || (force || !root._bokeh_is_initializing)) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks;\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n if (js_exports == null) js_exports = {};\n\n root._bokeh_onload_callbacks.push(callback);\n\n if (root._bokeh_is_loading > 0) {\n // Don't load bokeh if it is still initializing\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n } else if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n // There is nothing to load\n run_callbacks();\n return null;\n }\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n window._bokeh_on_load = on_load\n\n function on_error(e) {\n const src_el = e.srcElement\n console.error(\"failed to load \" + (src_el.href || src_el.src));\n }\n\n const skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n root._bokeh_is_loading = css_urls.length + 0;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n }\n\n const existing_stylesheets = []\n const links = document.getElementsByTagName('link')\n for (let i = 0; i < links.length; i++) {\n const link = links[i]\n if (link.href != null) {\n existing_stylesheets.push(link.href)\n }\n }\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const escaped = encodeURI(url)\n if (existing_stylesheets.indexOf(escaped) !== -1) {\n on_load()\n continue;\n }\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n } var existing_scripts = []\n const scripts = document.getElementsByTagName('script')\n for (let i = 0; i < scripts.length; i++) {\n var script = scripts[i]\n if (script.src != null) {\n existing_scripts.push(script.src)\n }\n }\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (let i = 0; i < js_modules.length; i++) {\n const url = js_modules[i];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (const name in js_exports) {\n const url = js_exports[name];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) >= 0 || root[name] != null) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n var element = document.createElement('script');\n element.onerror = on_error;\n element.async = false;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n element.textContent = `\n import ${name} from \"${url}\"\n window.${name} = ${name}\n window._bokeh_on_load()\n `\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n const js_urls = [\"https://cdn.holoviz.org/panel/1.7.5/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\"];\n const js_modules = [];\n const js_exports = {};\n const css_urls = [];\n const inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (let i = 0; i < inline_js.length; i++) {\n try {\n inline_js[i].call(root, root.Bokeh);\n } catch(e) {\n if (!reloading) {\n throw e;\n }\n }\n }\n // Cache old bokeh versions\n if (Bokeh != undefined && !reloading) {\n var NewBokeh = root.Bokeh;\n if (Bokeh.versions === undefined) {\n Bokeh.versions = new Map();\n }\n if (NewBokeh.version !== Bokeh.version) {\n Bokeh.versions.set(NewBokeh.version, NewBokeh)\n }\n root.Bokeh = Bokeh;\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n root._bokeh_is_initializing = false\n }\n\n function load_or_wait() {\n // Implement a backoff loop that tries to ensure we do not load multiple\n // versions of Bokeh and its dependencies at the same time.\n // In recent versions we use the root._bokeh_is_initializing flag\n // to determine whether there is an ongoing attempt to initialize\n // bokeh, however for backward compatibility we also try to ensure\n // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n // before older versions are fully initialized.\n if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n // If the timeout and bokeh was not successfully loaded we reset\n // everything and try loading again\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_is_initializing = false;\n root._bokeh_onload_callbacks = undefined;\n root._bokeh_is_loading = 0\n console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n load_or_wait();\n } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n setTimeout(load_or_wait, 100);\n } else {\n root._bokeh_is_initializing = true\n root._bokeh_onload_callbacks = []\n const bokeh_loaded = root.Bokeh != null && (root.Bokeh.version === py_version || (root.Bokeh.versions !== undefined && root.Bokeh.versions.has(py_version)));\n if (!reloading && !bokeh_loaded) {\n if (root.Bokeh) {\n root.Bokeh = undefined;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n }\n load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n }\n // Give older versions of the autoload script a head-start to ensure\n // they initialize before we start loading newer version.\n setTimeout(load_or_wait, 100)\n}(window));" }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", "}\n", "\n", "\n", " function JupyterCommManager() {\n", " }\n", "\n", " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", " comm_manager.register_target(comm_id, function(comm) {\n", " comm.on_msg(msg_handler);\n", " });\n", " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", " comm.onMsg = msg_handler;\n", " });\n", " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", " var messages = comm.messages[Symbol.asyncIterator]();\n", " function processIteratorResult(result) {\n", " var message = result.value;\n", " var content = {data: message.data, comm_id};\n", " var buffers = []\n", " for (var buffer of message.buffers || []) {\n", " buffers.push(new DataView(buffer))\n", " }\n", " var metadata = message.metadata || {};\n", " var msg = {content, buffers, metadata}\n", " msg_handler(msg);\n", " return messages.next().then(processIteratorResult);\n", " }\n", " return messages.next().then(processIteratorResult);\n", " })\n", " }\n", " }\n", "\n", " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", " if (comm_id in window.PyViz.comms) {\n", " return window.PyViz.comms[comm_id];\n", " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", " if (msg_handler) {\n", " comm.on_msg(msg_handler);\n", " }\n", " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", " let retries = 0;\n", " const open = () => {\n", " if (comm.active) {\n", " comm.open();\n", " } else if (retries > 3) {\n", " console.warn('Comm target never activated')\n", " } else {\n", " retries += 1\n", " setTimeout(open, 500)\n", " }\n", " }\n", " if (comm.active) {\n", " comm.open();\n", " } else {\n", " setTimeout(open, 500)\n", " }\n", " if (msg_handler) {\n", " comm.onMsg = msg_handler;\n", " }\n", " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", " comm_promise.then((comm) => {\n", " window.PyViz.comms[comm_id] = comm;\n", " if (msg_handler) {\n", " var messages = comm.messages[Symbol.asyncIterator]();\n", " function processIteratorResult(result) {\n", " var message = result.value;\n", " var content = {data: message.data};\n", " var metadata = message.metadata || {comm_id};\n", " var msg = {content, metadata}\n", " msg_handler(msg);\n", " return messages.next().then(processIteratorResult);\n", " }\n", " return messages.next().then(processIteratorResult);\n", " }\n", " })\n", " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", " return comm_promise.then((comm) => {\n", " comm.send(data, metadata, buffers, disposeOnDone);\n", " });\n", " };\n", " var comm = {\n", " send: sendClosure\n", " };\n", " }\n", " window.PyViz.comms[comm_id] = comm;\n", " return comm;\n", " }\n", " window.PyViz.comm_manager = new JupyterCommManager();\n", " \n", "\n", "\n", "var JS_MIME_TYPE = 'application/javascript';\n", "var HTML_MIME_TYPE = 'text/html';\n", "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", "var CLASS_NAME = 'output';\n", "\n", "/**\n", " * Render data to the DOM node\n", " */\n", "function render(props, node) {\n", " var div = document.createElement(\"div\");\n", " var script = document.createElement(\"script\");\n", " node.appendChild(div);\n", " node.appendChild(script);\n", "}\n", "\n", "/**\n", " * Handle when a new output is added\n", " */\n", "function handle_add_output(event, handle) {\n", " var output_area = handle.output_area;\n", " var output = handle.output;\n", " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", " return\n", " }\n", " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", " if (id !== undefined) {\n", " var nchildren = toinsert.length;\n", " var html_node = toinsert[nchildren-1].children[0];\n", " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", " var scripts = [];\n", " var nodelist = html_node.querySelectorAll(\"script\");\n", " for (var i in nodelist) {\n", " if (nodelist.hasOwnProperty(i)) {\n", " scripts.push(nodelist[i])\n", " }\n", " }\n", "\n", " scripts.forEach( function (oldScript) {\n", " var newScript = document.createElement(\"script\");\n", " var attrs = [];\n", " var nodemap = oldScript.attributes;\n", " for (var j in nodemap) {\n", " if (nodemap.hasOwnProperty(j)) {\n", " attrs.push(nodemap[j])\n", " }\n", " }\n", " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", " oldScript.parentNode.replaceChild(newScript, oldScript);\n", " });\n", " if (JS_MIME_TYPE in output.data) {\n", " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", " }\n", " output_area._hv_plot_id = id;\n", " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", " window.PyViz.plot_index[id] = Bokeh.index[id];\n", " } else {\n", " window.PyViz.plot_index[id] = null;\n", " }\n", " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", " var bk_div = document.createElement(\"div\");\n", " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", " var script_attrs = bk_div.children[0].attributes;\n", " for (var i = 0; i < script_attrs.length; i++) {\n", " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " }\n", " // store reference to server id on output_area\n", " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", " }\n", "}\n", "\n", "/**\n", " * Handle when an output is cleared or removed\n", " */\n", "function handle_clear_output(event, handle) {\n", " var id = handle.cell.output_area._hv_plot_id;\n", " var server_id = handle.cell.output_area._bokeh_server_id;\n", " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", " if (server_id !== null) {\n", " comm.send({event_type: 'server_delete', 'id': server_id});\n", " return;\n", " } else if (comm !== null) {\n", " comm.send({event_type: 'delete', 'id': id});\n", " }\n", " delete PyViz.plot_index[id];\n", " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", " var doc = window.Bokeh.index[id].model.document\n", " doc.clear();\n", " const i = window.Bokeh.documents.indexOf(doc);\n", " if (i > -1) {\n", " window.Bokeh.documents.splice(i, 1);\n", " }\n", " }\n", "}\n", "\n", "/**\n", " * Handle kernel restart event\n", " */\n", "function handle_kernel_cleanup(event, handle) {\n", " delete PyViz.comms[\"hv-extension-comm\"];\n", " window.PyViz.plot_index = {}\n", "}\n", "\n", "/**\n", " * Handle update_display_data messages\n", " */\n", "function handle_update_output(event, handle) {\n", " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", " handle_add_output(event, handle)\n", "}\n", "\n", "function register_renderer(events, OutputArea) {\n", " function append_mime(data, metadata, element) {\n", " // create a DOM node to render to\n", " var toinsert = this.create_output_subarea(\n", " metadata,\n", " CLASS_NAME,\n", " EXEC_MIME_TYPE\n", " );\n", " this.keyboard_manager.register_events(toinsert);\n", " // Render to node\n", " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", " render(props, toinsert[0]);\n", " element.append(toinsert);\n", " return toinsert\n", " }\n", "\n", " events.on('output_added.OutputArea', handle_add_output);\n", " events.on('output_updated.OutputArea', handle_update_output);\n", " events.on('clear_output.CodeCell', handle_clear_output);\n", " events.on('delete.Cell', handle_clear_output);\n", " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", "\n", " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", " safe: true,\n", " index: 0\n", " });\n", "}\n", "\n", "if (window.Jupyter !== undefined) {\n", " try {\n", " var events = require('base/js/events');\n", " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", " register_renderer(events, OutputArea);\n", " }\n", " } catch(err) {\n", " }\n", "}\n" ], "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n let retries = 0;\n const open = () => {\n if (comm.active) {\n comm.open();\n } else if (retries > 3) {\n console.warn('Comm target never activated')\n } else {\n retries += 1\n setTimeout(open, 500)\n }\n }\n if (comm.active) {\n comm.open();\n } else {\n setTimeout(open, 500)\n }\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n })\n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function(root) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " const force = false;\n", " const py_version = '3.7.3'.replace('rc', '-rc.').replace('.dev', '-dev.');\n", " const reloading = true;\n", " const Bokeh = root.Bokeh;\n", "\n", " // Set a timeout for this load but only if we are not already initializing\n", " if (typeof (root._bokeh_timeout) === \"undefined\" || (force || !root._bokeh_is_initializing)) {\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_failed_load = false;\n", " }\n", "\n", " function run_callbacks() {\n", " try {\n", " root._bokeh_onload_callbacks.forEach(function(callback) {\n", " if (callback != null)\n", " callback();\n", " });\n", " } finally {\n", " delete root._bokeh_onload_callbacks;\n", " }\n", " console.debug(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n", " if (css_urls == null) css_urls = [];\n", " if (js_urls == null) js_urls = [];\n", " if (js_modules == null) js_modules = [];\n", " if (js_exports == null) js_exports = {};\n", "\n", " root._bokeh_onload_callbacks.push(callback);\n", "\n", " if (root._bokeh_is_loading > 0) {\n", " // Don't load bokeh if it is still initializing\n", " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " } else if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n", " // There is nothing to load\n", " run_callbacks();\n", " return null;\n", " }\n", "\n", " function on_load() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", " run_callbacks()\n", " }\n", " }\n", " window._bokeh_on_load = on_load\n", "\n", " function on_error(e) {\n", " const src_el = e.srcElement\n", " console.error(\"failed to load \" + (src_el.href || src_el.src));\n", " }\n", "\n", " const skip = [];\n", " if (window.requirejs) {\n", " window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n", " root._bokeh_is_loading = css_urls.length + 0;\n", " } else {\n", " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n", " }\n", "\n", " const existing_stylesheets = []\n", " const links = document.getElementsByTagName('link')\n", " for (let i = 0; i < links.length; i++) {\n", " const link = links[i]\n", " if (link.href != null) {\n", " existing_stylesheets.push(link.href)\n", " }\n", " }\n", " for (let i = 0; i < css_urls.length; i++) {\n", " const url = css_urls[i];\n", " const escaped = encodeURI(url)\n", " if (existing_stylesheets.indexOf(escaped) !== -1) {\n", " on_load()\n", " continue;\n", " }\n", " const element = document.createElement(\"link\");\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.rel = \"stylesheet\";\n", " element.type = \"text/css\";\n", " element.href = url;\n", " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", " document.body.appendChild(element);\n", " } var existing_scripts = []\n", " const scripts = document.getElementsByTagName('script')\n", " for (let i = 0; i < scripts.length; i++) {\n", " var script = scripts[i]\n", " if (script.src != null) {\n", " existing_scripts.push(script.src)\n", " }\n", " }\n", " for (let i = 0; i < js_urls.length; i++) {\n", " const url = js_urls[i];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " const element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " for (let i = 0; i < js_modules.length; i++) {\n", " const url = js_modules[i];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " var element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " element.type = \"module\";\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " for (const name in js_exports) {\n", " const url = js_exports[name];\n", " const escaped = encodeURI(url)\n", " if (skip.indexOf(escaped) >= 0 || root[name] != null) {\n", " if (!window.requirejs) {\n", " on_load();\n", " }\n", " continue;\n", " }\n", " var element = document.createElement('script');\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.type = \"module\";\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " element.textContent = `\n", " import ${name} from \"${url}\"\n", " window.${name} = ${name}\n", " window._bokeh_on_load()\n", " `\n", " document.head.appendChild(element);\n", " }\n", " if (!js_urls.length && !js_modules.length) {\n", " on_load()\n", " }\n", " };\n", "\n", " function inject_raw_css(css) {\n", " const element = document.createElement(\"style\");\n", " element.appendChild(document.createTextNode(css));\n", " document.body.appendChild(element);\n", " }\n", "\n", " const js_urls = [\"https://cdn.holoviz.org/panel/1.7.5/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\"];\n", " const js_modules = [];\n", " const js_exports = {};\n", " const css_urls = [];\n", " const inline_js = [ function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", "function(Bokeh) {} // ensure no trailing comma for IE\n", " ];\n", "\n", " function run_inline_js() {\n", " if ((root.Bokeh !== undefined) || (force === true)) {\n", " for (let i = 0; i < inline_js.length; i++) {\n", " try {\n", " inline_js[i].call(root, root.Bokeh);\n", " } catch(e) {\n", " if (!reloading) {\n", " throw e;\n", " }\n", " }\n", " }\n", " // Cache old bokeh versions\n", " if (Bokeh != undefined && !reloading) {\n", " var NewBokeh = root.Bokeh;\n", " if (Bokeh.versions === undefined) {\n", " Bokeh.versions = new Map();\n", " }\n", " if (NewBokeh.version !== Bokeh.version) {\n", " Bokeh.versions.set(NewBokeh.version, NewBokeh)\n", " }\n", " root.Bokeh = Bokeh;\n", " }\n", " } else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!root._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " root._bokeh_failed_load = true;\n", " }\n", " root._bokeh_is_initializing = false\n", " }\n", "\n", " function load_or_wait() {\n", " // Implement a backoff loop that tries to ensure we do not load multiple\n", " // versions of Bokeh and its dependencies at the same time.\n", " // In recent versions we use the root._bokeh_is_initializing flag\n", " // to determine whether there is an ongoing attempt to initialize\n", " // bokeh, however for backward compatibility we also try to ensure\n", " // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n", " // before older versions are fully initialized.\n", " if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n", " // If the timeout and bokeh was not successfully loaded we reset\n", " // everything and try loading again\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_is_initializing = false;\n", " root._bokeh_onload_callbacks = undefined;\n", " root._bokeh_is_loading = 0\n", " console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n", " load_or_wait();\n", " } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n", " setTimeout(load_or_wait, 100);\n", " } else {\n", " root._bokeh_is_initializing = true\n", " root._bokeh_onload_callbacks = []\n", " const bokeh_loaded = root.Bokeh != null && (root.Bokeh.version === py_version || (root.Bokeh.versions !== undefined && root.Bokeh.versions.has(py_version)));\n", " if (!reloading && !bokeh_loaded) {\n", " if (root.Bokeh) {\n", " root.Bokeh = undefined;\n", " }\n", " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " }\n", " load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n", " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", " }\n", " // Give older versions of the autoload script a head-start to ensure\n", " // they initialize before we start loading newer version.\n", " setTimeout(load_or_wait, 100)\n", "}(window));" ], "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n const force = false;\n const py_version = '3.7.3'.replace('rc', '-rc.').replace('.dev', '-dev.');\n const reloading = true;\n const Bokeh = root.Bokeh;\n\n // Set a timeout for this load but only if we are not already initializing\n if (typeof (root._bokeh_timeout) === \"undefined\" || (force || !root._bokeh_is_initializing)) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks;\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n if (js_exports == null) js_exports = {};\n\n root._bokeh_onload_callbacks.push(callback);\n\n if (root._bokeh_is_loading > 0) {\n // Don't load bokeh if it is still initializing\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n } else if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n // There is nothing to load\n run_callbacks();\n return null;\n }\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n window._bokeh_on_load = on_load\n\n function on_error(e) {\n const src_el = e.srcElement\n console.error(\"failed to load \" + (src_el.href || src_el.src));\n }\n\n const skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n root._bokeh_is_loading = css_urls.length + 0;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n }\n\n const existing_stylesheets = []\n const links = document.getElementsByTagName('link')\n for (let i = 0; i < links.length; i++) {\n const link = links[i]\n if (link.href != null) {\n existing_stylesheets.push(link.href)\n }\n }\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const escaped = encodeURI(url)\n if (existing_stylesheets.indexOf(escaped) !== -1) {\n on_load()\n continue;\n }\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n } var existing_scripts = []\n const scripts = document.getElementsByTagName('script')\n for (let i = 0; i < scripts.length; i++) {\n var script = scripts[i]\n if (script.src != null) {\n existing_scripts.push(script.src)\n }\n }\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (let i = 0; i < js_modules.length; i++) {\n const url = js_modules[i];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) !== -1 || existing_scripts.indexOf(escaped) !== -1) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (const name in js_exports) {\n const url = js_exports[name];\n const escaped = encodeURI(url)\n if (skip.indexOf(escaped) >= 0 || root[name] != null) {\n if (!window.requirejs) {\n on_load();\n }\n continue;\n }\n var element = document.createElement('script');\n element.onerror = on_error;\n element.async = false;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n element.textContent = `\n import ${name} from \"${url}\"\n window.${name} = ${name}\n window._bokeh_on_load()\n `\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n const js_urls = [\"https://cdn.holoviz.org/panel/1.7.5/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\"];\n const js_modules = [];\n const js_exports = {};\n const css_urls = [];\n const inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (let i = 0; i < inline_js.length; i++) {\n try {\n inline_js[i].call(root, root.Bokeh);\n } catch(e) {\n if (!reloading) {\n throw e;\n }\n }\n }\n // Cache old bokeh versions\n if (Bokeh != undefined && !reloading) {\n var NewBokeh = root.Bokeh;\n if (Bokeh.versions === undefined) {\n Bokeh.versions = new Map();\n }\n if (NewBokeh.version !== Bokeh.version) {\n Bokeh.versions.set(NewBokeh.version, NewBokeh)\n }\n root.Bokeh = Bokeh;\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n root._bokeh_is_initializing = false\n }\n\n function load_or_wait() {\n // Implement a backoff loop that tries to ensure we do not load multiple\n // versions of Bokeh and its dependencies at the same time.\n // In recent versions we use the root._bokeh_is_initializing flag\n // to determine whether there is an ongoing attempt to initialize\n // bokeh, however for backward compatibility we also try to ensure\n // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n // before older versions are fully initialized.\n if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n // If the timeout and bokeh was not successfully loaded we reset\n // everything and try loading again\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_is_initializing = false;\n root._bokeh_onload_callbacks = undefined;\n root._bokeh_is_loading = 0\n console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n load_or_wait();\n } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n setTimeout(load_or_wait, 100);\n } else {\n root._bokeh_is_initializing = true\n root._bokeh_onload_callbacks = []\n const bokeh_loaded = root.Bokeh != null && (root.Bokeh.version === py_version || (root.Bokeh.versions !== undefined && root.Bokeh.versions.has(py_version)));\n if (!reloading && !bokeh_loaded) {\n if (root.Bokeh) {\n root.Bokeh = undefined;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n }\n load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n }\n // Give older versions of the autoload script a head-start to ensure\n // they initialize before we start loading newer version.\n setTimeout(load_or_wait, 100)\n}(window));" }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", "}\n", "\n", "\n", " function JupyterCommManager() {\n", " }\n", "\n", " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", " comm_manager.register_target(comm_id, function(comm) {\n", " comm.on_msg(msg_handler);\n", " });\n", " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", " comm.onMsg = msg_handler;\n", " });\n", " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", " var messages = comm.messages[Symbol.asyncIterator]();\n", " function processIteratorResult(result) {\n", " var message = result.value;\n", " var content = {data: message.data, comm_id};\n", " var buffers = []\n", " for (var buffer of message.buffers || []) {\n", " buffers.push(new DataView(buffer))\n", " }\n", " var metadata = message.metadata || {};\n", " var msg = {content, buffers, metadata}\n", " msg_handler(msg);\n", " return messages.next().then(processIteratorResult);\n", " }\n", " return messages.next().then(processIteratorResult);\n", " })\n", " }\n", " }\n", "\n", " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", " if (comm_id in window.PyViz.comms) {\n", " return window.PyViz.comms[comm_id];\n", " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", " if (msg_handler) {\n", " comm.on_msg(msg_handler);\n", " }\n", " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", " let retries = 0;\n", " const open = () => {\n", " if (comm.active) {\n", " comm.open();\n", " } else if (retries > 3) {\n", " console.warn('Comm target never activated')\n", " } else {\n", " retries += 1\n", " setTimeout(open, 500)\n", " }\n", " }\n", " if (comm.active) {\n", " comm.open();\n", " } else {\n", " setTimeout(open, 500)\n", " }\n", " if (msg_handler) {\n", " comm.onMsg = msg_handler;\n", " }\n", " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", " comm_promise.then((comm) => {\n", " window.PyViz.comms[comm_id] = comm;\n", " if (msg_handler) {\n", " var messages = comm.messages[Symbol.asyncIterator]();\n", " function processIteratorResult(result) {\n", " var message = result.value;\n", " var content = {data: message.data};\n", " var metadata = message.metadata || {comm_id};\n", " var msg = {content, metadata}\n", " msg_handler(msg);\n", " return messages.next().then(processIteratorResult);\n", " }\n", " return messages.next().then(processIteratorResult);\n", " }\n", " })\n", " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", " return comm_promise.then((comm) => {\n", " comm.send(data, metadata, buffers, disposeOnDone);\n", " });\n", " };\n", " var comm = {\n", " send: sendClosure\n", " };\n", " }\n", " window.PyViz.comms[comm_id] = comm;\n", " return comm;\n", " }\n", " window.PyViz.comm_manager = new JupyterCommManager();\n", " \n", "\n", "\n", "var JS_MIME_TYPE = 'application/javascript';\n", "var HTML_MIME_TYPE = 'text/html';\n", "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", "var CLASS_NAME = 'output';\n", "\n", "/**\n", " * Render data to the DOM node\n", " */\n", "function render(props, node) {\n", " var div = document.createElement(\"div\");\n", " var script = document.createElement(\"script\");\n", " node.appendChild(div);\n", " node.appendChild(script);\n", "}\n", "\n", "/**\n", " * Handle when a new output is added\n", " */\n", "function handle_add_output(event, handle) {\n", " var output_area = handle.output_area;\n", " var output = handle.output;\n", " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", " return\n", " }\n", " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", " if (id !== undefined) {\n", " var nchildren = toinsert.length;\n", " var html_node = toinsert[nchildren-1].children[0];\n", " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", " var scripts = [];\n", " var nodelist = html_node.querySelectorAll(\"script\");\n", " for (var i in nodelist) {\n", " if (nodelist.hasOwnProperty(i)) {\n", " scripts.push(nodelist[i])\n", " }\n", " }\n", "\n", " scripts.forEach( function (oldScript) {\n", " var newScript = document.createElement(\"script\");\n", " var attrs = [];\n", " var nodemap = oldScript.attributes;\n", " for (var j in nodemap) {\n", " if (nodemap.hasOwnProperty(j)) {\n", " attrs.push(nodemap[j])\n", " }\n", " }\n", " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", " oldScript.parentNode.replaceChild(newScript, oldScript);\n", " });\n", " if (JS_MIME_TYPE in output.data) {\n", " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", " }\n", " output_area._hv_plot_id = id;\n", " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", " window.PyViz.plot_index[id] = Bokeh.index[id];\n", " } else {\n", " window.PyViz.plot_index[id] = null;\n", " }\n", " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", " var bk_div = document.createElement(\"div\");\n", " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", " var script_attrs = bk_div.children[0].attributes;\n", " for (var i = 0; i < script_attrs.length; i++) {\n", " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " }\n", " // store reference to server id on output_area\n", " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", " }\n", "}\n", "\n", "/**\n", " * Handle when an output is cleared or removed\n", " */\n", "function handle_clear_output(event, handle) {\n", " var id = handle.cell.output_area._hv_plot_id;\n", " var server_id = handle.cell.output_area._bokeh_server_id;\n", " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", " if (server_id !== null) {\n", " comm.send({event_type: 'server_delete', 'id': server_id});\n", " return;\n", " } else if (comm !== null) {\n", " comm.send({event_type: 'delete', 'id': id});\n", " }\n", " delete PyViz.plot_index[id];\n", " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", " var doc = window.Bokeh.index[id].model.document\n", " doc.clear();\n", " const i = window.Bokeh.documents.indexOf(doc);\n", " if (i > -1) {\n", " window.Bokeh.documents.splice(i, 1);\n", " }\n", " }\n", "}\n", "\n", "/**\n", " * Handle kernel restart event\n", " */\n", "function handle_kernel_cleanup(event, handle) {\n", " delete PyViz.comms[\"hv-extension-comm\"];\n", " window.PyViz.plot_index = {}\n", "}\n", "\n", "/**\n", " * Handle update_display_data messages\n", " */\n", "function handle_update_output(event, handle) {\n", " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", " handle_add_output(event, handle)\n", "}\n", "\n", "function register_renderer(events, OutputArea) {\n", " function append_mime(data, metadata, element) {\n", " // create a DOM node to render to\n", " var toinsert = this.create_output_subarea(\n", " metadata,\n", " CLASS_NAME,\n", " EXEC_MIME_TYPE\n", " );\n", " this.keyboard_manager.register_events(toinsert);\n", " // Render to node\n", " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", " render(props, toinsert[0]);\n", " element.append(toinsert);\n", " return toinsert\n", " }\n", "\n", " events.on('output_added.OutputArea', handle_add_output);\n", " events.on('output_updated.OutputArea', handle_update_output);\n", " events.on('clear_output.CodeCell', handle_clear_output);\n", " events.on('delete.Cell', handle_clear_output);\n", " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", "\n", " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", " safe: true,\n", " index: 0\n", " });\n", "}\n", "\n", "if (window.Jupyter !== undefined) {\n", " try {\n", " var events = require('base/js/events');\n", " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", " register_renderer(events, OutputArea);\n", " }\n", " } catch(err) {\n", " }\n", "}\n" ], "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n let retries = 0;\n const open = () => {\n if (comm.active) {\n comm.open();\n } else if (retries > 3) {\n console.warn('Comm target never activated')\n } else {\n retries += 1\n setTimeout(open, 500)\n }\n }\n if (comm.active) {\n comm.open();\n } else {\n setTimeout(open, 500)\n }\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n })\n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 5.95 s, sys: 302 ms, total: 6.25 s\n", "Wall time: 3.85 s\n" ] } ], "source": [ "%%time\n", "%matplotlib inline\n", "\n", "import importlib\n", "import new_import_ODC \n", "\n", "importlib.reload(new_import_ODC)\n", "\n", "from new_import_ODC import *" ] }, { "cell_type": "code", "execution_count": 2, "id": "d824dc4f-994b-4d1c-8d24-ce6674da141c", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:35:57.474638Z", "iopub.status.busy": "2026-07-15T08:35:57.474260Z", "iopub.status.idle": "2026-07-15T08:35:57.710305Z", "shell.execute_reply": "2026-07-15T08:35:57.709420Z" }, "tags": [] }, "outputs": [ { "ename": "ValueError", "evalue": "No dask-gateway address provided or found in configuration", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "File \u001b[0;32m:2\u001b[0m\n", "File \u001b[0;32m~/CSIROBoeingPhase4-Vietnam/easi_tools/notebook_utils.py:123\u001b[0m, in \u001b[0;36minitialize_dask\u001b[0;34m(use_gateway, workers, wait, local_port, **kwargs)\u001b[0m\n\u001b[1;32m 121\u001b[0m \u001b[38;5;66;03m# Dask gateway\u001b[39;00m\n\u001b[1;32m 122\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m use_gateway:\n\u001b[0;32m--> 123\u001b[0m gateway \u001b[38;5;241m=\u001b[39m \u001b[43mGateway\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 124\u001b[0m clusters \u001b[38;5;241m=\u001b[39m gateway\u001b[38;5;241m.\u001b[39mlist_clusters()\n\u001b[1;32m 125\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m clusters:\n", "File \u001b[0;32m~/miniconda3/envs/env_01/lib/python3.10/site-packages/dask_gateway/client.py:282\u001b[0m, in \u001b[0;36mGateway.__init__\u001b[0;34m(self, address, proxy_address, public_address, auth, asynchronous, loop)\u001b[0m\n\u001b[1;32m 280\u001b[0m address \u001b[38;5;241m=\u001b[39m format_template(dask\u001b[38;5;241m.\u001b[39mconfig\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgateway.address\u001b[39m\u001b[38;5;124m\"\u001b[39m))\n\u001b[1;32m 281\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m address \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m--> 282\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 283\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNo dask-gateway address provided or found in configuration\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 284\u001b[0m )\n\u001b[1;32m 285\u001b[0m address \u001b[38;5;241m=\u001b[39m address\u001b[38;5;241m.\u001b[39mrstrip(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 287\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m public_address \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", "\u001b[0;31mValueError\u001b[0m: No dask-gateway address provided or found in configuration" ] } ], "source": [ "%%time\n", "# Cấu hình Daskgateway\n", "cluster, client = notebook_utils.initialize_dask(use_gateway=True, workers=(1, 10))\n", "# Khai báo 1 Datacube là dc\n", "dc = None\n", "\n", "# Cấu hình truy cập dịch vụ S3\n", "configure_s3_access(aws_unsigned=False, requester_pays=True, client=client)\n", "\n", "client" ] }, { "cell_type": "code", "execution_count": 3, "id": "fbed4c80-bbf8-4ea8-aa45-2460b2ba04c7", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:35:57.712287Z", "iopub.status.busy": "2026-07-15T08:35:57.712110Z", "iopub.status.idle": "2026-07-15T08:35:57.716910Z", "shell.execute_reply": "2026-07-15T08:35:57.716295Z" }, "tags": [] }, "outputs": [], "source": [ "## cấu hình thời gian lấy ảnh và tọa độ\n", "date_range = (\"2022-09-01\", \"2022-10-01\")\n", "longtitude_range = (105.86, 105.94)\n", "latitude_range = (9.65, 9.69)\n", "\n", "coordinates = (longtitude_range, latitude_range)" ] }, { "cell_type": "code", "execution_count": 4, "id": "6b90c49b-0665-4478-a23b-d111ef88eb79", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:35:57.718481Z", "iopub.status.busy": "2026-07-15T08:35:57.718326Z", "iopub.status.idle": "2026-07-15T08:35:59.842220Z", "shell.execute_reply": "2026-07-15T08:35:59.841686Z" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "

Dataset size: 0.00 MB

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 4kB\n",
       "Dimensions:      (y: 6, x: 10, time: 6)\n",
       "Coordinates:\n",
       "  * y            (y) float64 48B 1.072e+06 1.07e+06 ... 1.068e+06 1.066e+06\n",
       "  * x            (x) float64 80B 5.945e+05 5.955e+05 ... 6.025e+05 6.035e+05\n",
       "    spatial_ref  int32 4B 32648\n",
       "  * time         (time) datetime64[ns] 48B 2022-09-02T03:15:31.024000 ... 202...\n",
       "Data variables:\n",
       "    red          (time, y, x) float32 1kB dask.array<chunksize=(1, 6, 10), meta=np.ndarray>\n",
       "    nir          (time, y, x) float32 1kB dask.array<chunksize=(1, 6, 10), meta=np.ndarray>\n",
       "    scl          (time, y, x) float32 1kB dask.array<chunksize=(1, 6, 10), meta=np.ndarray>
" ], "text/plain": [ " Size: 4kB\n", "Dimensions: (y: 6, x: 10, time: 6)\n", "Coordinates:\n", " * y (y) float64 48B 1.072e+06 1.07e+06 ... 1.068e+06 1.066e+06\n", " * x (x) float64 80B 5.945e+05 5.955e+05 ... 6.025e+05 6.035e+05\n", " spatial_ref int32 4B 32648\n", " * time (time) datetime64[ns] 48B 2022-09-02T03:15:31.024000 ... 202...\n", "Data variables:\n", " red (time, y, x) float32 1kB dask.array\n", " nir (time, y, x) float32 1kB dask.array\n", " scl (time, y, x) float32 1kB dask.array" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "## truy vấn ảnh vệ tinh sen2\n", "data = load_data(None, date_range, longtitude_range, latitude_range)\n", "notebook_utils.heading(notebook_utils.xarray_object_size(data))\n", "display(data)" ] }, { "cell_type": "code", "execution_count": 5, "id": "2f6938b6-82e2-4916-bc1d-719c169e25e4", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:35:59.843704Z", "iopub.status.busy": "2026-07-15T08:35:59.843542Z", "iopub.status.idle": "2026-07-15T08:36:18.128895Z", "shell.execute_reply": "2026-07-15T08:36:18.128075Z" }, "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/x79/miniconda3/envs/env_01/lib/python3.10/site-packages/rasterio/warp.py:387: NotGeoreferencedWarning: Dataset has no geotransform, gcps, or rpcs. The identity matrix will be returned.\n", " dest = _reproject(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 2.79 s, sys: 86.4 ms, total: 2.88 s\n", "Wall time: 18.3 s\n" ] } ], "source": [ "%%time\n", "# Tiến hành loại bỏ các vị trí bị mây ảnh hưởng\n", "result = mask_clean(data)\n", "# progress(result)" ] }, { "cell_type": "code", "execution_count": 6, "id": "435f9f78-a9a4-4226-86ca-d4bec42d454e", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:36:18.130662Z", "iopub.status.busy": "2026-07-15T08:36:18.130484Z", "iopub.status.idle": "2026-07-15T08:36:18.147842Z", "shell.execute_reply": "2026-07-15T08:36:18.147222Z" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'NDVI' (time: 6, y: 6, x: 10)> Size: 1kB\n",
       "dask.array<truediv, shape=(6, 6, 10), dtype=float32, chunksize=(1, 6, 10), chunktype=numpy.ndarray>\n",
       "Coordinates:\n",
       "  * y            (y) float64 48B 1.072e+06 1.07e+06 ... 1.068e+06 1.066e+06\n",
       "  * x            (x) float64 80B 5.945e+05 5.955e+05 ... 6.025e+05 6.035e+05\n",
       "    spatial_ref  int32 4B 32648\n",
       "  * time         (time) datetime64[ns] 48B 2022-09-02T03:15:31.024000 ... 202...
" ], "text/plain": [ " Size: 1kB\n", "dask.array\n", "Coordinates:\n", " * y (y) float64 48B 1.072e+06 1.07e+06 ... 1.068e+06 1.066e+06\n", " * x (x) float64 80B 5.945e+05 5.955e+05 ... 6.025e+05 6.035e+05\n", " spatial_ref int32 4B 32648\n", " * time (time) datetime64[ns] 48B 2022-09-02T03:15:31.024000 ... 202..." ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Tiến hành tính toán NDVI\n", "ds1 = calculate_indices(result, index=\"NDVI\", satellite_mission=\"s2\")\n", "ndvi = ds1[\"NDVI\"]\n", "display(ndvi)" ] }, { "cell_type": "code", "execution_count": 7, "id": "84992d28-8e3f-468e-be08-ded511f2c662", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:36:18.149488Z", "iopub.status.busy": "2026-07-15T08:36:18.149321Z", "iopub.status.idle": "2026-07-15T08:36:18.227530Z", "shell.execute_reply": "2026-07-15T08:36:18.226784Z" }, "tags": [] }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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LPL5fHzlK1+JfD5f71EI92M4cS+GD/di+HAv0hvyhzcBgJFrxK1YAAD1IywAgGSEBQCQjLAAAJIZcWGxadOmaGlpifHjx8eCBQviiSeeqPdIo065XI5rr702mpubY8qUKbFixYp47rnn6j0W8b/3JpfLxbp16+o9yqj1j3/8Iz7xiU/E5MmT45JLLomrr7469u/fX++xRp0zZ87El7/85WhpaYkJEybE5ZdfHnfffXecPXu23qM1vBEVFtu3b49169bFhg0b4sCBA3H99dfH8uXL4/Dhw/UebVTp6uqKtra22LNnT3R2dsaZM2eitbU1Tp06Ve/RRrW9e/dGR0dHzJs3r96jjFr/+te/4rrrros3velN8dhjj8Vf/vKX+Pa3vx1vectb6j3aqPPNb34zfvCDH8TGjRvj2WefjW9961tx3333xfe+9716j9bwRtSfmy5atCjmz58fmzdv7ts3e/bsWLFiRZTL5TpONrq98sorMWXKlOjq6oobbrih3uOMSidPnoz58+fHpk2b4utf/3pcffXV8d3vfrfeY406d955Z/zhD3+wkjoMfOADH4ipU6fG/fff37fvwx/+cFxyySXx05/+tI6TNb4Rs2Jx+vTp2L9/f7S2tvbb39raGk8++WSdpiIioqenJyIiJk2aVOdJRq+2tra46aabYtmyZfUeZVTbsWNHLFy4MD760Y/GlClT4pprroktW7bUe6xRaenSpfG73/0unn/++YiI+NOf/hS7d++O97///XWerPEN+ZeQDZbjx49Hb29vTJ06td/+qVOnxtGjR+s0FVmWRXt7eyxdujTmzp1b73FGpW3btsXTTz8de/furfcoo96LL74Ymzdvjvb29rjrrrviqaeeis997nORz+fjk5/8ZL3HG1XuuOOO6OnpiVmzZkVTU1P09vbGPffcE7feemu9R2t4IyYsXvP/v4o9y7JB+Xp2Lsztt98ef/7zn2P37t31HmVU6u7ujrVr18ZvfvObGD9+fL3HGfXOnj0bCxcujHvvvTciIq655pp45plnYvPmzcJiiG3fvj0efPDB2Lp1a8yZMycOHjwY69ati2nTpsWqVavqPV5DGzFhcemll0ZTU9PrVieOHTv2ulUMhsaaNWtix44dsWvXrpg+fXq9xxmV9u/fH8eOHYsFCxb07evt7Y1du3bFxo0bo1qtRlNTUx0nHF0uu+yyuPLKK/vtmz17djz00EN1mmj0+uIXvxh33nln3HLLLRERcdVVV8Xf/va3KJfLwuIijZhnLMaNGxcLFiyIzs7Ofvs7OztjyZIldZpqdMqyLG6//fb4+c9/Hr///e+jpaWl3iONWjfeeGMcOnQoDh482LctXLgwbrvttjh48KCoGGLXXXfd6/70+vnnn4+ZM2fWaaLR6z//+U+MGdP/JbCpqcmfmyYwYlYsIiLa29tj5cqVsXDhwli8eHF0dHTE4cOHY/Xq1fUebVRpa2uLrVu3xqOPPhrNzc19q0jFYjEmTJhQ5+lGl+bm5tc92zJx4sSYPHmyZ17q4POf/3wsWbIk7r333vjYxz4WTz31VHR0dERHR0e9Rxt1br755rjnnntixowZMWfOnDhw4EB85zvfic985jP1Hq3xZSPM97///WzmzJnZuHHjsvnz52ddXV31HmnUiYhzbg888EC9RyPLsne9613Z2rVr6z3GqPWLX/wimzt3bpbP57NZs2ZlHR0d9R5pVKpUKtnatWuzGTNmZOPHj88uv/zybMOGDVm1Wq33aA1vRH2OBQBQXyPmGQsAoP6EBQCQjLAAAJIRFgBAMsICAEhGWAAAyQgLACAZYQEAJCMsAIBkhAUAkIywAACSERYAQDL/A8CnlMwofga8AAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "## Hiển thị ảnh NDVI chưa điền các giá trị mây (chưa fill nan)\n", "plt.imshow(ndvi.isel(time=0))" ] }, { "cell_type": "code", "execution_count": 8, "id": "72318b60-532a-4f08-a5f7-94762d08a42c", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:36:18.229489Z", "iopub.status.busy": "2026-07-15T08:36:18.229316Z", "iopub.status.idle": "2026-07-15T08:36:18.308460Z", "shell.execute_reply": "2026-07-15T08:36:18.307750Z" }, "tags": [] }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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VFdX9z1qampO95QAwBB32mGxfPny2Lt3b3zve9/7p8e1tLREd3d336Orq+t0TwkADHGn9aWQFStWxObNm2P79u0xZcqUf3psLpeLXC53WuMAgNJSVFgUCoVYsWJF3H///bF169aora0drF0AQAkqKiyamppiw4YN8cADD0RVVVUcPHgwIiKqq6tjzJgxgzIQACgdRd1j0dbWFt3d3XHllVfGeeed1/fYtGnTYO0DAEpI0V8KAQA4FT8rBABIRlgAAMkICwAgGWEBACQjLACAZIQFAJCMsAAAkhEWAEAywgIASEZYAADJCAsAIBlhAQAkIywAgGSEBQCQjLAAAJIRFgBAMsICAEhmVFYnrvhLeZQXSrdrJuwty3pCEuf8n66sJyTx0remZj1hwJ5rnZf1BIaZXY13Zj2Bv9l98casJwxYz5ETcc4bOK50/2QHAIYcYQEAJCMsAIBkhAUAkIywAACSERYAQDLCAgBIRlgAAMkICwAgGWEBACQjLACAZIQFAJCMsAAAkhEWAEAywgIASEZYAADJCAsAIBlhAQAkIywAgGSEBQCQTFFh0dbWFnPmzIlx48bFuHHjYt68efHggw8O1jYAoMQUFRZTpkyJL3zhC7Fr167YtWtXvPvd7473v//98fjjjw/WPgCghIwq5uBFixb1e75mzZpoa2uLHTt2xMyZM5MOAwBKT1Fh8fd6e3vj+9//fhw7dizmzZt3yuPy+Xzk8/m+5z09Pad7SgBgiCv65s19+/bFm970psjlcrFs2bK4//7744ILLjjl8a2trVFdXd33qKmpGdBgAGDoKjos3v72t8eePXtix44d8clPfjKWLl0aTzzxxCmPb2lpie7u7r5HV1fXgAYDAENX0V8KGT16dLztbW+LiIj6+vrYuXNnfPWrX41vfvObr3l8LpeLXC43sJUAQEkY8PexKBQK/e6hAABGrqKuWNx2223R2NgYNTU1ceTIkdi4cWNs3bo1tmzZMlj7AIASUlRY/OlPf4olS5bECy+8ENXV1TFnzpzYsmVLvOc97xmsfQBACSkqLO65557B2gEADAN+VggAkIywAACSERYAQDLCAgBIRlgAAMkICwAgGWEBACQjLACAZIQFAJCMsAAAkhEWAEAywgIASEZYAADJCAsAIBlhAQAkIywAgGSEBQCQjLAAAJIZldWJ9y5fEePGjcvq9AwzN1Vfm/WEAXv8/16Q9YQ0bsl6AAw95W99JusJA1Z+dk9EVL/+cYM/BQAYKYQFAJCMsAAAkhEWAEAywgIASEZYAADJCAsAIBlhAQAkIywAgGSEBQCQjLAAAJIRFgBAMsICAEhGWAAAyQgLACAZYQEAJCMsAIBkhAUAkIywAACSERYAQDIDCovW1tYoKyuLVatWJZoDAJSy0w6LnTt3Rnt7e8yZMyflHgCghJ1WWBw9ejRuuOGGWL9+fZxzzjmpNwEAJeq0wqKpqSmuvvrqWLhw4esem8/no6enp98DABieRhX7ho0bN8Zjjz0WO3fufEPHt7a2xuc+97mihwEApaeoKxZdXV2xcuXKuO+++6KysvINvaelpSW6u7v7Hl1dXac1FAAY+oq6YtHZ2RmHDh2Kurq6vtd6e3tj+/btsXbt2sjn81FRUdHvPblcLnK5XJq1AMCQVlRYXHXVVbFv375+r330ox+N6dOnxy233HJSVAAAI0tRYVFVVRWzZs3q99rYsWNjwoQJJ70OAIw8vvMmAJBM0X8r5B9t3bo1wQwAYDhwxQIASEZYAADJCAsAIBlhAQAkIywAgGSEBQCQjLAAAJIRFgBAMsICAEhGWAAAyQgLACAZYQEAJCMsAIBkhAUAkIywAACSERYAQDLCAgBIZlRWJ774s1+PilxlVqcfsCdab8p6An/nPy7alPWEAXvn//5K1hP4m3nX/nvWE5L4zaabs56QxDeeuiLrCQP2wwtrsp4wYMcLf31Dx7liAQAkIywAgGSEBQCQjLAAAJIRFgBAMsICAEhGWAAAyQgLACAZYQEAJCMsAIBkhAUAkIywAACSERYAQDLCAgBIRlgAAMkICwAgGWEBACQjLACAZIQFAJCMsAAAkikqLD772c9GWVlZv8db3/rWwdoGAJSYUcW+YebMmfGLX/yi73lFRUXSQQBA6So6LEaNGuUqBQDwmoq+x+KZZ56JyZMnR21tbVx33XXx7LPP/tPj8/l89PT09HsAAMNTUWFxySWXxHe+85342c9+FuvXr4+DBw/G/Pnz48UXXzzle1pbW6O6urrvUVNTM+DRAMDQVFRYNDY2xjXXXBOzZ8+OhQsXxk9+8pOIiPj2t799yve0tLREd3d336Orq2tgiwGAIavoeyz+3tixY2P27NnxzDPPnPKYXC4XuVxuIKcBAErEgL6PRT6fjyeffDLOO++8VHsAgBJWVFjcfPPNsW3btnjuuefit7/9bXzgAx+Inp6eWLp06WDtAwBKSFFfCnn++efj+uuvj8OHD8db3vKWeOc73xk7duyIadOmDdY+AKCEFBUWGzduHKwdAMAw4GeFAADJCAsAIBlhAQAkIywAgGSEBQCQjLAAAJIRFgBAMsICAEhGWAAAyQgLACAZYQEAJCMsAIBkhAUAkIywAACSERYAQDLCAgBIRlgAAMmMOtMnLBQKERHRm/+vM33qpHp6erKewDBz/K+l/XviVcPh94bPYmj5y9HjWU8YsOOFv2Y9YcBe/W949c/xUykrvN4RiT3//PNRU1NzJk8JACTS1dUVU6ZMOeU/P+NhceLEiThw4EBUVVVFWVlZ8n9/T09P1NTURFdXV4wbNy75v5/i+DyGDp/F0OGzGDp8Fm9coVCII0eOxOTJk6O8/NR3UpzxL4WUl5f/09JJZdy4cX6RDCE+j6HDZzF0+CyGDp/FG1NdXf26x7h5EwBIRlgAAMkMu7DI5XLxmc98JnK5XNZTCJ/HUOKzGDp8FkOHzyK9M37zJgAwfA27KxYAQHaEBQCQjLAAAJIRFgBAMsMuLNatWxe1tbVRWVkZdXV18dBDD2U9acRpbW2Niy++OKqqqmLixImxePHieOqpp7KeRfzPZ1NWVharVq3KesqI9cc//jE+/OEPx4QJE+Lss8+OCy+8MDo7O7OeNeIcP348br/99qitrY0xY8bE+eefH3fccUecOHEi62klb1iFxaZNm2LVqlWxevXq2L17d1x22WXR2NgY+/fvz3raiLJt27ZoamqKHTt2REdHRxw/fjwaGhri2LFjWU8b0Xbu3Bnt7e0xZ86crKeMWC+99FJceumlcdZZZ8WDDz4YTzzxRHzlK1+JN7/5zVlPG3G++MUvxje+8Y1Yu3ZtPPnkk/GlL30pvvzlL8fXvva1rKeVvGH1100vueSSmDt3brS1tfW9NmPGjFi8eHG0trZmuGxk+/Of/xwTJ06Mbdu2xeWXX571nBHp6NGjMXfu3Fi3bl18/vOfjwsvvDDuvvvurGeNOLfeemv8+te/diV1CHjf+94XkyZNinvuuafvtWuuuSbOPvvs+O53v5vhstI3bK5YvPLKK9HZ2RkNDQ39Xm9oaIhHHnkko1VERHR3d0dExPjx4zNeMnI1NTXF1VdfHQsXLsx6yoi2efPmqK+vjw9+8IMxceLEuOiii2L9+vVZzxqRFixYEL/85S/j6aefjoiI3/3ud/Hwww/He9/73oyXlb4z/kPIBsvhw4ejt7c3Jk2a1O/1SZMmxcGDBzNaRaFQiObm5liwYEHMmjUr6zkj0saNG+Oxxx6LnTt3Zj1lxHv22Wejra0tmpub47bbbotHH300PvWpT0Uul4uPfOQjWc8bUW655Zbo7u6O6dOnR0VFRfT29saaNWvi+uuvz3payRs2YfGqf/xR7IVCYVB+PDtvzPLly2Pv3r3x8MMPZz1lROrq6oqVK1fGz3/+86isrMx6zoh34sSJqK+vjzvvvDMiIi666KJ4/PHHo62tTVicYZs2bYr77rsvNmzYEDNnzow9e/bEqlWrYvLkybF06dKs55W0YRMW5557blRUVJx0deLQoUMnXcXgzFixYkVs3rw5tm/fHlOmTMl6zojU2dkZhw4dirq6ur7Xent7Y/v27bF27drI5/NRUVGR4cKR5bzzzosLLrig32szZsyIH/zgBxktGrk+/elPx6233hrXXXddRETMnj07/vCHP0Rra6uwGKBhc4/F6NGjo66uLjo6Ovq93tHREfPnz89o1chUKBRi+fLl8cMf/jB+9atfRW1tbdaTRqyrrroq9u3bF3v27Ol71NfXxw033BB79uwRFWfYpZdeetJfvX766adj2rRpGS0auV5++eUoL+//R2BFRYW/bprAsLliERHR3NwcS5Ysifr6+pg3b160t7fH/v37Y9myZVlPG1Gamppiw4YN8cADD0RVVVXfVaTq6uoYM2ZMxutGlqqqqpPubRk7dmxMmDDBPS8ZuOmmm2L+/Plx5513xoc+9KF49NFHo729Pdrb27OeNuIsWrQo1qxZE1OnTo2ZM2fG7t2746677oqPfexjWU8rfYVh5utf/3ph2rRphdGjRxfmzp1b2LZtW9aTRpyIeM3Hvffem/U0CoXCFVdcUVi5cmXWM0asH//4x4VZs2YVcrlcYfr06YX29vasJ41IPT09hZUrVxamTp1aqKysLJx//vmF1atXF/L5fNbTSt6w+j4WAEC2hs09FgBA9oQFAJCMsAAAkhEWAEAywgIASEZYAADJCAsAIBlhAQAkIywAgGSEBQCQjLAAAJIRFgBAMv8N4Wt+dwko4tcAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Thiết lập giá trị trung bình mùa vụ để xử lý các điểm ảnh bị mây dựa vào sự thay đổi theo mùa\n", "time_split = [\n", " slice(\"2022-09-01\", \"2023-01-01\"),\n", " slice(\"2023-01-01\", \"2023-05-01\"),\n", " slice(\"2023-05-01\", \"2023-07-01\"),\n", " slice(\"2023-07-01\", \"2022-10-01\"),\n", "]\n", "\n", "# Điền mây ở các vị trí mang giá trị nan (fill nan)\n", "fill_nan_ndvi = fill_nan(ndvi, time_split)\n", "\n", "# In kết quả ảnh NDVI đã điền mây (đã fill nan)\n", "plt.imshow(fill_nan_ndvi.isel(time=0))" ] }, { "cell_type": "code", "execution_count": 9, "id": "375b1cfb-37f5-49fe-8061-ea32eb47f9f6", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:36:18.310580Z", "iopub.status.busy": "2026-07-15T08:36:18.310399Z", "iopub.status.idle": "2026-07-15T08:36:18.334258Z", "shell.execute_reply": "2026-07-15T08:36:18.333726Z" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 17.3 ms, sys: 4.13 ms, total: 21.4 ms\n", "Wall time: 20.5 ms\n" ] } ], "source": [ "%%time\n", "## tính ndvi theo tháng\n", "average_ndvi = fill_nan_ndvi.resample(time=\"1M\").mean().persist()\n", "# progress(average_ndvi)\n", "\n", "# compute average_ndvi\n", "average_ndvi = average_ndvi.compute()" ] }, { "cell_type": "code", "execution_count": 10, "id": "187cc640-aef9-476b-91fc-b63f4d3ff2e3", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:36:18.335779Z", "iopub.status.busy": "2026-07-15T08:36:18.335624Z", "iopub.status.idle": "2026-07-15T08:36:59.853587Z", "shell.execute_reply": "2026-07-15T08:36:59.852937Z" }, "tags": [] }, "outputs": [], "source": [ "#Load dữ liệu ảnh Sentinel 1\n", "dsvh, dsvv = load_data_sen1(None, date_range, coordinates)\n", "average_vv = calculate_average(dsvv, time_pattern='1M')\n", "average_vh = calculate_average(dsvh, time_pattern='1M')" ] }, { "cell_type": "code", "execution_count": 11, "id": "d2585562-88aa-4c7d-bf70-1f6affcf65d4", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:36:59.855904Z", "iopub.status.busy": "2026-07-15T08:36:59.855678Z", "iopub.status.idle": "2026-07-15T08:37:03.673004Z", "shell.execute_reply": "2026-07-15T08:37:03.671853Z" }, "tags": [] }, "outputs": [], "source": [ "## cấu hình bộ dữ liệu điểm huấn luyện mô hình (train file)\n", "train_path = \"train/ST_training_data_updated_1130points_new.shp\" # đường dẫn shp file train\n", "\n", "## load dữ liệu điểm huấn luyện mô hình (train file)\n", "train = load_train_data(train_path)\n", "train.head()\n", "\n", "# cấu hình nhãn dữ liệu \n", "label_mapping = {\n", " \"Lua tom\": \"0\",\n", " \"Lua\": \"1\",\n", " \"CHN\": \"2\",\n", " \"CLN\": \"3\",\n", " \"TS\": \"4\",\n", " \"Song\": \"5\",\n", " \"Dat xay dung\": \"6\",\n", " \"Rung\": \"7\",\n", "}\n", "\n", "# xây dựng tập dữ liệu (dataset) chứa dữ liệu VH, VV, NDVI\n", "datasets = get_data_sen1_and_sen2(train, average_ndvi, average_vh, average_vv)\n", "\n", "# chia tập dữ liệu thành các phần theo tỉ lệ 80(80-20)-20 tương ứng với tập train, validate, test\n", "X_train, X_val, X_test, y_train, y_val, y_test = split_train_data(\n", " train, label_mapping, datasets\n", ")" ] }, { "cell_type": "code", "execution_count": 12, "id": "2e955884-d4af-422d-a8e6-d436199540e0", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:37:03.676506Z", "iopub.status.busy": "2026-07-15T08:37:03.675590Z", "iopub.status.idle": "2026-07-15T08:37:04.462590Z", "shell.execute_reply": "2026-07-15T08:37:04.462192Z" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "🚀 Training XGBoost model...\n", " Train samples: 678\n", " Val samples: 226\n", " Features: 3\n", " Classes: 8\n", "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-mlogloss:1.95483\tvalidation_1-mlogloss:1.96073\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[1]\tvalidation_0-mlogloss:1.92087\tvalidation_1-mlogloss:1.92814\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[2]\tvalidation_0-mlogloss:1.89031\tvalidation_1-mlogloss:1.90002\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[3]\tvalidation_0-mlogloss:1.86393\tvalidation_1-mlogloss:1.87377\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[4]\tvalidation_0-mlogloss:1.83996\tvalidation_1-mlogloss:1.85343\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[5]\tvalidation_0-mlogloss:1.81876\tvalidation_1-mlogloss:1.83444\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[6]\tvalidation_0-mlogloss:1.79859\tvalidation_1-mlogloss:1.81677\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[7]\tvalidation_0-mlogloss:1.78094\tvalidation_1-mlogloss:1.80011\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[8]\tvalidation_0-mlogloss:1.76452\tvalidation_1-mlogloss:1.78688\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[9]\tvalidation_0-mlogloss:1.74895\tvalidation_1-mlogloss:1.77440\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[10]\tvalidation_0-mlogloss:1.73571\tvalidation_1-mlogloss:1.76218\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[11]\tvalidation_0-mlogloss:1.72386\tvalidation_1-mlogloss:1.75144\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[12]\tvalidation_0-mlogloss:1.71263\tvalidation_1-mlogloss:1.74264\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[13]\tvalidation_0-mlogloss:1.70164\tvalidation_1-mlogloss:1.73356\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[14]\tvalidation_0-mlogloss:1.69171\tvalidation_1-mlogloss:1.72490\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[15]\tvalidation_0-mlogloss:1.68265\tvalidation_1-mlogloss:1.71686\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[16]\tvalidation_0-mlogloss:1.67386\tvalidation_1-mlogloss:1.71012\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[17]\tvalidation_0-mlogloss:1.66649\tvalidation_1-mlogloss:1.70439\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[18]\tvalidation_0-mlogloss:1.65950\tvalidation_1-mlogloss:1.69962\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[19]\tvalidation_0-mlogloss:1.65303\tvalidation_1-mlogloss:1.69538\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[20]\tvalidation_0-mlogloss:1.64703\tvalidation_1-mlogloss:1.69020\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[21]\tvalidation_0-mlogloss:1.64221\tvalidation_1-mlogloss:1.68647\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[22]\tvalidation_0-mlogloss:1.63713\tvalidation_1-mlogloss:1.68324\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[23]\tvalidation_0-mlogloss:1.63253\tvalidation_1-mlogloss:1.67972\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[24]\tvalidation_0-mlogloss:1.62839\tvalidation_1-mlogloss:1.67632\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[25]\tvalidation_0-mlogloss:1.62433\tvalidation_1-mlogloss:1.67320\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[26]\tvalidation_0-mlogloss:1.62059\tvalidation_1-mlogloss:1.67095\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[27]\tvalidation_0-mlogloss:1.61661\tvalidation_1-mlogloss:1.66756\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[28]\tvalidation_0-mlogloss:1.61328\tvalidation_1-mlogloss:1.66565\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[29]\tvalidation_0-mlogloss:1.61027\tvalidation_1-mlogloss:1.66265\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[30]\tvalidation_0-mlogloss:1.60735\tvalidation_1-mlogloss:1.66160\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[31]\tvalidation_0-mlogloss:1.60471\tvalidation_1-mlogloss:1.66025\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[32]\tvalidation_0-mlogloss:1.60240\tvalidation_1-mlogloss:1.65951\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[33]\tvalidation_0-mlogloss:1.59991\tvalidation_1-mlogloss:1.65837\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[34]\tvalidation_0-mlogloss:1.59732\tvalidation_1-mlogloss:1.65768\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[35]\tvalidation_0-mlogloss:1.59507\tvalidation_1-mlogloss:1.65727\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[36]\tvalidation_0-mlogloss:1.59273\tvalidation_1-mlogloss:1.65634\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[37]\tvalidation_0-mlogloss:1.59080\tvalidation_1-mlogloss:1.65556\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[38]\tvalidation_0-mlogloss:1.58892\tvalidation_1-mlogloss:1.65467\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[39]\tvalidation_0-mlogloss:1.58688\tvalidation_1-mlogloss:1.65399\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[40]\tvalidation_0-mlogloss:1.58512\tvalidation_1-mlogloss:1.65417\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[41]\tvalidation_0-mlogloss:1.58367\tvalidation_1-mlogloss:1.65361\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[42]\tvalidation_0-mlogloss:1.58226\tvalidation_1-mlogloss:1.65339\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[43]\tvalidation_0-mlogloss:1.58079\tvalidation_1-mlogloss:1.65323\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[44]\tvalidation_0-mlogloss:1.57952\tvalidation_1-mlogloss:1.65320\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[45]\tvalidation_0-mlogloss:1.57816\tvalidation_1-mlogloss:1.65251\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[46]\tvalidation_0-mlogloss:1.57677\tvalidation_1-mlogloss:1.65180\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[47]\tvalidation_0-mlogloss:1.57551\tvalidation_1-mlogloss:1.65133\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[48]\tvalidation_0-mlogloss:1.57426\tvalidation_1-mlogloss:1.65098\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[49]\tvalidation_0-mlogloss:1.57330\tvalidation_1-mlogloss:1.65050\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[50]\tvalidation_0-mlogloss:1.57220\tvalidation_1-mlogloss:1.64965\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[51]\tvalidation_0-mlogloss:1.57119\tvalidation_1-mlogloss:1.64947\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[52]\tvalidation_0-mlogloss:1.57026\tvalidation_1-mlogloss:1.65082\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[53]\tvalidation_0-mlogloss:1.56933\tvalidation_1-mlogloss:1.65114\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[54]\tvalidation_0-mlogloss:1.56859\tvalidation_1-mlogloss:1.65098\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[55]\tvalidation_0-mlogloss:1.56780\tvalidation_1-mlogloss:1.65063\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[56]\tvalidation_0-mlogloss:1.56690\tvalidation_1-mlogloss:1.65014\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[57]\tvalidation_0-mlogloss:1.56616\tvalidation_1-mlogloss:1.65095\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[58]\tvalidation_0-mlogloss:1.56535\tvalidation_1-mlogloss:1.65157\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[59]\tvalidation_0-mlogloss:1.56460\tvalidation_1-mlogloss:1.65074\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[60]\tvalidation_0-mlogloss:1.56372\tvalidation_1-mlogloss:1.65103\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[61]\tvalidation_0-mlogloss:1.56306\tvalidation_1-mlogloss:1.65143\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[62]\tvalidation_0-mlogloss:1.56250\tvalidation_1-mlogloss:1.65260\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[63]\tvalidation_0-mlogloss:1.56185\tvalidation_1-mlogloss:1.65247\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[64]\tvalidation_0-mlogloss:1.56133\tvalidation_1-mlogloss:1.65174\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[65]\tvalidation_0-mlogloss:1.56076\tvalidation_1-mlogloss:1.65277\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[66]\tvalidation_0-mlogloss:1.56010\tvalidation_1-mlogloss:1.65450\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[67]\tvalidation_0-mlogloss:1.55951\tvalidation_1-mlogloss:1.65500\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[68]\tvalidation_0-mlogloss:1.55902\tvalidation_1-mlogloss:1.65662\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[69]\tvalidation_0-mlogloss:1.55846\tvalidation_1-mlogloss:1.65779\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[70]\tvalidation_0-mlogloss:1.55798\tvalidation_1-mlogloss:1.65753\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[71]\tvalidation_0-mlogloss:1.55742\tvalidation_1-mlogloss:1.65760\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[72]\tvalidation_0-mlogloss:1.55702\tvalidation_1-mlogloss:1.65835\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[73]\tvalidation_0-mlogloss:1.55657\tvalidation_1-mlogloss:1.65979\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[74]\tvalidation_0-mlogloss:1.55613\tvalidation_1-mlogloss:1.66085\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[75]\tvalidation_0-mlogloss:1.55568\tvalidation_1-mlogloss:1.66123\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[76]\tvalidation_0-mlogloss:1.55538\tvalidation_1-mlogloss:1.66156\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[77]\tvalidation_0-mlogloss:1.55505\tvalidation_1-mlogloss:1.66268\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[78]\tvalidation_0-mlogloss:1.55467\tvalidation_1-mlogloss:1.66394\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[79]\tvalidation_0-mlogloss:1.55428\tvalidation_1-mlogloss:1.66422\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[80]\tvalidation_0-mlogloss:1.55390\tvalidation_1-mlogloss:1.66398\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[81]\tvalidation_0-mlogloss:1.55359\tvalidation_1-mlogloss:1.66475\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[82]\tvalidation_0-mlogloss:1.55323\tvalidation_1-mlogloss:1.66520\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[83]\tvalidation_0-mlogloss:1.55302\tvalidation_1-mlogloss:1.66510\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[84]\tvalidation_0-mlogloss:1.55276\tvalidation_1-mlogloss:1.66472\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[85]\tvalidation_0-mlogloss:1.55251\tvalidation_1-mlogloss:1.66431\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[86]\tvalidation_0-mlogloss:1.55221\tvalidation_1-mlogloss:1.66424\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[87]\tvalidation_0-mlogloss:1.55190\tvalidation_1-mlogloss:1.66485\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[88]\tvalidation_0-mlogloss:1.55166\tvalidation_1-mlogloss:1.66491\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[89]\tvalidation_0-mlogloss:1.55135\tvalidation_1-mlogloss:1.66608\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[90]\tvalidation_0-mlogloss:1.55105\tvalidation_1-mlogloss:1.66604" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[91]\tvalidation_0-mlogloss:1.55082\tvalidation_1-mlogloss:1.66697\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[92]\tvalidation_0-mlogloss:1.55057\tvalidation_1-mlogloss:1.66762\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[93]\tvalidation_0-mlogloss:1.55034\tvalidation_1-mlogloss:1.66721" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[94]\tvalidation_0-mlogloss:1.55011\tvalidation_1-mlogloss:1.66692\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[95]\tvalidation_0-mlogloss:1.54989\tvalidation_1-mlogloss:1.66743\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[96]\tvalidation_0-mlogloss:1.54977\tvalidation_1-mlogloss:1.66824\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[97]\tvalidation_0-mlogloss:1.54957\tvalidation_1-mlogloss:1.66862\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[98]\tvalidation_0-mlogloss:1.54941\tvalidation_1-mlogloss:1.66871\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[99]\tvalidation_0-mlogloss:1.54917\tvalidation_1-mlogloss:1.66925\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[100]\tvalidation_0-mlogloss:1.54898\tvalidation_1-mlogloss:1.67000\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[101]\tvalidation_0-mlogloss:1.54878\tvalidation_1-mlogloss:1.67083\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[102]\tvalidation_0-mlogloss:1.54861\tvalidation_1-mlogloss:1.67069\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[103]\tvalidation_0-mlogloss:1.54848\tvalidation_1-mlogloss:1.67156\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[104]\tvalidation_0-mlogloss:1.54831\tvalidation_1-mlogloss:1.67199\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[105]\tvalidation_0-mlogloss:1.54819\tvalidation_1-mlogloss:1.67353\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[106]\tvalidation_0-mlogloss:1.54804\tvalidation_1-mlogloss:1.67409" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[107]\tvalidation_0-mlogloss:1.54785\tvalidation_1-mlogloss:1.67571\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[108]\tvalidation_0-mlogloss:1.54769\tvalidation_1-mlogloss:1.67610\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[109]\tvalidation_0-mlogloss:1.54749\tvalidation_1-mlogloss:1.67505\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[110]\tvalidation_0-mlogloss:1.54734\tvalidation_1-mlogloss:1.67565\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[111]\tvalidation_0-mlogloss:1.54714\tvalidation_1-mlogloss:1.67501\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[112]\tvalidation_0-mlogloss:1.54694\tvalidation_1-mlogloss:1.67598\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[113]\tvalidation_0-mlogloss:1.54675\tvalidation_1-mlogloss:1.67676" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[114]\tvalidation_0-mlogloss:1.54660\tvalidation_1-mlogloss:1.67657\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[115]\tvalidation_0-mlogloss:1.54650\tvalidation_1-mlogloss:1.67720" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[116]\tvalidation_0-mlogloss:1.54636\tvalidation_1-mlogloss:1.67872\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[117]\tvalidation_0-mlogloss:1.54619\tvalidation_1-mlogloss:1.67971\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[118]\tvalidation_0-mlogloss:1.54608\tvalidation_1-mlogloss:1.68073\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[119]\tvalidation_0-mlogloss:1.54593\tvalidation_1-mlogloss:1.68072\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[120]\tvalidation_0-mlogloss:1.54581\tvalidation_1-mlogloss:1.68208\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[121]\tvalidation_0-mlogloss:1.54565\tvalidation_1-mlogloss:1.68191\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[122]\tvalidation_0-mlogloss:1.54553\tvalidation_1-mlogloss:1.68254\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[123]\tvalidation_0-mlogloss:1.54545\tvalidation_1-mlogloss:1.68190\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[124]\tvalidation_0-mlogloss:1.54533\tvalidation_1-mlogloss:1.68290\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[125]\tvalidation_0-mlogloss:1.54516\tvalidation_1-mlogloss:1.68264\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[126]\tvalidation_0-mlogloss:1.54503\tvalidation_1-mlogloss:1.68332\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[127]\tvalidation_0-mlogloss:1.54491\tvalidation_1-mlogloss:1.68335\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[128]\tvalidation_0-mlogloss:1.54478\tvalidation_1-mlogloss:1.68511\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[129]\tvalidation_0-mlogloss:1.54459\tvalidation_1-mlogloss:1.68530\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[130]\tvalidation_0-mlogloss:1.54449\tvalidation_1-mlogloss:1.68574\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[131]\tvalidation_0-mlogloss:1.54441\tvalidation_1-mlogloss:1.68651\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[132]\tvalidation_0-mlogloss:1.54429\tvalidation_1-mlogloss:1.68695" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[133]\tvalidation_0-mlogloss:1.54417\tvalidation_1-mlogloss:1.68773\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[134]\tvalidation_0-mlogloss:1.54407\tvalidation_1-mlogloss:1.68831\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[135]\tvalidation_0-mlogloss:1.54396\tvalidation_1-mlogloss:1.68973\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[136]\tvalidation_0-mlogloss:1.54387\tvalidation_1-mlogloss:1.69053\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[137]\tvalidation_0-mlogloss:1.54375\tvalidation_1-mlogloss:1.69024" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[138]\tvalidation_0-mlogloss:1.54369\tvalidation_1-mlogloss:1.69069" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[139]\tvalidation_0-mlogloss:1.54359\tvalidation_1-mlogloss:1.69058\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[140]\tvalidation_0-mlogloss:1.54350\tvalidation_1-mlogloss:1.69148\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[141]\tvalidation_0-mlogloss:1.54336\tvalidation_1-mlogloss:1.69111\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[142]\tvalidation_0-mlogloss:1.54324\tvalidation_1-mlogloss:1.69208\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[143]\tvalidation_0-mlogloss:1.54321\tvalidation_1-mlogloss:1.69218\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[144]\tvalidation_0-mlogloss:1.54311\tvalidation_1-mlogloss:1.69307\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[145]\tvalidation_0-mlogloss:1.54309\tvalidation_1-mlogloss:1.69285\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[146]\tvalidation_0-mlogloss:1.54298\tvalidation_1-mlogloss:1.69338\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[147]\tvalidation_0-mlogloss:1.54292\tvalidation_1-mlogloss:1.69344\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[148]\tvalidation_0-mlogloss:1.54285\tvalidation_1-mlogloss:1.69312\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[149]\tvalidation_0-mlogloss:1.54276\tvalidation_1-mlogloss:1.69305\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[150]\tvalidation_0-mlogloss:1.54263\tvalidation_1-mlogloss:1.69372\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[151]\tvalidation_0-mlogloss:1.54256\tvalidation_1-mlogloss:1.69405\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[152]\tvalidation_0-mlogloss:1.54250\tvalidation_1-mlogloss:1.69441\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[153]\tvalidation_0-mlogloss:1.54238\tvalidation_1-mlogloss:1.69454\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[154]\tvalidation_0-mlogloss:1.54230\tvalidation_1-mlogloss:1.69562\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[155]\tvalidation_0-mlogloss:1.54219\tvalidation_1-mlogloss:1.69670\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[156]\tvalidation_0-mlogloss:1.54211\tvalidation_1-mlogloss:1.69640\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[157]\tvalidation_0-mlogloss:1.54204\tvalidation_1-mlogloss:1.69690\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[158]\tvalidation_0-mlogloss:1.54197\tvalidation_1-mlogloss:1.69784\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[159]\tvalidation_0-mlogloss:1.54195\tvalidation_1-mlogloss:1.69788\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[160]\tvalidation_0-mlogloss:1.54185\tvalidation_1-mlogloss:1.69865\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[161]\tvalidation_0-mlogloss:1.54174\tvalidation_1-mlogloss:1.69913\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[162]\tvalidation_0-mlogloss:1.54169\tvalidation_1-mlogloss:1.69888" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[163]\tvalidation_0-mlogloss:1.54162\tvalidation_1-mlogloss:1.69907" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[164]\tvalidation_0-mlogloss:1.54151\tvalidation_1-mlogloss:1.69953\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[165]\tvalidation_0-mlogloss:1.54134\tvalidation_1-mlogloss:1.69920" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[166]\tvalidation_0-mlogloss:1.54129\tvalidation_1-mlogloss:1.69994\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[167]\tvalidation_0-mlogloss:1.54121\tvalidation_1-mlogloss:1.70030\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[168]\tvalidation_0-mlogloss:1.54113\tvalidation_1-mlogloss:1.69987\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[169]\tvalidation_0-mlogloss:1.54104\tvalidation_1-mlogloss:1.69925\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[170]\tvalidation_0-mlogloss:1.54100\tvalidation_1-mlogloss:1.69927\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[171]\tvalidation_0-mlogloss:1.54092\tvalidation_1-mlogloss:1.69969\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[172]\tvalidation_0-mlogloss:1.54085\tvalidation_1-mlogloss:1.70002" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[173]\tvalidation_0-mlogloss:1.54073\tvalidation_1-mlogloss:1.69961\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[174]\tvalidation_0-mlogloss:1.54063\tvalidation_1-mlogloss:1.69932\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[175]\tvalidation_0-mlogloss:1.54057\tvalidation_1-mlogloss:1.70062" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[176]\tvalidation_0-mlogloss:1.54048\tvalidation_1-mlogloss:1.70084\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[177]\tvalidation_0-mlogloss:1.54041\tvalidation_1-mlogloss:1.69992" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[178]\tvalidation_0-mlogloss:1.54038\tvalidation_1-mlogloss:1.70033\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[179]\tvalidation_0-mlogloss:1.54025\tvalidation_1-mlogloss:1.70055\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[180]\tvalidation_0-mlogloss:1.54022\tvalidation_1-mlogloss:1.70098\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[181]\tvalidation_0-mlogloss:1.54013\tvalidation_1-mlogloss:1.70193\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[182]\tvalidation_0-mlogloss:1.54002\tvalidation_1-mlogloss:1.70218\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[183]\tvalidation_0-mlogloss:1.53997\tvalidation_1-mlogloss:1.70308\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[184]\tvalidation_0-mlogloss:1.53995\tvalidation_1-mlogloss:1.70418" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[185]\tvalidation_0-mlogloss:1.53991\tvalidation_1-mlogloss:1.70436\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[186]\tvalidation_0-mlogloss:1.53984\tvalidation_1-mlogloss:1.70553\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[187]\tvalidation_0-mlogloss:1.53977\tvalidation_1-mlogloss:1.70659\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[188]\tvalidation_0-mlogloss:1.53978\tvalidation_1-mlogloss:1.70727\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[189]\tvalidation_0-mlogloss:1.53973\tvalidation_1-mlogloss:1.70710\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[190]\tvalidation_0-mlogloss:1.53965\tvalidation_1-mlogloss:1.70712\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[191]\tvalidation_0-mlogloss:1.53958\tvalidation_1-mlogloss:1.70738\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[192]\tvalidation_0-mlogloss:1.53950\tvalidation_1-mlogloss:1.70774\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[193]\tvalidation_0-mlogloss:1.53946\tvalidation_1-mlogloss:1.70776\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[194]\tvalidation_0-mlogloss:1.53940\tvalidation_1-mlogloss:1.70875\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[195]\tvalidation_0-mlogloss:1.53936\tvalidation_1-mlogloss:1.70919\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[196]\tvalidation_0-mlogloss:1.53929\tvalidation_1-mlogloss:1.70909\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[197]\tvalidation_0-mlogloss:1.53920\tvalidation_1-mlogloss:1.70951" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[198]\tvalidation_0-mlogloss:1.53911\tvalidation_1-mlogloss:1.70983\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[199]\tvalidation_0-mlogloss:1.53903\tvalidation_1-mlogloss:1.71002" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "✅ Training completed!" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", " Validation Accuracy: 0.3673 (36.73%)\n", "CPU times: user 6.06 s, sys: 119 ms, total: 6.18 s\n", "Wall time: 782 ms\n" ] } ], "source": [ "%%time\n", "# Import XGBoost\n", "import xgboost as xgb\n", "from sklearn.metrics import accuracy_score\n", "import numpy as np\n", "\n", "# Convert to numpy arrays\n", "X_train_np = np.asarray(X_train, dtype=np.float32)\n", "X_val_np = np.asarray(X_val, dtype=np.float32)\n", "y_train_np = np.asarray(y_train, dtype=np.int32)\n", "y_val_np = np.asarray(y_val, dtype=np.int32)\n", "\n", "print(\"🚀 Training XGBoost model...\")\n", "print(f\" Train samples: {len(X_train_np)}\")\n", "print(f\" Val samples: {len(X_val_np)}\")\n", "print(f\" Features: {X_train_np.shape[1]}\")\n", "print(f\" Classes: 8\\n\")\n", "\n", "# XGBoost parameters\n", "params = {\n", " 'objective': 'multi:softmax', # Multi-class classification\n", " 'num_class': 8, # 8 land use classes\n", " 'max_depth': 6, # Maximum tree depth\n", " 'learning_rate': 0.1, # Learning rate\n", " 'n_estimators': 200, # Number of trees\n", " 'subsample': 0.8, # Subsample ratio\n", " 'colsample_bytree': 0.8, # Feature sampling ratio\n", " 'random_state': 42,\n", " 'n_jobs': -1, # Use all CPU cores\n", " 'eval_metric': 'mlogloss' # Multi-class log loss\n", "}\n", "\n", "# Train XGBoost model\n", "model = xgb.XGBClassifier(**params)\n", "\n", "model.fit(\n", " X_train_np, y_train_np,\n", " eval_set=[(X_train_np, y_train_np), (X_val_np, y_val_np)],\n", " verbose=True\n", ")\n", "\n", "# Validation accuracy\n", "y_val_pred = model.predict(X_val_np)\n", "val_accuracy = accuracy_score(y_val_np, y_val_pred)\n", "print(f\"\\n✅ Training completed!\")\n", "print(f\" Validation Accuracy: {val_accuracy:.4f} ({val_accuracy*100:.2f}%)\")" ] }, { "cell_type": "code", "execution_count": 13, "id": "b2a1e42c-cf1b-4d82-a6af-b06e3496918f", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:37:04.466500Z", "iopub.status.busy": "2026-07-15T08:37:04.466169Z", "iopub.status.idle": "2026-07-15T08:37:04.800950Z", "shell.execute_reply": "2026-07-15T08:37:04.800127Z" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "📊 Evaluating XGBoost model on test set...\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Test Results:\n", " Accuracy: 0.2876 (28.76%)\n", " Precision: 0.3534\n", " Recall: 0.2876\n", " F1-Score: 0.2346\n", "\n" ] }, { "data": { "image/png": "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Xk8++aQ++ugj+3S8K9MFw8PDc7y+XLly9udze5xhGPr666/VsWNHTZs2TY0aNVKZMmU0YsQInT17Ntd987+u9EFcXFyujk9OTr5mnP/7s1xRqlQph8fe3t6SlKtELLdefvlljR07VsuWLVPbtm0VEhKibt26OUxz/bvc9vkVf/85pMs/S15/jh49esjHx0czZszQp59+ap+qejV9+vTR7Nmzdf/992v16tXasmWLtm7dqjJlyuSp3av9jP+kefPmql27ti5cuKAhQ4aoRIkSeXo9APxbkOQBQBHas2ePJkyYoL59+6p3795asGCBDh48qMcff9zhuCvX6K1YscJhf9myZe0JXEBAQK7bvVKlulI1vJIYHD9+PMexx44dU+nSpfN0nHR5IZg333xTiYmJ2r9/v0aNGqU5c+bokUceyXWc/6tjx46SpGXLluXq+FKlSl0zTkkOsTrL29vb4R6FV/w9AStRooQmT56sffv2KTExUXPnztX333+vLl26XPPceenzguTn56e77rpLsbGxKlGihO68886rHpeSkqLPPvtMjz76qMaNG6dbbrlFTZs2Vd26dXXq1Kk8tZnX+wNOnDhRu3btUuPGjTVhwgQdPnw4T68HgH8LkjwAKCKZmZnq16+fSpcurZdeekmSdMMNN2j06NF66aWXtGnTJvuxd9xxh2rVqqUpU6Zo3759Trd9ZYXLK7cBuDJF7u+Lc2zdulV79+7VLbfcIklq0aKFfH19cxx39OhR+/TIq6lWrZqeeOIJ1a1bVz/99JN9f14qTI0aNVLnzp315ptvau3atVc95scff1R8fLwk6ZZbbtHatWvtSd0Vb7/9tvz8/Ar0PnRRUVHauXOnw761a9cqLS3tmq8JDQ1VTEyM7r77bu3fv1/nzp276nG5/bcpDEOGDFGXLl00YcIE+fj4XPUYwzBks9nslc8r5s2bZ1+05oqCrI6uWbNGsbGxeuKJJ7RmzRoFBQWpd+/eunjxotPnBgB3w33yAKCIxMbG6scff9TKlSsVHBxs3//000/r008/1YABA7Rjxw75+vrK09NTy5YtU8eOHdWsWTMNGjRIbdq0UcmSJXXmzBn98MMP+vnnn696e4X4+Hh9//33kqT09HRt3rxZsbGxqlixor06U716df33v/+1XxvYuXNnHTlyRE8++aQiIiI0atQoSVJwcLCefPJJPfbYY+rbt6/uvvtuJScna/LkyfLx8dHEiRMlSTt37tSwYcPUs2dPVa1aVcWLF9fatWu1c+dOjRs3zh5b3bp19f777+uDDz5QpUqV5OPj848rI7799tvq1KmTOnfubL8Z+pUbwn/66ad67733tG3bNkVGRmrixIn67LPP1LZtW02YMEEhISF699139fnnn2vatGkOt6hw1n333acnn3xSEyZMUOvWrbVnzx7Nnj07RxvNmzfXf/7zH9WrV08lS5bU3r179c4776hFixby8/O76rlz+29TGBo0aHDdymlgYKBatWql559/XqVLl1ZUVJQ2bNigN99802FcS1KdOnUkSa+//roCAgLk4+Oj6Ojoq04x/SdXVuFs3bq1Jk6cKA8PD33wwQdq1aqVHn30UYd7TAIAxOqaAFAUduzYYfPy8rINGjToqs9v3rzZ5uHhYRs1apTD/pSUFNuUKVNsTZs2tQUGBtqKFStmK1u2rK19+/a2V155xZaenm4/9mqra/r4+NiqVatmGzlypO348eMO587KyrI999xztmrVqtm8vLxspUuXtt177722hISEHPHNmzfPVq9ePVvx4sVtQUFBtq5du9p2795tf/7EiRO2mJgYW40aNWwlSpSw+fv72+rVq2ebMWOGw6qeR44csXXo0MEWEBBgk2SrWLHidfvu/PnztpdfftnWokULex+UK1fOduedd9o+//xzh2N37dpl69Kliy0oKMhWvHhxW/369W3z5893OObK6pofffSRw/4r/fe/x19rdc2MjAzbo48+aouIiLD5+vraWrdubduxY0eO1TXHjRtna9Kkia1kyZI2b29vW6VKlWyjRo2ynTx5Mkcb/yu3/zatW7e21a5dO0ef9evXL1d9+7+ra17L1VbIPHr0qK179+62kiVL2gICAmydOnWy/fLLLzl+fpvNZps5c6YtOjra5unp6dC/14r9ynNXVtfMzMy0tW7d2hYaGppjDD///PM2SbalS5de92cFgH8Tw2az2cxJLwEAAAAABY1r8gAAAADAjZDkAQAAAIAbIckDAAAAADdCkgcAAAAAboQkDwAAAADcCEkeAAAAALgRboYOB9nZ2Tp27JgCAgJkGIbZ4QAAAKCI2Ww2nT17VuXKlZOHh+vXhC5cuKCLFy+a1n7x4sXl4+NjWvtXQ5IHB8eOHVNERITZYQAAAMBkCQkJ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RYuCiwwAAAAAkGd5ruTFxsaqU6dO2rNnjzIzM/XSSy9p9+7d2rx5szZs2FAYMQIAAAAAcinPlbyWLVtq06ZNOnfunCpXrqwvv/xSoaGh2rx5sxo3blwYMQIAAADANbHwiqM8V/IkqW7dulq4cGFBxwIAAAAAcFK+krysrCwtXbpUe/fulWEYqlmzprp27apixfJ1OgAAAADIN+PPzYx2XVGes7JffvlFXbt2VWJioqpXry5J+vXXX1WmTBmtWLFCdevWLfAgAQAAAAC5k+dr8u6//37Vrl1bR48e1U8//aSffvpJCQkJqlevnv773/8WRowAAAAAgFzKcyXv559/1o8//qiSJUva95UsWVLPPvusmjZtWqDBAQAAAMD1eBiGPExYBMWMNnMjz5W86tWr68SJEzn2JyUlqUqVKgUSFAAAAAAgf3KV5KWmptq3KVOmaMSIEfr444919OhRHT16VB9//LFGjhyp5557rrDjBQAAAAAHhmHelhcbN25Uly5dVK5cORmGoWXLljk8HxMTk+MWDTfccEOe+yNX0zWDg4Md7gFhs9nUq1cv+z6bzSZJ6tKli7KysvIcBAAAAAC4u/T0dNWvX1/9+/dX9+7dr3pMp06dNH/+fPvj4sWL57mdXCV569aty/OJAQAAAAB/6dy5szp37vyPx3h7eyssLMypdnKV5LVu3dqpRgAAAACgsFyZ2mhGu9Lly9v+l7e3t7y9vfN1zvXr16ts2bIKDg5W69at9eyzz6ps2bJ5Oke+715+7tw5xcfH6+LFiw7769Wrl99TAgAAAIDlREREODyeOHGiJk2alOfzdO7cWT179lTFihUVFxenJ598Uu3atdO2bdvylDTmOcn7448/1L9/f61cufKqz3NNHgAAAICilJ9FUAqqXUlKSEhQYGCgfX9+q3i9e/e2/71OnTpq0qSJKlasqM8//1x33nlnrs+T51sojBw5UqdPn9b3338vX19frVq1SgsXLlTVqlW1YsWKvJ4OAAAAACwtMDDQYctvkvd34eHhqlixog4cOJCn1+W5krd27VotX75cTZs2lYeHhypWrKj27dsrMDBQsbGxuv322/N6SgAAAADA3yQnJyshIUHh4eF5el2ek7z09HT7hX8hISH6448/VK1aNdWtW1c//fRTXk8HAAAAAE7xMAx5mDBfM69tpqWl6eDBg/bHcXFx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5gTrwhiDhcswcXNFLpvk7d27V9HRly/G/+2333TbbbepTp06+uSTT7Rt2za98sorki5XtvLq3Llz2rZtmzw9PXXgwAGH5z788EONGjVKAwYM0JdffqkdO3aof//+unjxov2YsmXLqkuXLpo/f76SkpL0xRdfaMCAAdds78r1f//r79/YXFnC/n+PvdrPdqXi+L/n+fv5/37uq7V/xfjx45WSkmLfEhISrnmsq7HZbLp4icV5civj4iV55Bh3hrKzrz0+8JfiXsXUoEaE1v2wz2H/+i371KweC4fkxcq1Pyk4sIRuaMz1oCg6vIfzZ9ojPfWftvX1f0NeVvw/JG6p6ReUfCZNlSLKqGHNSH2xYec1j/23YgyiKLnkdM21a9dq165dGjVqlCTpxx9/VGZmpl588UV7MnTlGrkrihcvrqysrFydf8yYMfLw8NDKlSt122236fbbb1e7du0kSd98841atmypoUOH2o8/dOhQjnPcf//9uuuuu1ShQgVVrlxZN9544zXbq1WrluLj43Xs2DGVK1dOkrR582aHY8qUKSNJOn78uEqWLCnp8sIreREUFKTQ0FBt2bJFN998s6TLC8ls375dDRo0uOprvL295e3tnad2zPDivC/UqlkNhZcNVvq5DH2+bru2/HxIb8YOMjs0y2jeqLreX/aNypQKVsWIMjp0JFFLv9isDm0amh2aZQzt006DJ76thrUi1bRutBYu3aSjiafUv/vNZodmGdnZ2Vq17id1bNNQxTw9zQ7HctLPZSju6F/3H4s/nqxffj2q4EA/VQgLMTEya+A9nDcvjO2lHh2bqM/Dryvt3AWVLXW52pSadkEXMi5/Ed31loY6eTpNR0+cUq3K5TR1TA99vmFnjkQGlzEGC5FZZTUXLeWZnuRlZGQoMTFRWVlZOnHihFatWqXY2Fj95z//Ud++fSVJlStXVmZmpmbNmqUuXbpo06ZNevXVVx3OExUVpbS0NH399deqX7++/Pz85Ofnl6O9zz//XG+99ZY2b96sRo0aady4cerXr5927typkiVLqkqVKnr77be1evVqRUdH65133tHWrVvtVcUrOnbsqKCgID3zzDMO18Rdza233qrq1aurb9++evHFF5WammpfzfOKKlWqKCIiQpMmTdIzzzyjAwcO6MUXX8xzfw4fPlyxsbGqUqWKatSooVmzZun06dOW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2zZDlk5ExJY8IiIiovxWrVqF0NBQ9OnTB3Z2drC2tsaXX36JlJQUDBgwAOHh4QAAb29vJCUlYcKECVi5ciU0Gg0OHToEIyMjvZk4iYheNYY8IiIior8sXboUAQEBiIyMhI+PD9RqNQAgISEBYWFhiI2NxZgxY/Dpp5/i1KlTGDduHO7du4eKFSsiOjoaarWaAY+IDI4hj4iIiAhATEwM3nvvPWzevBldunRRZsTUarUwNjbGtWvXMHjwYDx69Ajbtm2DnZ0dACApKQl2dnZQqVScRZOIigReZiIiIqISLzs7G7t27YKTkxMSExMBQC/giQicnZ0xfvx4nDp1CleuXFH2tbe3h0qlgk6nY8AjoiKBn0RERERU4pmZmSE0NBRmZmb4+uuvkZ6ejqCgIBgbG0On00GlUgEAqlatClNTU2RkZBR4DnbRJKKigp9GRERERAAqVKiAcePGoUGDBoiOjsaMGTMAPA5vWq0WAHDu3DnUr18f7u7uhiyViOhvMeQRERER/cXe3h7BwcEFgp6JiQn+/PNPrFq1Cq6urqhUqZKBKyUiejpOvEJERET0hKSkJISFheHEiRPo2bMnAgMD0b17d9y8eRNxcXEwMTGBiCjdOImIihKGPCIiIqJCJCUlITw8HCdPnsTVq1dhbW2N8+fPQ61WKxOyEBEVRQx5RERERE+RlJSEoKAg3Lt3D5s3b4ZareZtEoioyGPIIyIiIvobqampeOONN2BkZMSAR0SvBYY8IiIioueg0+l4mwQiei0w5BERERERERUjvBxFRERERERUjDDkERERERERFSMMeURERERERMUIQx4REREREVExwpBHRERERERUjDDkERERERERFSMMeURE9NqZPHky6tSpozweMGAAunfv/srruHnzJlQqFc6cOfPUbapWrYp58+Y993NGRETA2tr6H9emUqkQExPzj5+HiIhePwx5RET0UgwYMAAqlQoqlQpqtRpOTk4IDAxEenr6v/6758+fj4iIiOfa9nmCGRER0evMxNAFEBFR8dG+fXusXr0aubm5OHToEAYPHoz09HQsXry4wLa5ublQq9Uv5fe+8cYbL+V5iIiIigO25BER0UtjZmYGe3t7VK5cGX379oWvr6/SZTCvi+WqVavg5OQEMzMziAjS0tLw4Ycfonz58ihTpgxatWqFX375Re95p0+fDjs7O5QuXRqDBg1CVlaW3vonu2vqdDrMmDED1apVg5mZGapUqYKwsDAAwFtvvQUAqFu3LlQqFby9vZX9Vq9eDTc3N5ibm8PV1RWLFi3S+z0///wz6tatC3Nzc3h6euL06dMvfIzmzJmDWrVqwcrKCpUrV8bHH3+MR48eFdguJiYGNWrUgLm5Odq2bYvffvtNb/3WrVtRv359mJubw8nJCVOmTIFGo3nheoiIqPhhyCMion+NhYUFcnNzlcdXr17Fhg0bEBUVpXSX7NSpE5KSkrBjxw6cPHkS9erVQ+vWrXH//n0AwIYNGzBp0iSEhYUhLi4OFSpUKBC+njR+/HjMmDEDEydORHx8PNavXw87OzsAj4MaAOzduxd37tzB999/DwBYvnw5goODERYWhosXLyI8PBwTJ05EZGQkACA9PR2dO3eGi4sLTp48icmTJyMwMPCFj4mRkREWLFiA8+fPIzIyEvv378fYsWP1tsnIyEBYWBgiIyNx5MgRPHz4EO+//76yfteuXfjPf/6DgIAAxMfHY+nSpYiIiFCCLBERlXBCRET0EvTv31+6deumPD5+/LjY2tpK7969RURk0qRJolarJTk5Wdlm3759UqZMGcnKytJ7LmdnZ1m6dKmIiHh5ecmQIUP01jdq1Ehq165d6O9++PChmJmZyfLlywut88aNGwJATp8+rbe8cuXKsn79er1lU6dOFS8vLxERWbp0qdjY2Eh6erqyfvHixYU+V36Ojo4yd+7cp67fsGGD2NraKo9Xr14tAOTYsWPKsosXLwoAOX78uIiING/eXMLDw/WeZ+3atVKhQgXlMQCJjo5+6u8lIqLii2PyiIjopdm2bRtKlSoFjUaD3NxcdOvWDV9++aWy3tHREW+++aby+OTJk3j06BFsbW31niczMxPXrl0DAFy8eBFDhgzRW+/l5YUDBw4UWsPFixeRnZ2N1q1bP3fd9+7dw2+//YZBgwbB399fWa7RaJTxfhcvXkTt2rVhaWmpV8eLOnDgAMLDwxEfH4+HDx9Co9EgKysL6enpsLKyAgCYmJjA09NT2cfV1RXW1ta4ePEiGjZsiJMnT+LEiRN6LXdarRZZWVnIyMjQq5GIiEoehjwiInpp3nnnHSxevBhqtRoODg4FJlbJCzF5dDodKlSogIMHDxZ4rv/1NgIWFhYvvI9OpwPwuMtmo0aN9NYZGxsDAETkf6onv8TERHTs2BFDhgzB1KlTYWNjg8OHD2PQoEF63VqBx7dAeFLeMp1OhylTpuC9994rsI25ufk/rpOIiF5vDHlERPTSWFlZoVq1as+9fb169ZCUlAQTExNUrVq10G3c3Nxw7Ngx9OvXT1l27Nixpz5n9erVYWFhgX379mHw4MEF1puamgJ43PKVx87ODhUrVsT169fh6+tb6PO6u7tj7dq1yMzMVILk39VRmLi4OGg0GsyePRtGRo+HxW/YsKHAdhqNBnFxcWjYsCEA4PLly3jw4AFcXV0BPD5uly9ffqFjTUREJQdDHhERGUybNm3g5eWF7t27Y8aMGXBxccHt27exY8cOdO/eHZ6enhg5ciT69+8PT09PNGvWDOvWrcOFCxfg5ORU6HOam5sjKCgIY8eOhampKZo2bYp79+7hwoULGDRoEMqXLw8LCwvExsaiUqVKMDc3xxtvvIHJkycjICAAZcqUQYcOHZCdnY24uDikpqZi9OjR6Nu3L4KDgzFo0CCEhITg5s2bmDVr1gv9vc7OztBoNPjyyy/RpUsXHDlyBEuWLCmwnVqtxogRI7BgwQKo1WoMHz4cjRs3VkJfaGgoOnfujMqVK6NXr14wMjLC2bNnce7cOXz++ecv/h9BRETFCmfXJCIig1GpVNixYwdatGiBgQMHokaNGnj//fdx8+ZNZTbMPn36IDQ0FEFBQahfvz4SExMxdOjQv33eiRMn4tNPP0VoaCjc3NzQp08fJCcnA3g83m3BggVYunQpHBwc0K1bNwDA4MGDsWLFCkRERKBWrVpo2bIlIiIilFsulCpVClu3bkV8fDzq1q2L4OBgzJgx44X+3jp16mDOnDmYMWMGatasiXXr1mHatGkFtrO0tERQUBD69u0LLy8vWFhY4Ntvv1XWt2vXDtu2bcOePXvQoEEDNG7cGHPmzIGjo+ML1UNERMWTSl7GIAMiIiIiIiIqEtiSR0REREREVIww5BERERERERUjDHlERERERETFCEMeERERERFRMcKQR0REREREVIww5BERERERERUjDHlERERERETFCEMeERERERFRMcKQR0REREREVIww5BERERERERUjDHlERERERETFCEMeERERERFRMfL/4JXwTxYtbfcAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 622 ms, sys: 23.5 ms, total: 646 ms\n", "Wall time: 329 ms\n" ] } ], "source": [ "%%time\n", "# Evaluate on test set\n", "X_test_np = np.asarray(X_test, dtype=np.float32)\n", "y_test_np = np.asarray(y_test, dtype=np.int32)\n", "\n", "print(\"📊 Evaluating XGBoost model on test set...\\n\")\n", "\n", "# Predictions\n", "y_pred_test = model.predict(X_test_np)\n", "\n", "# Metrics\n", "from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix\n", "\n", "test_accuracy = accuracy_score(y_test_np, y_pred_test)\n", "precision = precision_score(y_test_np, y_pred_test, average='weighted', zero_division=0)\n", "recall = recall_score(y_test_np, y_pred_test, average='weighted', zero_division=0)\n", "f1 = f1_score(y_test_np, y_pred_test, average='weighted', zero_division=0)\n", "\n", "print(f\"📈 Test Results:\")\n", "print(f\" Accuracy: {test_accuracy:.4f} ({test_accuracy*100:.2f}%)\")\n", "print(f\" Precision: {precision:.4f}\")\n", "print(f\" Recall: {recall:.4f}\")\n", "print(f\" F1-Score: {f1:.4f}\\n\")\n", "\n", "# Confusion Matrix\n", "from sklearn.metrics import ConfusionMatrixDisplay\n", "import matplotlib.pyplot as plt\n", "\n", "# Create figure first\n", "fig, ax = plt.subplots(figsize=(10, 8))\n", "\n", "class_names = list(label_mapping.keys())\n", "cm = confusion_matrix(y_test_np, y_pred_test)\n", "disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=class_names)\n", "disp.plot(cmap='Blues', ax=ax)\n", "plt.xticks(rotation=45, ha='right')\n", "plt.title('XGBoost Confusion Matrix')\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 14, "id": "f1a14379-ed6e-4897-9ca4-2669743fab40", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:37:04.802731Z", "iopub.status.busy": "2026-07-15T08:37:04.802552Z", "iopub.status.idle": "2026-07-15T08:37:04.862105Z", "shell.execute_reply": "2026-07-15T08:37:04.861475Z" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ Model saved to model_xgboost.joblib\n", "✅ Model info saved to model_xgboost_info.json\n" ] } ], "source": [ "# Lưu mô hình huấn luyện\n", "import json\n", "import joblib\n", "\n", "# Save XGBoost model\n", "model_path = \"model_xgboost.joblib\"\n", "joblib.dump(model, model_path)\n", "print(f\"✅ Model saved to {model_path}\")\n", "\n", "# Save model info\n", "info = {\n", " \"model_type\": \"XGBoost\",\n", " \"num_classes\": 8,\n", " \"classes\": list(label_mapping.keys()),\n", " \"num_features\": X_train_np.shape[1],\n", " \"params\": params,\n", " \"accuracy\": float(test_accuracy),\n", " \"precision\": float(precision),\n", " \"recall\": float(recall),\n", " \"f1_score\": float(f1),\n", "}\n", "\n", "with open(\"model_xgboost_info.json\", \"w\") as f:\n", " json.dump(info, f, indent=2)\n", "\n", "print(f\"✅ Model info saved to model_xgboost_info.json\")" ] }, { "cell_type": "code", "execution_count": 15, "id": "33dd516d-9824-499e-96b9-5cd9224c194c", "metadata": { "execution": { "iopub.execute_input": "2026-07-15T08:37:04.863809Z", "iopub.status.busy": "2026-07-15T08:37:04.863630Z", "iopub.status.idle": "2026-07-15T08:37:04.866010Z", "shell.execute_reply": "2026-07-15T08:37:04.865483Z" }, "tags": [] }, "outputs": [], "source": [ "# đóng client, cluster\n", "# client.close()\n", "# cluster.close()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.18" } }, "nbformat": 4, "nbformat_minor": 5 }