diff --git a/user-guide/content-curation/docs-and-notebooks.qmd b/user-guide/content-curation/docs-and-notebooks.qmd index 5487fb8a..1f75b293 100644 --- a/user-guide/content-curation/docs-and-notebooks.qmd +++ b/user-guide/content-curation/docs-and-notebooks.qmd @@ -99,7 +99,7 @@ To present consistent best practices, we always access data via the STAC API. #### Analyzing data * [rioxarray](https://corteva.github.io/rioxarray/stable/): rasterio xarray extension -* [stackstac](https://stackstac.readthedocs.io/): stackstac.stack turns a STAC collection into a lazy xarray.DataArray, backed by dask. +* [odc-stac](https://odc-stac.readthedocs.io/): odc.stac.load turns a STAC collection into a lazy xarray.DataArray, backed by dask. ### Generate "Launch in VEDA JupyterHub" link diff --git a/user-guide/notebooks/datasets/nceo-biomass-statistics.ipynb b/user-guide/notebooks/datasets/nceo-biomass-statistics.ipynb index ccdc1845..9b65cb7e 100644 --- a/user-guide/notebooks/datasets/nceo-biomass-statistics.ipynb +++ b/user-guide/notebooks/datasets/nceo-biomass-statistics.ipynb @@ -233,9 +233,7 @@ "source": [ "## Reading and accessing the data\n", "\n", - "Now that we've explored the dataset through the STAC API, let's read and access the dataset itself. \n", - "\n", - "Note: We need to manually pull the epsg code from the item since stackstac doesn't understand newer versions of the Projection STAC Extension ([GitHub issue](https://github.com/gjoseph92/stackstac/issues/262))" + "Now that we've explored the dataset through the STAC API, let's read and access the dataset itself." ] }, { @@ -261,9 +259,7 @@ "\n", "\n", "\n", - "
<xarray.DataArray 'stackstac-00a12995ab4ad3703f5c19282f0cc6bf' (y: 81025,\n",
- " x: 78078)> Size: 51GB\n",
- "dask.array<getitem, shape=(81025, 78078), dtype=float64, chunksize=(1024, 1024), chunktype=numpy.ndarray>\n",
- "Coordinates: (12/16)\n",
- " time datetime64[ns] 8B NaT\n",
- " id <U19 76B 'AGB_map_2017v0m_COG'\n",
- " band <U11 44B 'cog_default'\n",
- " * x (x) float64 625kB -18.27 -18.27 -18.27 ... 51.86 51.86 51.86\n",
- " * y (y) float64 648kB 37.73 37.73 37.73 ... -35.05 -35.05 -35.05\n",
- " start_datetime <U25 100B '2017-01-01T00:00:00+00:00'\n",
- " ... ...\n",
- " end_datetime <U25 100B '2017-12-31T23:59:59+00:00'\n",
- " proj:bbox object 8B {-35.054059016911935, 51.86423292864056, 37.731...\n",
- " description <U47 188B 'Cloud optimized default layer to display on map'\n",
- " title <U17 68B 'Default COG Layer'\n",
- " raster:bands object 8B {'scale': 1, 'nodata': 'inf', 'offset': 0, 'sam...\n",
- " epsg int64 8B 4326\n",
+ "<xarray.DataArray 'cog_default' (latitude: 81024, longitude: 78077)> Size: 25GB\n",
+ "dask.array<getitem, shape=(81024, 78077), dtype=float32, chunksize=(5792, 5792), chunktype=numpy.ndarray>\n",
+ "Coordinates:\n",
+ " * latitude (latitude) float64 648kB 37.73 37.73 37.73 ... -35.05 -35.05\n",
+ " * longitude (longitude) float64 625kB -18.27 -18.27 -18.27 ... 51.86 51.86\n",
+ " spatial_ref int32 4B 4326\n",
+ " time datetime64[ns] 8B 2017-01-01\n",
"Attributes:\n",
- " spec: RasterSpec(epsg=4326, bounds=(-18.274427824843425, -35.05405...\n",
- " crs: epsg:4326\n",
- " transform: | 0.00, 0.00,-18.27|\\n| 0.00,-0.00, 37.73|\\n| 0.00, 0.00, 1.00|\n",
- " resolution: 0.0008983152841195214"
],
"text/plain": [
- " Size: 51GB\n",
- "dask.array\n",
- "Coordinates: (12/16)\n",
- " time datetime64[ns] 8B NaT\n",
- " id Size: 25GB\n",
+ "dask.array\n",
+ "Coordinates:\n",
+ " * latitude (latitude) float64 648kB 37.73 37.73 37.73 ... -35.05 -35.05\n",
+ " * longitude (longitude) float64 625kB -18.27 -18.27 -18.27 ... 51.86 51.86\n",
+ " spatial_ref int32 4B 4326\n",
+ " time datetime64[ns] 8B 2017-01-01\n",
"Attributes:\n",
- " spec: RasterSpec(epsg=4326, bounds=(-18.274427824843425, -35.05405...\n",
- " crs: epsg:4326\n",
- " transform: | 0.00, 0.00,-18.27|\\n| 0.00,-0.00, 37.73|\\n| 0.00, 0.00, 1.00|\n",
- " resolution: 0.0008983152841195214"
+ " nodata: inf"
]
},
"execution_count": 6,
@@ -860,11 +833,11 @@
}
],
"source": [
- "import stackstac\n",
+ "import odc.stac\n",
"import rioxarray\n",
"\n",
"\n",
- "da = stackstac.stack(items[0], epsg=items[0].ext.proj.epsg).squeeze()\n",
+ "da = odc.stac.load(items[:1], chunks={\"latitude\": \"auto\", \"longitude\": \"auto\"}, dtype=\"float32\")['cog_default'].squeeze()\n",
"da"
]
},
@@ -940,8 +913,8 @@
"\n",
"/* Override VSCode background color */\n",
".cell-output-ipywidget-background:has(\n",
- " > .cell-output-ipywidget-background > .lm-Widget > *[data-root-id]\n",
- " ),\n",
+ " > .cell-output-ipywidget-background > .lm-Widget > *[data-root-id]\n",
+ "),\n",
".cell-output-ipywidget-background:has(> .lm-Widget > *[data-root-id]) {\n",
" background-color: transparent !important;\n",
"}\n",
@@ -960,9 +933,11 @@
" }\n",
"\n",
" const force = true;\n",
- " const py_version = '3.7.3'.replace('rc', '-rc.').replace('.dev', '-dev.');\n",
+ " const version = '3.8.1'.replace('rc', '-rc.').replace('.dev', '-dev.');\n",
" const reloading = false;\n",
" const Bokeh = root.Bokeh;\n",
+ " const BK_RE = /^https:\\/\\/cdn\\.bokeh\\.org\\/bokeh\\/(release|dev)\\/bokeh-/;\n",
+ " const PN_RE = /^https:\\/\\/cdn\\.holoviz\\.org\\/panel\\/[^/]+\\/dist\\/panel/i;\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",
@@ -982,7 +957,7 @@
" console.debug(\"Bokeh: all callbacks have finished\");\n",
" }\n",
"\n",
- " function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n",
+ " function load_libs(css_urls, js_urls, js_modules, js_exports, Bokeh, callback) {\n",
" if (css_urls == null) css_urls = [];\n",
" if (js_urls == null) js_urls = [];\n",
" if (js_modules == null) js_modules = [];\n",
@@ -1056,7 +1031,10 @@
" 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",
+ " const shouldSkip = skip.includes(escaped) || existing_scripts.includes(escaped)\n",
+ " const isBokehOrPanel = BK_RE.test(escaped) || PN_RE.test(escaped)\n",
+ " const missingOrBroken = Bokeh == null || Bokeh.Panel == null || (Bokeh.version != version && !Bokeh.versions?.has(version)) || Bokeh.versions?.get(version).Panel == null;\n",
+ " if (shouldSkip && !(isBokehOrPanel && missingOrBroken)) {\n",
" if (!window.requirejs) {\n",
" on_load();\n",
" }\n",
@@ -1120,7 +1098,7 @@
" document.body.appendChild(element);\n",
" }\n",
"\n",
- " const js_urls = [\"https://cdn.holoviz.org/panel/1.7.1/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.1/dist/panel.min.js\"];\n",
+ " const js_urls = [\"https://cdn.holoviz.org/panel/1.8.4/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.8.1.min.js\", \"https://cdn.holoviz.org/panel/1.8.4/dist/panel.min.js\"];\n",
" const js_modules = [];\n",
" const js_exports = {};\n",
" const css_urls = [];\n",
@@ -1141,24 +1119,13 @@
" }\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",
+ " root._bokeh_is_initializing = false;\n",
" }\n",
"\n",
" function load_or_wait() {\n",
@@ -1175,24 +1142,35 @@
" 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",
+ " 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",
+ " root._bokeh_is_initializing = true;\n",
+ " root._bokeh_onload_callbacks = [];\n",
+ " const bokeh_loaded = Bokeh != null && ((Bokeh.version === version && Bokeh.Panel) || (Bokeh.versions?.has(version) && Bokeh.versions.get(version).Panel));\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",
+ " load_libs(css_urls, js_urls, js_modules, js_exports, Bokeh, function() {\n",
" console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
" run_inline_js();\n",
+ " if (Bokeh != undefined && !reloading) {\n",
+ " const NewBokeh = root.Bokeh;\n",
+ " if (Bokeh.versions === undefined) {\n",
+ " Bokeh.versions = new Map();\n",
+ " }\n",
+ " if (NewBokeh.version !== Bokeh.version) {\n",
+ " Bokeh[NewBokeh.version] = NewBokeh;\n",
+ " Bokeh.versions.set(NewBokeh.version, NewBokeh);\n",
+ " }\n",
+ " root.Bokeh = Bokeh;\n",
+ " }\n",
" });\n",
" }\n",
" }\n",
@@ -1201,7 +1179,7 @@
" 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.1/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.1/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));"
+ "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n const force = true;\n const version = '3.8.1'.replace('rc', '-rc.').replace('.dev', '-dev.');\n const reloading = false;\n const Bokeh = root.Bokeh;\n const BK_RE = /^https:\\/\\/cdn\\.bokeh\\.org\\/bokeh\\/(release|dev)\\/bokeh-/;\n const PN_RE = /^https:\\/\\/cdn\\.holoviz\\.org\\/panel\\/[^/]+\\/dist\\/panel/i;\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, Bokeh, 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 const shouldSkip = skip.includes(escaped) || existing_scripts.includes(escaped)\n const isBokehOrPanel = BK_RE.test(escaped) || PN_RE.test(escaped)\n const missingOrBroken = Bokeh == null || Bokeh.Panel == null || (Bokeh.version != version && !Bokeh.versions?.has(version)) || Bokeh.versions?.get(version).Panel == null;\n if (shouldSkip && !(isBokehOrPanel && missingOrBroken)) {\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.8.4/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.8.1.min.js\", \"https://cdn.holoviz.org/panel/1.8.4/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 } 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 = Bokeh != null && ((Bokeh.version === version && Bokeh.Panel) || (Bokeh.versions?.has(version) && Bokeh.versions.get(version).Panel));\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, Bokeh, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n if (Bokeh != undefined && !reloading) {\n const NewBokeh = root.Bokeh;\n if (Bokeh.versions === undefined) {\n Bokeh.versions = new Map();\n }\n if (NewBokeh.version !== Bokeh.version) {\n Bokeh[NewBokeh.version] = NewBokeh;\n Bokeh.versions.set(NewBokeh.version, NewBokeh);\n }\n root.Bokeh = Bokeh;\n }\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"
@@ -1458,17 +1436,17 @@
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
- "\n",
- " \n",
+ "\n",
+ " \n",
"\n",
""
+ ]
+ },
+ "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 version = '3.8.1'.replace('rc', '-rc.').replace('.dev', '-dev.');\n",
+ " const reloading = false;\n",
+ " const Bokeh = root.Bokeh;\n",
+ " const BK_RE = /^https:\\/\\/cdn\\.bokeh\\.org\\/bokeh\\/(release|dev)\\/bokeh-/;\n",
+ " const PN_RE = /^https:\\/\\/cdn\\.holoviz\\.org\\/panel\\/[^/]+\\/dist\\/panel/i;\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, Bokeh, 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",
+ " const shouldSkip = skip.includes(escaped) || existing_scripts.includes(escaped)\n",
+ " const isBokehOrPanel = BK_RE.test(escaped) || PN_RE.test(escaped)\n",
+ " const missingOrBroken = Bokeh == null || Bokeh.Panel == null || (Bokeh.version != version && !Bokeh.versions?.has(version)) || Bokeh.versions?.get(version).Panel == null;\n",
+ " if (shouldSkip && !(isBokehOrPanel && missingOrBroken)) {\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.8.4/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.8.1.min.js\", \"https://cdn.holoviz.org/panel/1.8.4/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",
+ " } 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 = Bokeh != null && ((Bokeh.version === version && Bokeh.Panel) || (Bokeh.versions?.has(version) && Bokeh.versions.get(version).Panel));\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, Bokeh, function() {\n",
+ " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
+ " run_inline_js();\n",
+ " if (Bokeh != undefined && !reloading) {\n",
+ " const NewBokeh = root.Bokeh;\n",
+ " if (Bokeh.versions === undefined) {\n",
+ " Bokeh.versions = new Map();\n",
+ " }\n",
+ " if (NewBokeh.version !== Bokeh.version) {\n",
+ " Bokeh[NewBokeh.version] = NewBokeh;\n",
+ " Bokeh.versions.set(NewBokeh.version, NewBokeh);\n",
+ " }\n",
+ " root.Bokeh = Bokeh;\n",
+ " }\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 version = '3.8.1'.replace('rc', '-rc.').replace('.dev', '-dev.');\n const reloading = false;\n const Bokeh = root.Bokeh;\n const BK_RE = /^https:\\/\\/cdn\\.bokeh\\.org\\/bokeh\\/(release|dev)\\/bokeh-/;\n const PN_RE = /^https:\\/\\/cdn\\.holoviz\\.org\\/panel\\/[^/]+\\/dist\\/panel/i;\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, Bokeh, 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 const shouldSkip = skip.includes(escaped) || existing_scripts.includes(escaped)\n const isBokehOrPanel = BK_RE.test(escaped) || PN_RE.test(escaped)\n const missingOrBroken = Bokeh == null || Bokeh.Panel == null || (Bokeh.version != version && !Bokeh.versions?.has(version)) || Bokeh.versions?.get(version).Panel == null;\n if (shouldSkip && !(isBokehOrPanel && missingOrBroken)) {\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.8.4/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.8.1.min.js\", \"https://cdn.holoviz.org/panel/1.8.4/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 } 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 = Bokeh != null && ((Bokeh.version === version && Bokeh.Panel) || (Bokeh.versions?.has(version) && Bokeh.versions.get(version).Panel));\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, Bokeh, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n if (Bokeh != undefined && !reloading) {\n const NewBokeh = root.Bokeh;\n if (Bokeh.versions === undefined) {\n Bokeh.versions = new Map();\n }\n if (NewBokeh.version !== Bokeh.version) {\n Bokeh[NewBokeh.version] = NewBokeh;\n Bokeh.versions.set(NewBokeh.version, NewBokeh);\n }\n root.Bokeh = Bokeh;\n }\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",
+ " console.log(message)\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",
+ " comm.open();\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 console.log(message)\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 comm.open();\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": "0dfd6995-9f17-45d4-8c42-1a29c4fc2d27"
+ }
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "from pystac_client import Client\n",
+ "import pandas as pd\n",
+ "import odc.stac\n",
+ "\n",
+ "import rioxarray # noqa\n",
+ "import hvplot.xarray # noqa"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17891bda-af2b-443d-80db-71cfb3d47823",
+ "metadata": {
+ "tags": []
+ },
+ "source": [
+ "## Declare your collection of interest\n",
+ "\n",
+ "You can discover available collections the following ways:\n",
+ "\n",
+ "* Programmatically: see example in the `list-collections.ipynb` notebook\n",
+ "* JSON API: https://openveda.cloud/api/stac/collections\n",
+ "* STAC Browser: https://openveda.cloud"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "b0b2f0c2-b734-493d-ab3e-47ec65de0da5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "STAC_API_URL = \"https://openveda.cloud/api/stac/\"\n",
+ "collection = \"no2-monthly\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fc316ef9",
+ "metadata": {},
+ "source": [
+ "## Discover items in collection for region and time of interest\n",
+ "\n",
+ "Use `pystac_client` to search the STAC collection for a particular area of interest within specified datetime bounds."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "cbc79250-9ebe-4ab2-b200-07e2d5262113",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "china_bbox = [\n",
+ " 73.675,\n",
+ " 18.198,\n",
+ " 135.026,\n",
+ " 53.459,\n",
+ "]\n",
+ "datetime = \"2000-01-01/2025-07-25\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "8efe9b34",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Found 93 items\n"
+ ]
+ }
+ ],
+ "source": [
+ "catalog = Client.open(STAC_API_URL)\n",
+ "search = catalog.search(\n",
+ " bbox=china_bbox, datetime=datetime, collections=[collection], limit=1000\n",
+ ")\n",
+ "item_collection = search.item_collection()\n",
+ "print(f\"Found {len(item_collection)} items\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "beacc93f",
+ "metadata": {},
+ "source": [
+ "## Read data\n",
+ "\n",
+ "Read in data using `xarray` using a combination of `xpystac`, `odc-stac`, and `rasterio`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "4d2a4d87-58ec-4ccf-964a-2734877b8aa4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds = odc.stac.load(item_collection, chunks={\"latitude\": \"auto\", \"longitude\": \"auto\"})\n",
+ "da = ds['cog_default']\n",
+ "da = da.where(da != da.nodata)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a0a59a7f-b3bc-4783-8da5-c455acaf02a6",
+ "metadata": {},
+ "source": [
+ "## Clip the data to the bounding box for China"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "92bed8e4-dcf0-4226-8d1c-7ca66460ac52",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "<xarray.DataArray 'cog_default' (time: 93, latitude: 354, longitude: 615)> Size: 81MB\n",
+ "dask.array<getitem, shape=(93, 354, 615), dtype=float32, chunksize=(1, 354, 615), chunktype=numpy.ndarray>\n",
+ "Coordinates:\n",
+ " * time (time) datetime64[ns] 744B 2016-01-01 2016-02-01 ... 2023-09-01\n",
+ " * latitude (latitude) float64 3kB 53.45 53.35 53.25 ... 18.35 18.25 18.15\n",
+ " * longitude (longitude) float64 5kB 73.65 73.75 73.85 ... 134.9 135.0 135.1\n",
+ " spatial_ref int64 8B 0\n",
+ "Attributes:\n",
+ " _FillValue: -1.2676506e+30
"
+ ],
+ "text/plain": [
+ " Size: 81MB\n",
+ "dask.array\n",
+ "Coordinates:\n",
+ " * time (time) datetime64[ns] 744B 2016-01-01 2016-02-01 ... 2023-09-01\n",
+ " * latitude (latitude) float64 3kB 53.45 53.35 53.25 ... 18.35 18.25 18.15\n",
+ " * longitude (longitude) float64 5kB 73.65 73.75 73.85 ... 134.9 135.0 135.1\n",
+ " spatial_ref int64 8B 0\n",
+ "Attributes:\n",
+ " _FillValue: -1.2676506e+30"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Subset to Bounding Box for China\n",
+ "subset = da.rio.clip_box(*china_bbox)\n",
+ "subset"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2292a792-5859-4fc1-83b8-06d48d94197b",
+ "metadata": {},
+ "source": [
+ "## Aggregate the data\n",
+ "\n",
+ "Calculate the mean at each time across regional data. Note this is the first time that the data is actually loaded."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "ab7632e9-ea71-482d-b8f6-7c987f20fdfa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "means = subset.mean(dim=(\"longitude\", \"latitude\")).compute()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7ff1d2f1-1e1b-4d01-9164-f7d0bcb86e7b",
+ "metadata": {},
+ "source": [
+ "Plot the mean monthly NO2 using `hvplot`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "b39bf4ae-1f5d-4e07-ba5c-2837cdb13999",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {},
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "application/vnd.holoviews_exec.v0+json": "",
+ "text/html": [
+ "\n",
+ " \n",
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ":Curve [time] (cog_default)"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {
+ "application/vnd.holoviews_exec.v0+json": {
+ "id": "795b4afd-b5a6-4835-b4d2-e5707416f8d3"
+ }
+ },
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "means.hvplot.line(x=\"time\", ylabel=\"NO2\", title=\"Mean Monthly NO2 in China\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5fbb5503-6d73-452d-8ef6-1c29b3af7be3",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "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.12.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/user-guide/notebooks/quickstarts/timeseries-rioxarray-stackstac.ipynb b/user-guide/notebooks/quickstarts/timeseries-rioxarray-stackstac.ipynb
deleted file mode 100644
index f8f6337d..00000000
--- a/user-guide/notebooks/quickstarts/timeseries-rioxarray-stackstac.ipynb
+++ /dev/null
@@ -1,2520 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "raw",
- "id": "f43a8dbd-1a62-49c1-b682-f9353b822675",
- "metadata": {},
- "source": [
- "---\n",
- "title: Calculate timeseries from COGs\n",
- "description: Demonstrates how to aggregate COGs using `pystac_client`, `rioxarray`, and `stackstac`\n",
- "author: Aimee Barciauskas, Julia Signell\n",
- "date: February 1, 2023\n",
- "execute:\n",
- " freeze: true\n",
- " cache: true\n",
- "---"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "81b36cd7-5e66-41bd-bc79-cf75e580293b",
- "metadata": {},
- "source": [
- "## Run this notebook\n",
- "\n",
- "You can launch this notebook in VEDA JupyterHub by clicking the link below.\n",
- "\n",
- "[Launch in VEDA JupyterHub (requires access)](https://hub.openveda.cloud/hub/user-redirect/git-pull?repo=https://github.com/NASA-IMPACT/veda-docs&urlpath=lab/tree/veda-docs/user-guide/notebooks/quickstarts/timeseries-rioxarray-stackstac.ipynb&branch=main) \n",
- "\n",
- "Learn more
\n",
- " \n",
- "### Inside the Hub\n",
- "\n",
- "This notebook was written on the VEDA JupyterHub and as such is designed to be run on a jupyterhub which is associated with an AWS IAM role which has been granted permissions to the VEDA data store via its bucket policy. The instance used provided 16GB of RAM. \n",
- "\n",
- "See (VEDA Analytics JupyterHub Access)[https://nasa-impact.github.io/veda-docs/veda-jh-access.html] for information about how to gain access.\n",
- "\n",
- "### Outside the Hub\n",
- "\n",
- "The data is in a protected bucket. Please request access by emailng aimee@developmentseed.org or alexandra@developmentseed.org and providing your affiliation, interest in or expected use of the dataset and an AWS IAM role or user Amazon Resource Name (ARN). The team will help you configure the cognito client.\n",
- "\n",
- "You should then run:\n",
- "\n",
- "```\n",
- "%run -i 'cognito_login.py'\n",
- "```\n",
- " \n",
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "id": "0af28e0e-aed3-4d11-9ebb-dc64e2cc69f0",
- "metadata": {},
- "source": [
- "## Approach\n",
- "\n",
- " 1. Use `pystac_client` to open the STAC catalog and retrieve the items in the collection\n",
- " 2. Use `stackstac` to create an `xarray` dataset containing all the items cropped to AOI\n",
- " 3. Calculate the mean for each timestep over the AOI"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "aadabf9e",
- "metadata": {},
- "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.1/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.1/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.1/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.1/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",
- " console.log(message)\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",
- " comm.open();\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 console.log(message)\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 comm.open();\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": "56fb3995-eec9-4772-a6db-3ed7f0297196"
- }
- },
- "output_type": "display_data"
- }
- ],
- "source": [
- "from pystac_client import Client\n",
- "import pandas as pd\n",
- "import stackstac\n",
- "\n",
- "import rioxarray # noqa\n",
- "import hvplot.xarray # noqa"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "17891bda-af2b-443d-80db-71cfb3d47823",
- "metadata": {
- "tags": []
- },
- "source": [
- "## Declare your collection of interest\n",
- "\n",
- "You can discover available collections the following ways:\n",
- "\n",
- "* Programmatically: see example in the `list-collections.ipynb` notebook\n",
- "* JSON API: https://openveda.cloud/api/stac/collections\n",
- "* STAC Browser: https://openveda.cloud"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "b0b2f0c2-b734-493d-ab3e-47ec65de0da5",
- "metadata": {},
- "outputs": [],
- "source": [
- "STAC_API_URL = \"https://openveda.cloud/api/stac/\"\n",
- "collection = \"no2-monthly\""
- ]
- },
- {
- "cell_type": "markdown",
- "id": "fc316ef9",
- "metadata": {},
- "source": [
- "## Discover items in collection for region and time of interest\n",
- "\n",
- "Use `pystac_client` to search the STAC collection for a particular area of interest within specified datetime bounds."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "cbc79250-9ebe-4ab2-b200-07e2d5262113",
- "metadata": {},
- "outputs": [],
- "source": [
- "china_bbox = [\n",
- " 73.675,\n",
- " 18.198,\n",
- " 135.026,\n",
- " 53.459,\n",
- "]\n",
- "datetime = \"2000-01-01/2025-07-25\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "8efe9b34",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Found 93 items\n"
- ]
- }
- ],
- "source": [
- "catalog = Client.open(STAC_API_URL)\n",
- "search = catalog.search(\n",
- " bbox=china_bbox, datetime=datetime, collections=[collection], limit=1000\n",
- ")\n",
- "item_collection = search.item_collection()\n",
- "print(f\"Found {len(item_collection)} items\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "beacc93f",
- "metadata": {},
- "source": [
- "## Read data\n",
- "\n",
- "Read in data using `xarray` using a combination of `xpystac`, `stackstac`, and `rasterio`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "id": "4d2a4d87-58ec-4ccf-964a-2734877b8aa4",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "<xarray.DataArray 'stackstac-707c2fec3a4bde6be0d838dc97f60ec1' (time: 93,\n",
- " y: 1800, x: 3600)> Size: 5GB\n",
- "dask.array<getitem, shape=(93, 1800, 3600), dtype=float64, chunksize=(1, 1024, 1024), chunktype=numpy.ndarray>\n",
- "Coordinates: (12/17)\n",
- " id (time) <U37 14kB 'OMI_trno2_0.10x0.10_202309_Col3_V4.nc' ...\n",
- " band <U11 44B 'cog_default'\n",
- " * x (x) float64 29kB -180.0 -179.9 -179.8 ... 179.7 179.8 179.9\n",
- " * y (y) float64 14kB 90.0 89.9 89.8 89.7 ... -89.7 -89.8 -89.9\n",
- " start_datetime (time) <U25 9kB '2023-09-01T00:00:00+00:00' ... '2016-01-...\n",
- " end_datetime (time) <U25 9kB '2023-09-30T00:00:00+00:00' ... '2016-01-...\n",
- " ... ...\n",
- " proj:code <U9 36B 'EPSG:4326'\n",
- " title <U17 68B 'Default COG Layer'\n",
- " proj:shape object 8B {1800, 3600}\n",
- " description <U47 188B 'Cloud optimized default layer to display on map'\n",
- " epsg int64 8B 4326\n",
- " * time (time) datetime64[ns, UTC] 744B 2023-09-01T00:00:00+00:00...\n",
- "Attributes:\n",
- " spec: RasterSpec(epsg=4326, bounds=(-180.0, -90.0, 180.0, 90.0), r...\n",
- " crs: epsg:4326\n",
- " transform: | 0.10, 0.00,-180.00|\\n| 0.00,-0.10, 90.00|\\n| 0.00, 0.00, 1...\n",
- " resolution: 0.1"
- ],
- "text/plain": [
- " Size: 5GB\n",
- "dask.array\n",
- "Coordinates: (12/17)\n",
- " id (time) \n",
- "<xarray.DataArray 'stackstac-707c2fec3a4bde6be0d838dc97f60ec1' (time: 93,\n",
- " y: 354, x: 614)> Size: 162MB\n",
- "dask.array<getitem, shape=(93, 354, 614), dtype=float64, chunksize=(1, 354, 535), chunktype=numpy.ndarray>\n",
- "Coordinates: (12/18)\n",
- " id (time) <U37 14kB 'OMI_trno2_0.10x0.10_202309_Col3_V4.nc' ...\n",
- " band <U11 44B 'cog_default'\n",
- " * x (x) float64 5kB 73.7 73.8 73.9 74.0 ... 134.8 134.9 135.0\n",
- " * y (y) float64 3kB 53.5 53.4 53.3 53.2 ... 18.5 18.4 18.3 18.2\n",
- " start_datetime (time) <U25 9kB '2023-09-01T00:00:00+00:00' ... '2016-01-...\n",
- " end_datetime (time) <U25 9kB '2023-09-30T00:00:00+00:00' ... '2016-01-...\n",
- " ... ...\n",
- " title <U17 68B 'Default COG Layer'\n",
- " proj:shape object 8B {1800, 3600}\n",
- " description <U47 188B 'Cloud optimized default layer to display on map'\n",
- " epsg int64 8B 4326\n",
- " * time (time) datetime64[ns, UTC] 744B 2023-09-01T00:00:00+00:00...\n",
- " spatial_ref int64 8B 0\n",
- "Attributes:\n",
- " spec: RasterSpec(epsg=4326, bounds=(-180.0, -90.0, 180.0, 90.0), r...\n",
- " resolution: 0.1 "
- ],
- "text/plain": [
- " Size: 162MB\n",
- "dask.array\n",
- "Coordinates: (12/18)\n",
- " id (time) \n",
- " \n",
- "\n",
- ""
- ],
- "text/plain": [
- ":Curve [time] (stackstac-707c2fec3a4bde6be0d838dc97f60ec1)"
- ]
- },
- "execution_count": 8,
- "metadata": {
- "application/vnd.holoviews_exec.v0+json": {
- "id": "d9f29bc7-9cee-46ee-9c79-cc968f11215c"
- }
- },
- "output_type": "execute_result"
- }
- ],
- "source": [
- "means.hvplot.line(x=\"time\", ylabel=\"NO2\", title=\"Mean Monthly NO2 in China\")"
- ]
- }
- ],
- "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.12.10"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/user-guide/notebooks/quickstarts/visualize-multiple-times.ipynb b/user-guide/notebooks/quickstarts/visualize-multiple-times.ipynb
index ce4a1f68..51317ec8 100644
--- a/user-guide/notebooks/quickstarts/visualize-multiple-times.ipynb
+++ b/user-guide/notebooks/quickstarts/visualize-multiple-times.ipynb
@@ -7,7 +7,7 @@
"source": [
"---\n",
"title: Open and visualize COGs\n",
- "description: Demonstrates how to visualize COGs using `pystac_client`, `rioxarray`, `stackstac`, and `hvplot`\n",
+ "description: Demonstrates how to visualize COGs using `pystac_client`, `rioxarray`, `odc-stac`, and `hvplot`\n",
"author: Julia Signell\n",
"date: February 2, 2023\n",
"execute:\n",
@@ -58,7 +58,7 @@
"## Approach\n",
"\n",
" 1. Use `pystac_client` to open the STAC catalog and retrieve the items in the collection\n",
- " 2. Use `stackstac` to create an `xarray` dataset containing all the items\n",
+ " 2. Use `odc-stac` to create an `xarray` dataset containing all the items\n",
" 3. Use `rioxarray` to crop data to AOI\n",
" 3. Use `hvplot` to render the COG at every timestep"
]
@@ -82,8 +82,8 @@
"\n",
"/* Override VSCode background color */\n",
".cell-output-ipywidget-background:has(\n",
- " > .cell-output-ipywidget-background > .lm-Widget > *[data-root-id]\n",
- " ),\n",
+ " > .cell-output-ipywidget-background > .lm-Widget > *[data-root-id]\n",
+ "),\n",
".cell-output-ipywidget-background:has(> .lm-Widget > *[data-root-id]) {\n",
" background-color: transparent !important;\n",
"}\n",
@@ -102,9 +102,11 @@
" }\n",
"\n",
" const force = true;\n",
- " const py_version = '3.7.3'.replace('rc', '-rc.').replace('.dev', '-dev.');\n",
+ " const version = '3.8.1'.replace('rc', '-rc.').replace('.dev', '-dev.');\n",
" const reloading = false;\n",
" const Bokeh = root.Bokeh;\n",
+ " const BK_RE = /^https:\\/\\/cdn\\.bokeh\\.org\\/bokeh\\/(release|dev)\\/bokeh-/;\n",
+ " const PN_RE = /^https:\\/\\/cdn\\.holoviz\\.org\\/panel\\/[^/]+\\/dist\\/panel/i;\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",
@@ -124,7 +126,7 @@
" console.debug(\"Bokeh: all callbacks have finished\");\n",
" }\n",
"\n",
- " function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n",
+ " function load_libs(css_urls, js_urls, js_modules, js_exports, Bokeh, callback) {\n",
" if (css_urls == null) css_urls = [];\n",
" if (js_urls == null) js_urls = [];\n",
" if (js_modules == null) js_modules = [];\n",
@@ -198,7 +200,10 @@
" 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",
+ " const shouldSkip = skip.includes(escaped) || existing_scripts.includes(escaped)\n",
+ " const isBokehOrPanel = BK_RE.test(escaped) || PN_RE.test(escaped)\n",
+ " const missingOrBroken = Bokeh == null || Bokeh.Panel == null || (Bokeh.version != version && !Bokeh.versions?.has(version)) || Bokeh.versions?.get(version).Panel == null;\n",
+ " if (shouldSkip && !(isBokehOrPanel && missingOrBroken)) {\n",
" if (!window.requirejs) {\n",
" on_load();\n",
" }\n",
@@ -262,7 +267,7 @@
" document.body.appendChild(element);\n",
" }\n",
"\n",
- " const js_urls = [\"https://cdn.holoviz.org/panel/1.7.1/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.1/dist/panel.min.js\"];\n",
+ " const js_urls = [\"https://cdn.holoviz.org/panel/1.8.4/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.8.1.min.js\", \"https://cdn.holoviz.org/panel/1.8.4/dist/panel.min.js\"];\n",
" const js_modules = [];\n",
" const js_exports = {};\n",
" const css_urls = [];\n",
@@ -283,24 +288,13 @@
" }\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",
+ " root._bokeh_is_initializing = false;\n",
" }\n",
"\n",
" function load_or_wait() {\n",
@@ -317,24 +311,35 @@
" 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",
+ " 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",
+ " root._bokeh_is_initializing = true;\n",
+ " root._bokeh_onload_callbacks = [];\n",
+ " const bokeh_loaded = Bokeh != null && ((Bokeh.version === version && Bokeh.Panel) || (Bokeh.versions?.has(version) && Bokeh.versions.get(version).Panel));\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",
+ " load_libs(css_urls, js_urls, js_modules, js_exports, Bokeh, function() {\n",
" console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
" run_inline_js();\n",
+ " if (Bokeh != undefined && !reloading) {\n",
+ " const NewBokeh = root.Bokeh;\n",
+ " if (Bokeh.versions === undefined) {\n",
+ " Bokeh.versions = new Map();\n",
+ " }\n",
+ " if (NewBokeh.version !== Bokeh.version) {\n",
+ " Bokeh[NewBokeh.version] = NewBokeh;\n",
+ " Bokeh.versions.set(NewBokeh.version, NewBokeh);\n",
+ " }\n",
+ " root.Bokeh = Bokeh;\n",
+ " }\n",
" });\n",
" }\n",
" }\n",
@@ -343,7 +348,7 @@
" 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.1/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.1/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));"
+ "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n const force = true;\n const version = '3.8.1'.replace('rc', '-rc.').replace('.dev', '-dev.');\n const reloading = false;\n const Bokeh = root.Bokeh;\n const BK_RE = /^https:\\/\\/cdn\\.bokeh\\.org\\/bokeh\\/(release|dev)\\/bokeh-/;\n const PN_RE = /^https:\\/\\/cdn\\.holoviz\\.org\\/panel\\/[^/]+\\/dist\\/panel/i;\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, Bokeh, 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 const shouldSkip = skip.includes(escaped) || existing_scripts.includes(escaped)\n const isBokehOrPanel = BK_RE.test(escaped) || PN_RE.test(escaped)\n const missingOrBroken = Bokeh == null || Bokeh.Panel == null || (Bokeh.version != version && !Bokeh.versions?.has(version)) || Bokeh.versions?.get(version).Panel == null;\n if (shouldSkip && !(isBokehOrPanel && missingOrBroken)) {\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.8.4/dist/bundled/reactiveesm/es-module-shims@^1.10.0/dist/es-module-shims.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.8.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.8.1.min.js\", \"https://cdn.holoviz.org/panel/1.8.4/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 } 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 = Bokeh != null && ((Bokeh.version === version && Bokeh.Panel) || (Bokeh.versions?.has(version) && Bokeh.versions.get(version).Panel));\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, Bokeh, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n if (Bokeh != undefined && !reloading) {\n const NewBokeh = root.Bokeh;\n if (Bokeh.versions === undefined) {\n Bokeh.versions = new Map();\n }\n if (NewBokeh.version !== Bokeh.version) {\n Bokeh[NewBokeh.version] = NewBokeh;\n Bokeh.versions.set(NewBokeh.version, NewBokeh);\n }\n root.Bokeh = Bokeh;\n }\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"
@@ -600,17 +605,17 @@
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
- "\n",
- " \n",
+ "\n",
+ " \n",
"\n",
"