Skip to content

Instantly share code, notes, and snippets.

@ropitz
Last active April 1, 2022 15:10
Show Gist options
  • Save ropitz/d54ca08e86fc680476836a363604d45f to your computer and use it in GitHub Desktop.
Save ropitz/d54ca08e86fc680476836a363604d45f to your computer and use it in GitHub Desktop.
soil-concept-network-viz.ipynb
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/ropitz/d54ca08e86fc680476836a363604d45f/soil-concept-network-viz.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"tags": [
"hide_input"
],
"id": "p80_FwLQUsQ7"
},
"source": [
"# Make an Interactive Network Visualization with Bokeh"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "mMIGpbGQUsQ9"
},
"source": [
"## Dataset"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "hnNogs8WUsRD"
},
"source": [
"## Import Libraries"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"id": "is8MRV-zUsRD"
},
"outputs": [],
"source": [
"import pandas as pd\n",
"import networkx\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "UFTctB3TUsRE"
},
"source": [
"## Install and Import Bokeh"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"id": "Fda5ym45UsRE"
},
"outputs": [],
"source": [
"#!pip install bokeh"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"id": "0V6FsPrXUsRF"
},
"outputs": [],
"source": [
"from bokeh.io import output_notebook, show, save"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "moUA6hhbUsRF"
},
"source": [
"To view interactive Bokeh visualizations in a Jupyter notebook, you need to run this cell:"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"id": "ZSk6DQEZUsRF"
},
"outputs": [],
"source": [
"output_notebook()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "nS1fMJdcUsRG"
},
"source": [
"## Create Network From Pandas DataFrame"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"id": "gz-Z54TAUsRG"
},
"outputs": [],
"source": [
"got_df = pd.read_csv('https://raw.githubusercontent.com/ropitz/soils/main/summary_concept_maps.csv')"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 655
},
"id": "-MfcphulUsRH",
"outputId": "e8508546-ff29-4c25-daf0-840813e7c4e7"
},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" technica concept\n",
"0 Acidity (pH) Capturing Critical Zone processes\n",
"1 Acidity (pH) Erosion\n",
"2 Acidity (pH) Evidencing ecosystem processes\n",
"3 Acidity (pH) Evidencing ecosystem processes\n",
"4 Acidity (pH) Evidencing human-ecosystem interactions\n",
".. ... ...\n",
"189 Texture Supporting a living ecosystem\n",
"190 Texture Sustaining animal health\n",
"191 Texture Sustaining human health\n",
"192 Texture Sustaining plant health\n",
"193 Texture Sustaining plant health\n",
"\n",
"[194 rows x 2 columns]"
],
"text/html": [
"\n",
" <div id=\"df-a6226faf-3b7f-4007-96af-2368b8a4894c\">\n",
" <div class=\"colab-df-container\">\n",
" <div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>technica</th>\n",
" <th>concept</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Acidity (pH)</td>\n",
" <td>Capturing Critical Zone processes</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Acidity (pH)</td>\n",
" <td>Erosion</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Acidity (pH)</td>\n",
" <td>Evidencing ecosystem processes</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Acidity (pH)</td>\n",
" <td>Evidencing ecosystem processes</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Acidity (pH)</td>\n",
" <td>Evidencing human-ecosystem interactions</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>189</th>\n",
" <td>Texture</td>\n",
" <td>Supporting a living ecosystem</td>\n",
" </tr>\n",
" <tr>\n",
" <th>190</th>\n",
" <td>Texture</td>\n",
" <td>Sustaining animal health</td>\n",
" </tr>\n",
" <tr>\n",
" <th>191</th>\n",
" <td>Texture</td>\n",
" <td>Sustaining human health</td>\n",
" </tr>\n",
" <tr>\n",
" <th>192</th>\n",
" <td>Texture</td>\n",
" <td>Sustaining plant health</td>\n",
" </tr>\n",
" <tr>\n",
" <th>193</th>\n",
" <td>Texture</td>\n",
" <td>Sustaining plant health</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>194 rows × 2 columns</p>\n",
"</div>\n",
" <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-a6226faf-3b7f-4007-96af-2368b8a4894c')\"\n",
" title=\"Convert this dataframe to an interactive table.\"\n",
" style=\"display:none;\">\n",
" \n",
" <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
" width=\"24px\">\n",
" <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
" <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
" </svg>\n",
" </button>\n",
" \n",
" <style>\n",
" .colab-df-container {\n",
" display:flex;\n",
" flex-wrap:wrap;\n",
" gap: 12px;\n",
" }\n",
"\n",
" .colab-df-convert {\n",
" background-color: #E8F0FE;\n",
" border: none;\n",
" border-radius: 50%;\n",
" cursor: pointer;\n",
" display: none;\n",
" fill: #1967D2;\n",
" height: 32px;\n",
" padding: 0 0 0 0;\n",
" width: 32px;\n",
" }\n",
"\n",
" .colab-df-convert:hover {\n",
" background-color: #E2EBFA;\n",
" box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
" fill: #174EA6;\n",
" }\n",
"\n",
" [theme=dark] .colab-df-convert {\n",
" background-color: #3B4455;\n",
" fill: #D2E3FC;\n",
" }\n",
"\n",
" [theme=dark] .colab-df-convert:hover {\n",
" background-color: #434B5C;\n",
" box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
" filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
" fill: #FFFFFF;\n",
" }\n",
" </style>\n",
"\n",
" <script>\n",
" const buttonEl =\n",
" document.querySelector('#df-a6226faf-3b7f-4007-96af-2368b8a4894c button.colab-df-convert');\n",
" buttonEl.style.display =\n",
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
"\n",
" async function convertToInteractive(key) {\n",
" const element = document.querySelector('#df-a6226faf-3b7f-4007-96af-2368b8a4894c');\n",
" const dataTable =\n",
" await google.colab.kernel.invokeFunction('convertToInteractive',\n",
" [key], {});\n",
" if (!dataTable) return;\n",
"\n",
" const docLinkHtml = 'Like what you see? Visit the ' +\n",
" '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
" + ' to learn more about interactive tables.';\n",
" element.innerHTML = '';\n",
" dataTable['output_type'] = 'display_data';\n",
" await google.colab.output.renderOutput(dataTable, element);\n",
" const docLink = document.createElement('div');\n",
" docLink.innerHTML = docLinkHtml;\n",
" element.appendChild(docLink);\n",
" }\n",
" </script>\n",
" </div>\n",
" </div>\n",
" "
]
},
"metadata": {},
"execution_count": 43
}
],
"source": [
"got_df"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "hxmC2P7tUsRH"
},
"source": [
"Then we make a network with `networkx.from_pandas_edgelist()`:"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"id": "xgwne9viUsRH"
},
"outputs": [],
"source": [
"G = networkx.from_pandas_edgelist(got_df, 'technica', 'concept')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6R5biQWGUsRH"
},
"source": [
"## Basic Network "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "rXiCBH94UsRH"
},
"source": [
"The code below shows how to make a basic network viz that includes Hover Tooltips (a text box that will display when a user hovers over nodes) as well as Zoom and Pan/Drag functionality.\n",
"\n",
"For more details about visualizing network graphs with Bokeh, see [the documentation](https://docs.bokeh.org/en/latest/docs/user_guide/graph.html?highlight=networks)."
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"id": "VwXy5892UsRI"
},
"outputs": [],
"source": [
"from bokeh.io import output_notebook, show, save\n",
"from bokeh.models import Range1d, Circle, ColumnDataSource, MultiLine\n",
"from bokeh.plotting import figure\n",
"from bokeh.plotting import from_networkx"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 617
},
"id": "NjOPEhiWUsRI",
"outputId": "9e1d903d-e16f-4ad0-e168-1ddd6d2a6233"
},
"outputs": [
{
"output_type": "display_data",
"data": {
"application/javascript": [
"\n",
"(function(root) {\n",
" function now() {\n",
" return new Date();\n",
" }\n",
"\n",
" var force = true;\n",
"\n",
" if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
" root._bokeh_onload_callbacks = [];\n",
" root._bokeh_is_loading = undefined;\n",
" }\n",
"\n",
" var JS_MIME_TYPE = 'application/javascript';\n",
" var HTML_MIME_TYPE = 'text/html';\n",
" var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
" var CLASS_NAME = 'output_bokeh rendered_html';\n",
"\n",
" /**\n",
" * Render data to the DOM node\n",
" */\n",
" function render(props, node) {\n",
" var script = document.createElement(\"script\");\n",
" node.appendChild(script);\n",
" }\n",
"\n",
" /**\n",
" * Handle when an output is cleared or removed\n",
" */\n",
" function handleClearOutput(event, handle) {\n",
" var cell = handle.cell;\n",
"\n",
" var id = cell.output_area._bokeh_element_id;\n",
" var server_id = cell.output_area._bokeh_server_id;\n",
" // Clean up Bokeh references\n",
" if (id != null && id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
"\n",
" if (server_id !== undefined) {\n",
" // Clean up Bokeh references\n",
" var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
" cell.notebook.kernel.execute(cmd, {\n",
" iopub: {\n",
" output: function(msg) {\n",
" var id = msg.content.text.trim();\n",
" if (id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
" }\n",
" }\n",
" });\n",
" // Destroy server and session\n",
" var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
" cell.notebook.kernel.execute(cmd);\n",
" }\n",
" }\n",
"\n",
" /**\n",
" * Handle when a new output is added\n",
" */\n",
" function handleAddOutput(event, handle) {\n",
" var output_area = handle.output_area;\n",
" var output = handle.output;\n",
"\n",
" // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
" if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n",
" return\n",
" }\n",
"\n",
" var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
"\n",
" if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
" toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
" // store reference to embed id on output_area\n",
" output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
" }\n",
" 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].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
" toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\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",
" function register_renderer(events, OutputArea) {\n",
"\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[toinsert.length - 1]);\n",
" element.append(toinsert);\n",
" return toinsert\n",
" }\n",
"\n",
" /* Handle when an output is cleared or removed */\n",
" events.on('clear_output.CodeCell', handleClearOutput);\n",
" events.on('delete.Cell', handleClearOutput);\n",
"\n",
" /* Handle when a new output is added */\n",
" events.on('output_added.OutputArea', handleAddOutput);\n",
"\n",
" /**\n",
" * Register the mime type and append_mime function with output_area\n",
" */\n",
" OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
" /* Is output safe? */\n",
" safe: true,\n",
" /* Index of renderer in `output_area.display_order` */\n",
" index: 0\n",
" });\n",
" }\n",
"\n",
" // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
" if (root.Jupyter !== undefined) {\n",
" var events = require('base/js/events');\n",
" var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
"\n",
" if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
" register_renderer(events, OutputArea);\n",
" }\n",
" }\n",
"\n",
" \n",
" if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
" root._bokeh_timeout = Date.now() + 5000;\n",
" root._bokeh_failed_load = false;\n",
" }\n",
"\n",
" var NB_LOAD_WARNING = {'data': {'text/html':\n",
" \"<div style='background-color: #fdd'>\\n\"+\n",
" \"<p>\\n\"+\n",
" \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
" \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
" \"</p>\\n\"+\n",
" \"<ul>\\n\"+\n",
" \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
" \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
" \"</ul>\\n\"+\n",
" \"<code>\\n\"+\n",
" \"from bokeh.resources import INLINE\\n\"+\n",
" \"output_notebook(resources=INLINE)\\n\"+\n",
" \"</code>\\n\"+\n",
" \"</div>\"}};\n",
"\n",
" function display_loaded() {\n",
" var el = document.getElementById(null);\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS is loading...\";\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
" }\n",
" } else if (Date.now() < root._bokeh_timeout) {\n",
" setTimeout(display_loaded, 100)\n",
" }\n",
" }\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, callback) {\n",
" if (css_urls == null) css_urls = [];\n",
" if (js_urls == null) js_urls = [];\n",
"\n",
" root._bokeh_onload_callbacks.push(callback);\n",
" if (root._bokeh_is_loading > 0) {\n",
" console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
" return null;\n",
" }\n",
" if (js_urls == null || js_urls.length === 0) {\n",
" run_callbacks();\n",
" return null;\n",
" }\n",
" console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
" root._bokeh_is_loading = css_urls.length + js_urls.length;\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",
"\n",
" function on_error(url) {\n",
" console.error(\"failed to load \" + url);\n",
" }\n",
"\n",
" for (let i = 0; i < css_urls.length; i++) {\n",
" const url = css_urls[i];\n",
" const element = document.createElement(\"link\");\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\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",
" }\n",
"\n",
" const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\": \"dM3QQsP+wXdHg42wTqW85BjZQdLNNIXqlPw/BgKoExPmTG7ZLML4EGqLMfqHT6ON\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\": \"8x57I4YuIfu8XyZfFo0XVr2WAT8EK4rh/uDe3wF7YuW2FNUSNEpJbsPaB1nJ2fz2\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\": \"3QTqdz9LyAm2i0sG5XTePsHec3UHWwVsrOL68SYRoAXsafvfAyqtQ+h440+qIBhS\"};\n",
"\n",
" for (let i = 0; i < js_urls.length; i++) {\n",
" const url = js_urls[i];\n",
" const element = document.createElement('script');\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\n",
" element.async = false;\n",
" element.src = url;\n",
" if (url in hashes) {\n",
" element.crossOrigin = \"anonymous\";\n",
" element.integrity = \"sha384-\" + hashes[url];\n",
" }\n",
" console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
" document.head.appendChild(element);\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",
" \n",
" var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\"];\n",
" var css_urls = [];\n",
" \n",
"\n",
" var inline_js = [\n",
" function(Bokeh) {\n",
" Bokeh.set_log_level(\"info\");\n",
" },\n",
" function(Bokeh) {\n",
" \n",
" \n",
" }\n",
" ];\n",
"\n",
" function run_inline_js() {\n",
" \n",
" if (root.Bokeh !== undefined || force === true) {\n",
" \n",
" for (var i = 0; i < inline_js.length; i++) {\n",
" inline_js[i].call(root, root.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",
" } else if (force !== true) {\n",
" var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n",
" cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
" }\n",
"\n",
" }\n",
"\n",
" if (root._bokeh_is_loading === 0) {\n",
" console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
" run_inline_js();\n",
" } else {\n",
" load_libs(css_urls, js_urls, function() {\n",
" console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
" run_inline_js();\n",
" });\n",
" }\n",
"}(window));"
],
"application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n \n\n \n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n var NB_LOAD_WARNING = {'data': {'text/html':\n \"<div style='background-color: #fdd'>\\n\"+\n \"<p>\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"</p>\\n\"+\n \"<ul>\\n\"+\n \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n \"<li>use INLINE resources instead, as so:</li>\\n\"+\n \"</ul>\\n\"+\n \"<code>\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"</code>\\n\"+\n \"</div>\"}};\n\n function display_loaded() {\n var el = document.getElementById(null);\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\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, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\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\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\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 }\n\n const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\": \"dM3QQsP+wXdHg42wTqW85BjZQdLNNIXqlPw/BgKoExPmTG7ZLML4EGqLMfqHT6ON\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\": \"8x57I4YuIfu8XyZfFo0XVr2WAT8EK4rh/uDe3wF7YuW2FNUSNEpJbsPaB1nJ2fz2\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\": \"3QTqdz9LyAm2i0sG5XTePsHec3UHWwVsrOL68SYRoAXsafvfAyqtQ+h440+qIBhS\"};\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n if (url in hashes) {\n element.crossOrigin = \"anonymous\";\n element.integrity = \"sha384-\" + hashes[url];\n }\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\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 \n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\"];\n var css_urls = [];\n \n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {\n \n \n }\n ];\n\n function run_inline_js() {\n \n if (root.Bokeh !== undefined || force === true) {\n \n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.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 } else if (force !== true) {\n var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));"
},
"metadata": {}
},
{
"output_type": "display_data",
"data": {
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
" <div class=\"bk-root\" id=\"ea2d8aaa-b19e-4086-bce9-62e33e03d162\" data-root-id=\"2202\"></div>\n"
]
},
"metadata": {}
},
{
"output_type": "display_data",
"data": {
"application/javascript": [
"(function(root) {\n",
" function embed_document(root) {\n",
" \n",
" var docs_json = {\"d3070b1d-16f4-48ca-8d4d-3949c26ced91\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"2211\"}],\"center\":[{\"id\":\"2214\"},{\"id\":\"2218\"}],\"left\":[{\"id\":\"2215\"}],\"renderers\":[{\"id\":\"2230\"}],\"title\":{\"id\":\"2203\"},\"toolbar\":{\"id\":\"2224\"},\"x_range\":{\"id\":\"2200\"},\"x_scale\":{\"id\":\"2207\"},\"y_range\":{\"id\":\"2201\"},\"y_scale\":{\"id\":\"2209\"}},\"id\":\"2202\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"2219\",\"type\":\"PanTool\"},{\"attributes\":{},\"id\":\"2370\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"2366\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"data_source\":{\"id\":\"2232\"},\"glyph\":{\"id\":\"2240\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"2234\"}},\"id\":\"2233\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"2369\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"2372\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"2212\",\"type\":\"BasicTicker\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"concept\",\"@index\"]]},\"id\":\"2223\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"2216\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"2371\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"formatter\":{\"id\":\"2369\"},\"major_label_policy\":{\"id\":\"2368\"},\"ticker\":{\"id\":\"2216\"}},\"id\":\"2215\",\"type\":\"LinearAxis\"},{\"attributes\":{\"source\":{\"id\":\"2236\"}},\"id\":\"2238\",\"type\":\"CDSView\"},{\"attributes\":{\"axis\":{\"id\":\"2211\"},\"ticker\":null},\"id\":\"2214\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"2359\",\"type\":\"NodesOnly\"},{\"attributes\":{\"end\":10.1,\"start\":-10.1},\"id\":\"2200\",\"type\":\"Range1d\"},{\"attributes\":{\"text\":\"soil health and heritage\"},\"id\":\"2203\",\"type\":\"Title\"},{\"attributes\":{\"source\":{\"id\":\"2232\"}},\"id\":\"2234\",\"type\":\"CDSView\"},{\"attributes\":{\"edge_renderer\":{\"id\":\"2237\"},\"inspection_policy\":{\"id\":\"2359\"},\"layout_provider\":{\"id\":\"2239\"},\"node_renderer\":{\"id\":\"2233\"},\"selection_policy\":{\"id\":\"2358\"}},\"id\":\"2230\",\"type\":\"GraphRenderer\"},{\"attributes\":{},\"id\":\"2221\",\"type\":\"SaveTool\"},{\"attributes\":{\"formatter\":{\"id\":\"2366\"},\"major_label_policy\":{\"id\":\"2365\"},\"ticker\":{\"id\":\"2212\"}},\"id\":\"2211\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"2358\",\"type\":\"NodesOnly\"},{\"attributes\":{},\"id\":\"2368\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"2373\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"graph_layout\":{\"Acidity (pH)\":[-2.6277755962403093,-0.14827198706558659],\"Archiving evidence of past ecosystem processes\":[4.829157205850568,-1.4941993379166745],\"Archiving evidence of past human activities\":[4.058774003447908,-0.36268782397972854],\"Bulk Density\":[-3.3825552125992395,6.266886457280649],\"Capturing Critical Zone processes\":[-1.9081825999280284,3.1505740870437355],\"Carbon Content\":[-0.11137456795375472,-0.7813193396576277],\"Colour\":[0.5923970291278003,5.072978514997036],\"Compaction\":[2.8181805377227493,3.9319068953930643],\"Erosion\":[-0.45767335941096904,3.4943714677155473],\"Evidencing ecosystem processes\":[-4.594303373946529,0.0839540843556384],\"Evidencing human-ecosystem interactions\":[3.0437218290068353,1.702662825157531],\"Forming rural landscapes\":[-2.5281688005419114,-6.293910477457642],\"Inorganic inclusions\":[7.029036890238247,2.2750293499913616],\"Modification\":[2.7734949783573164,-7.985982048253882],\"Moisture\":[-0.13276324712690882,-2.0396632180461656],\"Nutrient Content \":[1.2579908359211958,-2.16763371702539],\"Organic Matter Content\":[-0.9301295008073707,-1.2998148992373206],\"Organisms present\":[-10.0,1.0818168841132862],\"Porosity \":[1.420937048816935,0.23505161515289283],\"Regulating Climate\":[-4.804510727192356,-2.3627588162036997],\"Resistivity \":[8.727110007875153,-5.100364228291512],\"Restoration\":[2.602392374042473,-3.38428040723617],\"Storing Carbon\":[-1.783215054428406,2.0721532341782973],\"Structure\":[-1.1804143793927375,0.2383449301307497],\"Supporting a living ecosystem\":[-3.169213757014932,1.5786645653316054],\"Sustaining animal health\":[-0.03803120392784761,-4.107632559389041],\"Sustaining human health\":[3.1467024721798253,-0.06831649289452794],\"Sustaining plant health\":[0.11507997477469287,2.3218018123050213],\"Temperature\":[-6.3737703296714034,2.2810032414423698],\"Texture\":[1.6071065228210073,1.8096353880661813]}},\"id\":\"2239\",\"type\":\"StaticLayoutProvider\"},{\"attributes\":{},\"id\":\"2365\",\"type\":\"AllLabels\"},{\"attributes\":{\"data\":{\"end\":[\"Capturing Critical Zone processes\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Restoration\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Bulk Density\",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Carbon Content\",\"Colour\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Temperature\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Structure\",\"Temperature\",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Compaction\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining human health\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Resistivity \",\"Texture\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Resistivity \",\"Structure\",\"Texture\",\"Moisture\",\"Organic Matter Content\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Modification\",\"Nutrient Content \"],\"start\":[\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Restoration\",\"Restoration\",\"Restoration\",\"Restoration\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Moisture\",\"Modification\"]},\"selected\":{\"id\":\"2370\"},\"selection_policy\":{\"id\":\"2371\"}},\"id\":\"2236\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"end\":10.1,\"start\":-10.1},\"id\":\"2201\",\"type\":\"Range1d\"},{\"attributes\":{\"data_source\":{\"id\":\"2236\"},\"glyph\":{\"id\":\"2245\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"2238\"}},\"id\":\"2237\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"axis\":{\"id\":\"2215\"},\"dimension\":1,\"ticker\":null},\"id\":\"2218\",\"type\":\"Grid\"},{\"attributes\":{\"fill_color\":{\"value\":\"skyblue\"},\"size\":{\"value\":15}},\"id\":\"2240\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"2222\",\"type\":\"ResetTool\"},{\"attributes\":{\"line_alpha\":{\"value\":0.5}},\"id\":\"2245\",\"type\":\"MultiLine\"},{\"attributes\":{\"data\":{\"index\":[\"Acidity (pH)\",\"Capturing Critical Zone processes\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Restoration\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Bulk Density\",\"Carbon Content\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining human health\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Modification\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Porosity \",\"Resistivity \",\"Structure\",\"Temperature\",\"Texture\"]},\"selected\":{\"id\":\"2372\"},\"selection_policy\":{\"id\":\"2373\"}},\"id\":\"2232\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"active_multi\":null,\"active_scroll\":{\"id\":\"2220\"},\"tools\":[{\"id\":\"2219\"},{\"id\":\"2220\"},{\"id\":\"2221\"},{\"id\":\"2222\"},{\"id\":\"2223\"}]},\"id\":\"2224\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"2207\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"2220\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"2209\",\"type\":\"LinearScale\"}],\"root_ids\":[\"2202\"]},\"title\":\"Bokeh Application\",\"version\":\"2.3.3\"}};\n",
" var render_items = [{\"docid\":\"d3070b1d-16f4-48ca-8d4d-3949c26ced91\",\"root_ids\":[\"2202\"],\"roots\":{\"2202\":\"ea2d8aaa-b19e-4086-bce9-62e33e03d162\"}}];\n",
" root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
"\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" embed_document(root);\n",
" } else {\n",
" var attempts = 0;\n",
" var timer = setInterval(function(root) {\n",
" if (root.Bokeh !== undefined) {\n",
" clearInterval(timer);\n",
" embed_document(root);\n",
" } else {\n",
" attempts++;\n",
" if (attempts > 100) {\n",
" clearInterval(timer);\n",
" console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
" }\n",
" }\n",
" }, 10, root)\n",
" }\n",
"})(window);"
],
"application/vnd.bokehjs_exec.v0+json": ""
},
"metadata": {
"application/vnd.bokehjs_exec.v0+json": {
"id": "2202"
}
}
}
],
"source": [
"#Choose a title!\n",
"title = 'soil health and heritage'\n",
"\n",
"#Establish which categories will appear when hovering over each node\n",
"HOVER_TOOLTIPS = [(\"concept\", \"@index\")]\n",
"\n",
"#Create a plot — set dimensions, toolbar, and title\n",
"plot = figure(tooltips = HOVER_TOOLTIPS,\n",
" tools=\"pan,wheel_zoom,save,reset\", active_scroll='wheel_zoom',\n",
" x_range=Range1d(-10.1, 10.1), y_range=Range1d(-10.1, 10.1), title=title)\n",
"\n",
"#Create a network graph object with spring layout\n",
"# https://networkx.github.io/documentation/networkx-1.9/reference/generated/networkx.drawing.layout.spring_layout.html\n",
"network_graph = from_networkx(G, networkx.spring_layout, scale=10, center=(0, 0))\n",
"\n",
"#Set node size and color\n",
"network_graph.node_renderer.glyph = Circle(size=15, fill_color='skyblue')\n",
"\n",
"#Set edge opacity and width\n",
"network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.5, line_width=1)\n",
"\n",
"#Add network graph to the plot\n",
"plot.renderers.append(network_graph)\n",
"\n",
"show(plot)\n",
"#save(plot, filename=f\"{title}.html\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "64JXZTsSUsRJ"
},
"source": [
"## Network with Nodes Sized and Colored By Attribute (Degree)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3k8Qtor6UsRJ"
},
"source": [
"The code below shows how to size and color nodes by degree."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "v5O0cNM_UsRJ"
},
"source": [
"**Include Bokeh color palettes**"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"id": "_fgUKathUsRK"
},
"outputs": [],
"source": [
"from bokeh.io import output_notebook, show, save\n",
"from bokeh.models import Range1d, Circle, ColumnDataSource, MultiLine\n",
"from bokeh.plotting import figure\n",
"from bokeh.plotting import from_networkx\n",
"from bokeh.palettes import Blues8, Reds8, Purples8, Oranges8, Viridis8, Spectral8\n",
"from bokeh.transform import linear_cmap"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "W9Uj-HvkUsRK"
},
"source": [
"**Calculate degree for each node and add as node attribute**"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {
"id": "o4976-8EUsRK"
},
"outputs": [],
"source": [
"degrees = dict(networkx.degree(G))\n",
"networkx.set_node_attributes(G, name='degree', values=degrees)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "-g5OX8EOUsRK"
},
"source": [
"**Slightly adjust degree so that the nodes with very small degrees are still visible**"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {
"id": "UrOcXx5QUsRK"
},
"outputs": [],
"source": [
"number_to_adjust_by = 5\n",
"adjusted_node_size = dict([(node, degree+number_to_adjust_by) for node, degree in networkx.degree(G)])\n",
"networkx.set_node_attributes(G, name='adjusted_node_size', values=adjusted_node_size)"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 0
},
"id": "dXuqs-EtUsRL",
"outputId": "3bfd708d-a843-4990-bb11-76cb0e81a0ff"
},
"outputs": [
{
"output_type": "display_data",
"data": {
"application/javascript": [
"\n",
"(function(root) {\n",
" function now() {\n",
" return new Date();\n",
" }\n",
"\n",
" var force = true;\n",
"\n",
" if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
" root._bokeh_onload_callbacks = [];\n",
" root._bokeh_is_loading = undefined;\n",
" }\n",
"\n",
" var JS_MIME_TYPE = 'application/javascript';\n",
" var HTML_MIME_TYPE = 'text/html';\n",
" var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
" var CLASS_NAME = 'output_bokeh rendered_html';\n",
"\n",
" /**\n",
" * Render data to the DOM node\n",
" */\n",
" function render(props, node) {\n",
" var script = document.createElement(\"script\");\n",
" node.appendChild(script);\n",
" }\n",
"\n",
" /**\n",
" * Handle when an output is cleared or removed\n",
" */\n",
" function handleClearOutput(event, handle) {\n",
" var cell = handle.cell;\n",
"\n",
" var id = cell.output_area._bokeh_element_id;\n",
" var server_id = cell.output_area._bokeh_server_id;\n",
" // Clean up Bokeh references\n",
" if (id != null && id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
"\n",
" if (server_id !== undefined) {\n",
" // Clean up Bokeh references\n",
" var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
" cell.notebook.kernel.execute(cmd, {\n",
" iopub: {\n",
" output: function(msg) {\n",
" var id = msg.content.text.trim();\n",
" if (id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
" }\n",
" }\n",
" });\n",
" // Destroy server and session\n",
" var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
" cell.notebook.kernel.execute(cmd);\n",
" }\n",
" }\n",
"\n",
" /**\n",
" * Handle when a new output is added\n",
" */\n",
" function handleAddOutput(event, handle) {\n",
" var output_area = handle.output_area;\n",
" var output = handle.output;\n",
"\n",
" // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
" if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n",
" return\n",
" }\n",
"\n",
" var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
"\n",
" if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
" toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
" // store reference to embed id on output_area\n",
" output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
" }\n",
" 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].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
" toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\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",
" function register_renderer(events, OutputArea) {\n",
"\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[toinsert.length - 1]);\n",
" element.append(toinsert);\n",
" return toinsert\n",
" }\n",
"\n",
" /* Handle when an output is cleared or removed */\n",
" events.on('clear_output.CodeCell', handleClearOutput);\n",
" events.on('delete.Cell', handleClearOutput);\n",
"\n",
" /* Handle when a new output is added */\n",
" events.on('output_added.OutputArea', handleAddOutput);\n",
"\n",
" /**\n",
" * Register the mime type and append_mime function with output_area\n",
" */\n",
" OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
" /* Is output safe? */\n",
" safe: true,\n",
" /* Index of renderer in `output_area.display_order` */\n",
" index: 0\n",
" });\n",
" }\n",
"\n",
" // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
" if (root.Jupyter !== undefined) {\n",
" var events = require('base/js/events');\n",
" var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
"\n",
" if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
" register_renderer(events, OutputArea);\n",
" }\n",
" }\n",
"\n",
" \n",
" if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
" root._bokeh_timeout = Date.now() + 5000;\n",
" root._bokeh_failed_load = false;\n",
" }\n",
"\n",
" var NB_LOAD_WARNING = {'data': {'text/html':\n",
" \"<div style='background-color: #fdd'>\\n\"+\n",
" \"<p>\\n\"+\n",
" \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
" \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
" \"</p>\\n\"+\n",
" \"<ul>\\n\"+\n",
" \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
" \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
" \"</ul>\\n\"+\n",
" \"<code>\\n\"+\n",
" \"from bokeh.resources import INLINE\\n\"+\n",
" \"output_notebook(resources=INLINE)\\n\"+\n",
" \"</code>\\n\"+\n",
" \"</div>\"}};\n",
"\n",
" function display_loaded() {\n",
" var el = document.getElementById(null);\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS is loading...\";\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
" }\n",
" } else if (Date.now() < root._bokeh_timeout) {\n",
" setTimeout(display_loaded, 100)\n",
" }\n",
" }\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, callback) {\n",
" if (css_urls == null) css_urls = [];\n",
" if (js_urls == null) js_urls = [];\n",
"\n",
" root._bokeh_onload_callbacks.push(callback);\n",
" if (root._bokeh_is_loading > 0) {\n",
" console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
" return null;\n",
" }\n",
" if (js_urls == null || js_urls.length === 0) {\n",
" run_callbacks();\n",
" return null;\n",
" }\n",
" console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
" root._bokeh_is_loading = css_urls.length + js_urls.length;\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",
"\n",
" function on_error(url) {\n",
" console.error(\"failed to load \" + url);\n",
" }\n",
"\n",
" for (let i = 0; i < css_urls.length; i++) {\n",
" const url = css_urls[i];\n",
" const element = document.createElement(\"link\");\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\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",
" }\n",
"\n",
" const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\": \"dM3QQsP+wXdHg42wTqW85BjZQdLNNIXqlPw/BgKoExPmTG7ZLML4EGqLMfqHT6ON\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\": \"8x57I4YuIfu8XyZfFo0XVr2WAT8EK4rh/uDe3wF7YuW2FNUSNEpJbsPaB1nJ2fz2\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\": \"3QTqdz9LyAm2i0sG5XTePsHec3UHWwVsrOL68SYRoAXsafvfAyqtQ+h440+qIBhS\"};\n",
"\n",
" for (let i = 0; i < js_urls.length; i++) {\n",
" const url = js_urls[i];\n",
" const element = document.createElement('script');\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\n",
" element.async = false;\n",
" element.src = url;\n",
" if (url in hashes) {\n",
" element.crossOrigin = \"anonymous\";\n",
" element.integrity = \"sha384-\" + hashes[url];\n",
" }\n",
" console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
" document.head.appendChild(element);\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",
" \n",
" var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\"];\n",
" var css_urls = [];\n",
" \n",
"\n",
" var inline_js = [\n",
" function(Bokeh) {\n",
" Bokeh.set_log_level(\"info\");\n",
" },\n",
" function(Bokeh) {\n",
" \n",
" \n",
" }\n",
" ];\n",
"\n",
" function run_inline_js() {\n",
" \n",
" if (root.Bokeh !== undefined || force === true) {\n",
" \n",
" for (var i = 0; i < inline_js.length; i++) {\n",
" inline_js[i].call(root, root.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",
" } else if (force !== true) {\n",
" var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n",
" cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
" }\n",
"\n",
" }\n",
"\n",
" if (root._bokeh_is_loading === 0) {\n",
" console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
" run_inline_js();\n",
" } else {\n",
" load_libs(css_urls, js_urls, function() {\n",
" console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
" run_inline_js();\n",
" });\n",
" }\n",
"}(window));"
],
"application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n \n\n \n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n var NB_LOAD_WARNING = {'data': {'text/html':\n \"<div style='background-color: #fdd'>\\n\"+\n \"<p>\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"</p>\\n\"+\n \"<ul>\\n\"+\n \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n \"<li>use INLINE resources instead, as so:</li>\\n\"+\n \"</ul>\\n\"+\n \"<code>\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"</code>\\n\"+\n \"</div>\"}};\n\n function display_loaded() {\n var el = document.getElementById(null);\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\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, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\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\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\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 }\n\n const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\": \"dM3QQsP+wXdHg42wTqW85BjZQdLNNIXqlPw/BgKoExPmTG7ZLML4EGqLMfqHT6ON\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\": \"8x57I4YuIfu8XyZfFo0XVr2WAT8EK4rh/uDe3wF7YuW2FNUSNEpJbsPaB1nJ2fz2\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\": \"3QTqdz9LyAm2i0sG5XTePsHec3UHWwVsrOL68SYRoAXsafvfAyqtQ+h440+qIBhS\"};\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n if (url in hashes) {\n element.crossOrigin = \"anonymous\";\n element.integrity = \"sha384-\" + hashes[url];\n }\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\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 \n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\"];\n var css_urls = [];\n \n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {\n \n \n }\n ];\n\n function run_inline_js() {\n \n if (root.Bokeh !== undefined || force === true) {\n \n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.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 } else if (force !== true) {\n var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));"
},
"metadata": {}
},
{
"output_type": "display_data",
"data": {
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
" <div class=\"bk-root\" id=\"4611bcac-41e3-4e25-a1cc-776e7f4076a5\" data-root-id=\"2493\"></div>\n"
]
},
"metadata": {}
},
{
"output_type": "display_data",
"data": {
"application/javascript": [
"(function(root) {\n",
" function embed_document(root) {\n",
" \n",
" var docs_json = {\"60681ef9-a6fb-497e-bafb-7c3ecc442058\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"2502\"}],\"center\":[{\"id\":\"2505\"},{\"id\":\"2509\"}],\"left\":[{\"id\":\"2506\"}],\"renderers\":[{\"id\":\"2521\"}],\"title\":{\"id\":\"2494\"},\"toolbar\":{\"id\":\"2515\"},\"x_range\":{\"id\":\"2491\"},\"x_scale\":{\"id\":\"2498\"},\"y_range\":{\"id\":\"2492\"},\"y_scale\":{\"id\":\"2500\"}},\"id\":\"2493\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"source\":{\"id\":\"2527\"}},\"id\":\"2529\",\"type\":\"CDSView\"},{\"attributes\":{\"formatter\":{\"id\":\"2690\"},\"major_label_policy\":{\"id\":\"2689\"},\"ticker\":{\"id\":\"2507\"}},\"id\":\"2506\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"2693\",\"type\":\"Selection\"},{\"attributes\":{\"active_multi\":null,\"active_scroll\":{\"id\":\"2511\"},\"tools\":[{\"id\":\"2510\"},{\"id\":\"2511\"},{\"id\":\"2512\"},{\"id\":\"2513\"},{\"id\":\"2514\"}]},\"id\":\"2515\",\"type\":\"Toolbar\"},{\"attributes\":{\"axis\":{\"id\":\"2506\"},\"dimension\":1,\"ticker\":null},\"id\":\"2509\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"2692\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"2510\",\"type\":\"PanTool\"},{\"attributes\":{},\"id\":\"2694\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"end\":10.1,\"start\":-10.1},\"id\":\"2491\",\"type\":\"Range1d\"},{\"attributes\":{},\"id\":\"2690\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"fill_color\":{\"field\":\"adjusted_node_size\",\"transform\":{\"id\":\"2539\"}},\"size\":{\"field\":\"adjusted_node_size\"}},\"id\":\"2540\",\"type\":\"Circle\"},{\"attributes\":{\"end\":10.1,\"start\":-10.1},\"id\":\"2492\",\"type\":\"Range1d\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"concept\",\"@index\"],[\"Degree\",\"@degree\"]]},\"id\":\"2514\",\"type\":\"HoverTool\"},{\"attributes\":{\"source\":{\"id\":\"2523\"}},\"id\":\"2525\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"2511\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"text\":\"soil health and heritage\"},\"id\":\"2494\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"2512\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"2680\",\"type\":\"NodesOnly\"},{\"attributes\":{},\"id\":\"2679\",\"type\":\"NodesOnly\"},{\"attributes\":{},\"id\":\"2687\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"2513\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"2689\",\"type\":\"AllLabels\"},{\"attributes\":{\"data\":{\"adjusted_node_size\":[14,13,15,13,14,11,10,17,17,18,10,19,14,16,8,12,12,11,12,9,20,7,15,19,7,16,7,14,10,14],\"degree\":[9,8,10,8,9,6,5,12,12,13,5,14,9,11,3,7,7,6,7,4,15,2,10,14,2,11,2,9,5,9],\"index\":[\"Acidity (pH)\",\"Capturing Critical Zone processes\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Restoration\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Bulk Density\",\"Carbon Content\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining human health\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Modification\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Porosity \",\"Resistivity \",\"Structure\",\"Temperature\",\"Texture\"]},\"selected\":{\"id\":\"2693\"},\"selection_policy\":{\"id\":\"2694\"}},\"id\":\"2523\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"graph_layout\":{\"Acidity (pH)\":[-4.368502287517612,-1.124303383669833],\"Archiving evidence of past ecosystem processes\":[5.1343114367754055,-3.1329217063008277],\"Archiving evidence of past human activities\":[3.1039963479212127,-3.0868364290605808],\"Bulk Density\":[-3.8018772821280886,6.648211068205472],\"Capturing Critical Zone processes\":[0.46101610196062837,4.936083501676605],\"Carbon Content\":[-0.05151104041368463,-1.1733221621710355],\"Colour\":[-4.533548601751401,-3.5429765830605544],\"Compaction\":[-1.582103970021751,-3.446908542004116],\"Erosion\":[-2.8702024457940185,0.9427636554893153],\"Evidencing ecosystem processes\":[-4.697255512364437,2.5308670783116245],\"Evidencing human-ecosystem interactions\":[0.6665936923997521,-4.220107244191397],\"Forming rural landscapes\":[-2.0339805576948633,-7.0548111083998615],\"Inorganic inclusions\":[3.614616492413713,-7.644801081316594],\"Modification\":[9.91169241036183,1.8753846722127356],\"Moisture\":[1.3949869650403104,-0.11298695921195673],\"Nutrient Content \":[3.3199614621060753,1.282836020698373],\"Organic Matter Content\":[0.05140283015601157,-0.04125409187761986],\"Organisms present\":[-8.800695088357562,8.421103820831492],\"Porosity \":[2.803630407249293,-0.23743969636312845],\"Regulating Climate\":[-5.720929785123481,0.4545526267138521],\"Resistivity \":[10.0,-7.298782540259778],\"Restoration\":[0.27384604577634547,-5.808256254138366],\"Storing Carbon\":[-1.8234718794737077,1.788421081638794],\"Structure\":[-0.11431405528230193,3.719743063779652],\"Supporting a living ecosystem\":[-2.510674650336325,3.374112095751625],\"Sustaining animal health\":[5.474534949724231,2.37463553401264],\"Sustaining human health\":[4.151880837975646,4.404203559205057],\"Sustaining plant health\":[-1.7666500070902853,-0.5698503084111131],\"Temperature\":[-8.097745217151449,2.8804331848143305],\"Texture\":[2.4109924006405823,2.862207127095197]}},\"id\":\"2530\",\"type\":\"StaticLayoutProvider\"},{\"attributes\":{\"data_source\":{\"id\":\"2527\"},\"glyph\":{\"id\":\"2545\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"2529\"}},\"id\":\"2528\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"2498\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"2500\",\"type\":\"LinearScale\"},{\"attributes\":{\"data_source\":{\"id\":\"2523\"},\"glyph\":{\"id\":\"2540\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"2525\"}},\"id\":\"2524\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"line_alpha\":{\"value\":0.5}},\"id\":\"2545\",\"type\":\"MultiLine\"},{\"attributes\":{},\"id\":\"2507\",\"type\":\"BasicTicker\"},{\"attributes\":{\"data\":{\"end\":[\"Capturing Critical Zone processes\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Restoration\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Bulk Density\",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Carbon Content\",\"Colour\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Temperature\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Structure\",\"Temperature\",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Compaction\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining human health\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Resistivity \",\"Texture\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Resistivity \",\"Structure\",\"Texture\",\"Moisture\",\"Organic Matter Content\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Modification\",\"Nutrient Content \"],\"start\":[\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Restoration\",\"Restoration\",\"Restoration\",\"Restoration\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Moisture\",\"Modification\"]},\"selected\":{\"id\":\"2691\"},\"selection_policy\":{\"id\":\"2692\"}},\"id\":\"2527\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"edge_renderer\":{\"id\":\"2528\"},\"inspection_policy\":{\"id\":\"2680\"},\"layout_provider\":{\"id\":\"2530\"},\"node_renderer\":{\"id\":\"2524\"},\"selection_policy\":{\"id\":\"2679\"}},\"id\":\"2521\",\"type\":\"GraphRenderer\"},{\"attributes\":{},\"id\":\"2686\",\"type\":\"AllLabels\"},{\"attributes\":{\"formatter\":{\"id\":\"2687\"},\"major_label_policy\":{\"id\":\"2686\"},\"ticker\":{\"id\":\"2503\"}},\"id\":\"2502\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"2691\",\"type\":\"Selection\"},{\"attributes\":{\"high\":20,\"low\":7,\"palette\":[\"#084594\",\"#2171b5\",\"#4292c6\",\"#6baed6\",\"#9ecae1\",\"#c6dbef\",\"#deebf7\",\"#f7fbff\"]},\"id\":\"2539\",\"type\":\"LinearColorMapper\"},{\"attributes\":{\"axis\":{\"id\":\"2502\"},\"ticker\":null},\"id\":\"2505\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"2503\",\"type\":\"BasicTicker\"}],\"root_ids\":[\"2493\"]},\"title\":\"Bokeh Application\",\"version\":\"2.3.3\"}};\n",
" var render_items = [{\"docid\":\"60681ef9-a6fb-497e-bafb-7c3ecc442058\",\"root_ids\":[\"2493\"],\"roots\":{\"2493\":\"4611bcac-41e3-4e25-a1cc-776e7f4076a5\"}}];\n",
" root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
"\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" embed_document(root);\n",
" } else {\n",
" var attempts = 0;\n",
" var timer = setInterval(function(root) {\n",
" if (root.Bokeh !== undefined) {\n",
" clearInterval(timer);\n",
" embed_document(root);\n",
" } else {\n",
" attempts++;\n",
" if (attempts > 100) {\n",
" clearInterval(timer);\n",
" console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
" }\n",
" }\n",
" }, 10, root)\n",
" }\n",
"})(window);"
],
"application/vnd.bokehjs_exec.v0+json": ""
},
"metadata": {
"application/vnd.bokehjs_exec.v0+json": {
"id": "2493"
}
}
}
],
"source": [
"#Choose attributes from G network to size and color by — setting manual size (e.g. 10) or color (e.g. 'skyblue') also allowed\n",
"size_by_this_attribute = 'adjusted_node_size'\n",
"color_by_this_attribute = 'adjusted_node_size'\n",
"\n",
"#Pick a color palette — Blues8, Reds8, Purples8, Oranges8, Viridis8\n",
"color_palette = Blues8\n",
"\n",
"#Choose a title!\n",
"title = 'soil health and heritage'\n",
"\n",
"#Establish which categories will appear when hovering over each node\n",
"HOVER_TOOLTIPS = [\n",
" (\"concept\", \"@index\"),\n",
" (\"Degree\", \"@degree\")\n",
"]\n",
"\n",
"#Create a plot — set dimensions, toolbar, and title\n",
"plot = figure(tooltips = HOVER_TOOLTIPS,\n",
" tools=\"pan,wheel_zoom,save,reset\", active_scroll='wheel_zoom',\n",
" x_range=Range1d(-10.1, 10.1), y_range=Range1d(-10.1, 10.1), title=title)\n",
"\n",
"#Create a network graph object\n",
"# https://networkx.github.io/documentation/networkx-1.9/reference/generated/networkx.drawing.layout.spring_layout.html\\\n",
"network_graph = from_networkx(G, networkx.spring_layout, scale=10, center=(0, 0))\n",
"\n",
"#Set node sizes and colors according to node degree (color as spectrum of color palette)\n",
"minimum_value_color = min(network_graph.node_renderer.data_source.data[color_by_this_attribute])\n",
"maximum_value_color = max(network_graph.node_renderer.data_source.data[color_by_this_attribute])\n",
"network_graph.node_renderer.glyph = Circle(size=size_by_this_attribute, fill_color=linear_cmap(color_by_this_attribute, color_palette, minimum_value_color, maximum_value_color))\n",
"\n",
"#Set edge opacity and width\n",
"network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.5, line_width=1)\n",
"\n",
"plot.renderers.append(network_graph)\n",
"\n",
"show(plot)\n",
"#save(plot, filename=f\"{title}.html\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "YxRyQkfjUsRL"
},
"source": [
"## Network with Nodes Colored By Attribute (Community)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "zbXq15uGUsRL"
},
"source": [
"The code below shows how to size and color nodes by modularity class."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ndVsTZRZUsRL"
},
"source": [
"**Include community module**"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {
"id": "bZAte44cUsRL"
},
"outputs": [],
"source": [
"from bokeh.io import output_notebook, show, save\n",
"from bokeh.models import Range1d, Circle, ColumnDataSource, MultiLine\n",
"from bokeh.plotting import figure\n",
"from bokeh.plotting import from_networkx\n",
"from bokeh.palettes import Blues8, Reds8, Purples8, Oranges8, Viridis8, Spectral8\n",
"from bokeh.transform import linear_cmap\n",
"from networkx.algorithms import community"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "X7syVy5tUsRM"
},
"source": [
"**Calculate degree for each node and add as node attribute**"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {
"tags": [
"hide-input"
],
"id": "-7Rj8AD6UsRM"
},
"outputs": [],
"source": [
"degrees = dict(networkx.degree(G))\n",
"networkx.set_node_attributes(G, name='degree', values=degrees)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "wCwSvucrUsRM"
},
"source": [
"**Slightly adjust degree so that the nodes with very small degrees are still visible**"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {
"tags": [
"hide-input"
],
"id": "RKoq91HZUsRM"
},
"outputs": [],
"source": [
"number_to_adjust_by = 5\n",
"adjusted_node_size = dict([(node, degree+number_to_adjust_by) for node, degree in networkx.degree(G)])\n",
"networkx.set_node_attributes(G, name='adjusted_node_size', values=adjusted_node_size)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "VelrtOu8UsRM"
},
"source": [
"**Calculate communities**"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {
"id": "0vTFl0EgUsRM"
},
"outputs": [],
"source": [
"communities = community.greedy_modularity_communities(G)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "we9_7ts5UsRM"
},
"source": [
"**Add modularity class and color as attributes to network graph**"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {
"id": "7I47Zxj1UsRN"
},
"outputs": [],
"source": [
"# Create empty dictionaries\n",
"modularity_class = {}\n",
"modularity_color = {}\n",
"#Loop through each community in the network\n",
"for community_number, community in enumerate(communities):\n",
" #For each member of the community, add their community number and a distinct color\n",
" for name in community: \n",
" modularity_class[name] = community_number\n",
" modularity_color[name] = Spectral8[community_number]"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {
"id": "C-oqphphUsRN"
},
"outputs": [],
"source": [
"# Add modularity class and color as attributes from the network above\n",
"networkx.set_node_attributes(G, modularity_class, 'modularity_class')\n",
"networkx.set_node_attributes(G, modularity_color, 'modularity_color')"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 0
},
"id": "AXKfHsB5UsRN",
"outputId": "f5f249ae-0974-4e7a-869f-722dcb996fb3"
},
"outputs": [
{
"output_type": "display_data",
"data": {
"application/javascript": [
"\n",
"(function(root) {\n",
" function now() {\n",
" return new Date();\n",
" }\n",
"\n",
" var force = true;\n",
"\n",
" if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
" root._bokeh_onload_callbacks = [];\n",
" root._bokeh_is_loading = undefined;\n",
" }\n",
"\n",
" var JS_MIME_TYPE = 'application/javascript';\n",
" var HTML_MIME_TYPE = 'text/html';\n",
" var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
" var CLASS_NAME = 'output_bokeh rendered_html';\n",
"\n",
" /**\n",
" * Render data to the DOM node\n",
" */\n",
" function render(props, node) {\n",
" var script = document.createElement(\"script\");\n",
" node.appendChild(script);\n",
" }\n",
"\n",
" /**\n",
" * Handle when an output is cleared or removed\n",
" */\n",
" function handleClearOutput(event, handle) {\n",
" var cell = handle.cell;\n",
"\n",
" var id = cell.output_area._bokeh_element_id;\n",
" var server_id = cell.output_area._bokeh_server_id;\n",
" // Clean up Bokeh references\n",
" if (id != null && id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
"\n",
" if (server_id !== undefined) {\n",
" // Clean up Bokeh references\n",
" var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
" cell.notebook.kernel.execute(cmd, {\n",
" iopub: {\n",
" output: function(msg) {\n",
" var id = msg.content.text.trim();\n",
" if (id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
" }\n",
" }\n",
" });\n",
" // Destroy server and session\n",
" var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
" cell.notebook.kernel.execute(cmd);\n",
" }\n",
" }\n",
"\n",
" /**\n",
" * Handle when a new output is added\n",
" */\n",
" function handleAddOutput(event, handle) {\n",
" var output_area = handle.output_area;\n",
" var output = handle.output;\n",
"\n",
" // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
" if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n",
" return\n",
" }\n",
"\n",
" var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
"\n",
" if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
" toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
" // store reference to embed id on output_area\n",
" output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
" }\n",
" 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].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
" toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\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",
" function register_renderer(events, OutputArea) {\n",
"\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[toinsert.length - 1]);\n",
" element.append(toinsert);\n",
" return toinsert\n",
" }\n",
"\n",
" /* Handle when an output is cleared or removed */\n",
" events.on('clear_output.CodeCell', handleClearOutput);\n",
" events.on('delete.Cell', handleClearOutput);\n",
"\n",
" /* Handle when a new output is added */\n",
" events.on('output_added.OutputArea', handleAddOutput);\n",
"\n",
" /**\n",
" * Register the mime type and append_mime function with output_area\n",
" */\n",
" OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
" /* Is output safe? */\n",
" safe: true,\n",
" /* Index of renderer in `output_area.display_order` */\n",
" index: 0\n",
" });\n",
" }\n",
"\n",
" // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
" if (root.Jupyter !== undefined) {\n",
" var events = require('base/js/events');\n",
" var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
"\n",
" if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
" register_renderer(events, OutputArea);\n",
" }\n",
" }\n",
"\n",
" \n",
" if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
" root._bokeh_timeout = Date.now() + 5000;\n",
" root._bokeh_failed_load = false;\n",
" }\n",
"\n",
" var NB_LOAD_WARNING = {'data': {'text/html':\n",
" \"<div style='background-color: #fdd'>\\n\"+\n",
" \"<p>\\n\"+\n",
" \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
" \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
" \"</p>\\n\"+\n",
" \"<ul>\\n\"+\n",
" \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
" \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
" \"</ul>\\n\"+\n",
" \"<code>\\n\"+\n",
" \"from bokeh.resources import INLINE\\n\"+\n",
" \"output_notebook(resources=INLINE)\\n\"+\n",
" \"</code>\\n\"+\n",
" \"</div>\"}};\n",
"\n",
" function display_loaded() {\n",
" var el = document.getElementById(null);\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS is loading...\";\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
" }\n",
" } else if (Date.now() < root._bokeh_timeout) {\n",
" setTimeout(display_loaded, 100)\n",
" }\n",
" }\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, callback) {\n",
" if (css_urls == null) css_urls = [];\n",
" if (js_urls == null) js_urls = [];\n",
"\n",
" root._bokeh_onload_callbacks.push(callback);\n",
" if (root._bokeh_is_loading > 0) {\n",
" console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
" return null;\n",
" }\n",
" if (js_urls == null || js_urls.length === 0) {\n",
" run_callbacks();\n",
" return null;\n",
" }\n",
" console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
" root._bokeh_is_loading = css_urls.length + js_urls.length;\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",
"\n",
" function on_error(url) {\n",
" console.error(\"failed to load \" + url);\n",
" }\n",
"\n",
" for (let i = 0; i < css_urls.length; i++) {\n",
" const url = css_urls[i];\n",
" const element = document.createElement(\"link\");\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\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",
" }\n",
"\n",
" const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\": \"dM3QQsP+wXdHg42wTqW85BjZQdLNNIXqlPw/BgKoExPmTG7ZLML4EGqLMfqHT6ON\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\": \"8x57I4YuIfu8XyZfFo0XVr2WAT8EK4rh/uDe3wF7YuW2FNUSNEpJbsPaB1nJ2fz2\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\": \"3QTqdz9LyAm2i0sG5XTePsHec3UHWwVsrOL68SYRoAXsafvfAyqtQ+h440+qIBhS\"};\n",
"\n",
" for (let i = 0; i < js_urls.length; i++) {\n",
" const url = js_urls[i];\n",
" const element = document.createElement('script');\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\n",
" element.async = false;\n",
" element.src = url;\n",
" if (url in hashes) {\n",
" element.crossOrigin = \"anonymous\";\n",
" element.integrity = \"sha384-\" + hashes[url];\n",
" }\n",
" console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
" document.head.appendChild(element);\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",
" \n",
" var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\"];\n",
" var css_urls = [];\n",
" \n",
"\n",
" var inline_js = [\n",
" function(Bokeh) {\n",
" Bokeh.set_log_level(\"info\");\n",
" },\n",
" function(Bokeh) {\n",
" \n",
" \n",
" }\n",
" ];\n",
"\n",
" function run_inline_js() {\n",
" \n",
" if (root.Bokeh !== undefined || force === true) {\n",
" \n",
" for (var i = 0; i < inline_js.length; i++) {\n",
" inline_js[i].call(root, root.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",
" } else if (force !== true) {\n",
" var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n",
" cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
" }\n",
"\n",
" }\n",
"\n",
" if (root._bokeh_is_loading === 0) {\n",
" console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
" run_inline_js();\n",
" } else {\n",
" load_libs(css_urls, js_urls, function() {\n",
" console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
" run_inline_js();\n",
" });\n",
" }\n",
"}(window));"
],
"application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n \n\n \n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n var NB_LOAD_WARNING = {'data': {'text/html':\n \"<div style='background-color: #fdd'>\\n\"+\n \"<p>\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"</p>\\n\"+\n \"<ul>\\n\"+\n \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n \"<li>use INLINE resources instead, as so:</li>\\n\"+\n \"</ul>\\n\"+\n \"<code>\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"</code>\\n\"+\n \"</div>\"}};\n\n function display_loaded() {\n var el = document.getElementById(null);\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\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, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\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\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\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 }\n\n const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\": \"dM3QQsP+wXdHg42wTqW85BjZQdLNNIXqlPw/BgKoExPmTG7ZLML4EGqLMfqHT6ON\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\": \"8x57I4YuIfu8XyZfFo0XVr2WAT8EK4rh/uDe3wF7YuW2FNUSNEpJbsPaB1nJ2fz2\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\": \"3QTqdz9LyAm2i0sG5XTePsHec3UHWwVsrOL68SYRoAXsafvfAyqtQ+h440+qIBhS\"};\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n if (url in hashes) {\n element.crossOrigin = \"anonymous\";\n element.integrity = \"sha384-\" + hashes[url];\n }\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\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 \n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\"];\n var css_urls = [];\n \n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {\n \n \n }\n ];\n\n function run_inline_js() {\n \n if (root.Bokeh !== undefined || force === true) {\n \n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.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 } else if (force !== true) {\n var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));"
},
"metadata": {}
},
{
"output_type": "display_data",
"data": {
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
" <div class=\"bk-root\" id=\"0786ca22-f121-4119-a760-092719a88b8d\" data-root-id=\"2814\"></div>\n"
]
},
"metadata": {}
},
{
"output_type": "display_data",
"data": {
"application/javascript": [
"(function(root) {\n",
" function embed_document(root) {\n",
" \n",
" var docs_json = {\"7a6e1d29-cd36-4dfd-90ae-da60c02b860d\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"2823\"}],\"center\":[{\"id\":\"2826\"},{\"id\":\"2830\"}],\"left\":[{\"id\":\"2827\"}],\"renderers\":[{\"id\":\"2844\"}],\"title\":{\"id\":\"2815\"},\"toolbar\":{\"id\":\"2837\"},\"x_range\":{\"id\":\"2812\"},\"x_scale\":{\"id\":\"2819\"},\"y_range\":{\"id\":\"2813\"},\"y_scale\":{\"id\":\"2821\"}},\"id\":\"2814\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"data_source\":{\"id\":\"2850\"},\"glyph\":{\"id\":\"2859\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"2852\"}},\"id\":\"2851\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"3026\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"2819\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"2821\",\"type\":\"LinearScale\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"concept\",\"@index\"],[\"Degree\",\"@degree\"],[\"Modularity Class\",\"@modularity_class\"],[\"Modularity Color\",\"$color[swatch]:modularity_color\"]]},\"id\":\"2836\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"3025\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"data\":{\"end\":[\"Capturing Critical Zone processes\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Restoration\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Bulk Density\",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Carbon Content\",\"Colour\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Temperature\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Structure\",\"Temperature\",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Compaction\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining human health\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Resistivity \",\"Texture\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Resistivity \",\"Structure\",\"Texture\",\"Moisture\",\"Organic Matter Content\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Modification\",\"Nutrient Content \"],\"start\":[\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Restoration\",\"Restoration\",\"Restoration\",\"Restoration\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Moisture\",\"Modification\"]},\"selected\":{\"id\":\"3026\"},\"selection_policy\":{\"id\":\"3027\"}},\"id\":\"2850\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"formatter\":{\"id\":\"3022\"},\"major_label_policy\":{\"id\":\"3021\"},\"ticker\":{\"id\":\"2824\"}},\"id\":\"2823\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"3015\",\"type\":\"NodesOnly\"},{\"attributes\":{},\"id\":\"2833\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"2828\",\"type\":\"BasicTicker\"},{\"attributes\":{\"graph_layout\":{\"Acidity (pH)\":[0.338925864248007,-4.527961444938511],\"Archiving evidence of past ecosystem processes\":[0.11918384441534231,4.809376711709442],\"Archiving evidence of past human activities\":[0.3631853509446426,3.6641080123993257],\"Bulk Density\":[-4.941446336637213,-4.344226562009304],\"Capturing Critical Zone processes\":[-3.7367262325789796,-2.046333374256268],\"Carbon Content\":[0.6139528141813688,-0.06903853371679526],\"Colour\":[2.9930888735086003,-0.9840750254727231],\"Compaction\":[1.8340757944952293,1.625423034393139],\"Erosion\":[-1.5983586835593921,-2.2355297677483303],\"Evidencing ecosystem processes\":[2.684161287455354,-3.1026865048629912],\"Evidencing human-ecosystem interactions\":[3.4699019393970003,0.8264052432031539],\"Forming rural landscapes\":[5.847288282301986,-0.8235186160536546],\"Inorganic inclusions\":[3.8148557965405545,4.601561890700006],\"Modification\":[2.4399945084902326,7.301013746083128],\"Moisture\":[0.523970195370836,0.790472775657755],\"Nutrient Content \":[0.08218810781164455,2.496891851589313],\"Organic Matter Content\":[0.4954727516687244,-0.7647629823138925],\"Organisms present\":[5.407635405468146,-6.9009321765096345],\"Porosity \":[-1.3219898885897918,1.0001588770086705],\"Regulating Climate\":[-1.7956084932259107,-4.284844771759704],\"Resistivity \":[0.1721146670657766,10.0],\"Restoration\":[2.3072117765852314,-4.060363439437248],\"Storing Carbon\":[-2.108381757013055,-1.304698513325117],\"Structure\":[-4.30994395799056,-0.16459726871793007],\"Supporting a living ecosystem\":[-0.219692462079557,-2.654084875613379],\"Sustaining animal health\":[-2.5254685625662088,3.37779493438227],\"Sustaining human health\":[-3.7113292749655398,2.692845802413691],\"Sustaining plant health\":[-1.0110038267976573,-0.6364779490498841],\"Temperature\":[-2.687111417911487,-5.641331140990227],\"Texture\":[-3.5401463660332904,1.3594100672357003]}},\"id\":\"2853\",\"type\":\"StaticLayoutProvider\"},{\"attributes\":{\"source\":{\"id\":\"2850\"}},\"id\":\"2852\",\"type\":\"CDSView\"},{\"attributes\":{\"axis\":{\"id\":\"2827\"},\"dimension\":1,\"ticker\":null},\"id\":\"2830\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"3028\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"3014\",\"type\":\"NodesOnly\"},{\"attributes\":{},\"id\":\"3024\",\"type\":\"AllLabels\"},{\"attributes\":{\"active_multi\":null,\"active_scroll\":{\"id\":\"2832\"},\"tools\":[{\"id\":\"2831\"},{\"id\":\"2832\"},{\"id\":\"2833\"},{\"id\":\"2834\"},{\"id\":\"2835\"},{\"id\":\"2836\"}]},\"id\":\"2837\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"2831\",\"type\":\"PanTool\"},{\"attributes\":{},\"id\":\"3029\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"2834\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"2824\",\"type\":\"BasicTicker\"},{\"attributes\":{\"axis\":{\"id\":\"2823\"},\"ticker\":null},\"id\":\"2826\",\"type\":\"Grid\"},{\"attributes\":{\"callback\":null},\"id\":\"2835\",\"type\":\"TapTool\"},{\"attributes\":{},\"id\":\"3021\",\"type\":\"AllLabels\"},{\"attributes\":{\"fill_color\":{\"field\":\"modularity_color\"},\"size\":{\"field\":\"adjusted_node_size\"}},\"id\":\"2854\",\"type\":\"Circle\"},{\"attributes\":{\"text\":\"soil health and heritage\"},\"id\":\"2815\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"2832\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"3027\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"data\":{\"adjusted_node_size\":[14,13,15,13,14,11,10,17,17,18,10,19,14,16,8,12,12,11,12,9,20,7,15,19,7,16,7,14,10,14],\"degree\":[9,8,10,8,9,6,5,12,12,13,5,14,9,11,3,7,7,6,7,4,15,2,10,14,2,11,2,9,5,9],\"index\":[\"Acidity (pH)\",\"Capturing Critical Zone processes\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Restoration\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Bulk Density\",\"Carbon Content\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining human health\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Modification\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Porosity \",\"Resistivity \",\"Structure\",\"Temperature\",\"Texture\"],\"modularity_class\":[1,2,0,1,0,1,1,2,1,0,2,1,0,0,1,2,2,0,0,0,2,2,2,1,1,0,0,2,1,2],\"modularity_color\":[\"#66c2a5\",\"#abdda4\",\"#3288bd\",\"#66c2a5\",\"#3288bd\",\"#66c2a5\",\"#66c2a5\",\"#abdda4\",\"#66c2a5\",\"#3288bd\",\"#abdda4\",\"#66c2a5\",\"#3288bd\",\"#3288bd\",\"#66c2a5\",\"#abdda4\",\"#abdda4\",\"#3288bd\",\"#3288bd\",\"#3288bd\",\"#abdda4\",\"#abdda4\",\"#abdda4\",\"#66c2a5\",\"#66c2a5\",\"#3288bd\",\"#3288bd\",\"#abdda4\",\"#66c2a5\",\"#abdda4\"]},\"selected\":{\"id\":\"3028\"},\"selection_policy\":{\"id\":\"3029\"}},\"id\":\"2846\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"data_source\":{\"id\":\"2846\"},\"glyph\":{\"id\":\"2854\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"2848\"}},\"id\":\"2847\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"formatter\":{\"id\":\"3025\"},\"major_label_policy\":{\"id\":\"3024\"},\"ticker\":{\"id\":\"2828\"}},\"id\":\"2827\",\"type\":\"LinearAxis\"},{\"attributes\":{\"line_alpha\":{\"value\":0.5}},\"id\":\"2859\",\"type\":\"MultiLine\"},{\"attributes\":{\"source\":{\"id\":\"2846\"}},\"id\":\"2848\",\"type\":\"CDSView\"},{\"attributes\":{\"edge_renderer\":{\"id\":\"2851\"},\"inspection_policy\":{\"id\":\"3015\"},\"layout_provider\":{\"id\":\"2853\"},\"node_renderer\":{\"id\":\"2847\"},\"selection_policy\":{\"id\":\"3014\"}},\"id\":\"2844\",\"type\":\"GraphRenderer\"},{\"attributes\":{\"end\":10.1,\"start\":-10.1},\"id\":\"2813\",\"type\":\"Range1d\"},{\"attributes\":{},\"id\":\"3022\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"end\":10.1,\"start\":-10.1},\"id\":\"2812\",\"type\":\"Range1d\"}],\"root_ids\":[\"2814\"]},\"title\":\"Bokeh Application\",\"version\":\"2.3.3\"}};\n",
" var render_items = [{\"docid\":\"7a6e1d29-cd36-4dfd-90ae-da60c02b860d\",\"root_ids\":[\"2814\"],\"roots\":{\"2814\":\"0786ca22-f121-4119-a760-092719a88b8d\"}}];\n",
" root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
"\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" embed_document(root);\n",
" } else {\n",
" var attempts = 0;\n",
" var timer = setInterval(function(root) {\n",
" if (root.Bokeh !== undefined) {\n",
" clearInterval(timer);\n",
" embed_document(root);\n",
" } else {\n",
" attempts++;\n",
" if (attempts > 100) {\n",
" clearInterval(timer);\n",
" console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
" }\n",
" }\n",
" }, 10, root)\n",
" }\n",
"})(window);"
],
"application/vnd.bokehjs_exec.v0+json": ""
},
"metadata": {
"application/vnd.bokehjs_exec.v0+json": {
"id": "2814"
}
}
}
],
"source": [
"#Choose attributes from G network to size and color by — setting manual size (e.g. 10) or color (e.g. 'skyblue') also allowed\n",
"size_by_this_attribute = 'adjusted_node_size'\n",
"color_by_this_attribute = 'modularity_color'\n",
"#Pick a color palette — Blues8, Reds8, Purples8, Oranges8, Viridis8\n",
"color_palette = Blues8\n",
"#Choose a title!\n",
"title = 'soil health and heritage'\n",
"\n",
"#Establish which categories will appear when hovering over each node\n",
"HOVER_TOOLTIPS = [\n",
" (\"concept\", \"@index\"),\n",
" (\"Degree\", \"@degree\"),\n",
" (\"Modularity Class\", \"@modularity_class\"),\n",
" (\"Modularity Color\", \"$color[swatch]:modularity_color\"),\n",
"]\n",
"\n",
"#Create a plot — set dimensions, toolbar, and title\n",
"plot = figure(tooltips = HOVER_TOOLTIPS,\n",
" tools=\"pan,wheel_zoom,save,reset, tap\", active_scroll='wheel_zoom',\n",
" x_range=Range1d(-10.1, 10.1), y_range=Range1d(-10.1, 10.1), title=title)\n",
"\n",
"#Create a network graph object\n",
"# https://networkx.github.io/documentation/networkx-1.9/reference/generated/networkx.drawing.layout.spring_layout.html\n",
"network_graph = from_networkx(G, networkx.spring_layout, scale=10, center=(0, 0))\n",
"\n",
"#Set node sizes and colors according to node degree (color as category from attribute)\n",
"network_graph.node_renderer.glyph = Circle(size=size_by_this_attribute, fill_color=color_by_this_attribute)\n",
"\n",
"#Set edge opacity and width\n",
"network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.5, line_width=1)\n",
"\n",
"plot.renderers.append(network_graph)\n",
"\n",
"show(plot)\n",
"#save(plot, filename=f\"{title}.html\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "G6dc5q-TUsRN"
},
"source": [
"## Network with Responsive Highlighting"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "TdSBD16mUsRN"
},
"source": [
"The code below shows how to create responsive highlighting when a user hovers over nodes or edges, which you can read more about in [Bokeh's NetworkX Integration documentation](https://docs.bokeh.org/en/latest/docs/user_guide/graph.html?highlight=networks#interaction-policies). "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "IRH7X7laUsRN"
},
"source": [
"**Include EdgesAndLinkedNodes, NodesAndLinkedEdges**"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {
"id": "CT4FrVM8UsRO"
},
"outputs": [],
"source": [
"from bokeh.io import output_notebook, show, save\n",
"from bokeh.models import Range1d, Circle, ColumnDataSource, MultiLine, EdgesAndLinkedNodes, NodesAndLinkedEdges\n",
"from bokeh.plotting import figure\n",
"from bokeh.plotting import from_networkx\n",
"from bokeh.palettes import Blues8, Reds8, Purples8, Oranges8, Viridis8, Spectral8\n",
"from bokeh.transform import linear_cmap\n",
"from networkx.algorithms import community"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kWPnR6HiUsRO"
},
"source": [
"**Calculate degree for each node and add as node attribute**"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {
"id": "u7y6HgLKUsRO"
},
"outputs": [],
"source": [
"degrees = dict(networkx.degree(G))\n",
"networkx.set_node_attributes(G, name='degree', values=degrees)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZP9cUkukUsRO"
},
"source": [
"**Slightly adjust degree so that the nodes with very small degrees are still visible**"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {
"tags": [
"hide-input"
],
"id": "O_2StX9yUsRO"
},
"outputs": [],
"source": [
"number_to_adjust_by = 5\n",
"adjusted_node_size = dict([(node, degree+number_to_adjust_by) for node, degree in networkx.degree(G)])\n",
"networkx.set_node_attributes(G, name='adjusted_node_size', values=adjusted_node_size)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "aR8n6BlUUsRO"
},
"source": [
"**Calculate communities**"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {
"tags": [
"hide-input"
],
"id": "W4LWGuZqUsRO"
},
"outputs": [],
"source": [
"communities = community.greedy_modularity_communities(G)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "xQoVab7QUsRP"
},
"source": [
"**Add modularity class and color as attributes to network graph**"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {
"tags": [
"hide-input"
],
"id": "g-Fwo2auUsRP"
},
"outputs": [],
"source": [
"# Create empty dictionaries\n",
"modularity_class = {}\n",
"modularity_color = {}\n",
"#Loop through each community in the network\n",
"for community_number, community in enumerate(communities):\n",
" #For each member of the community, add their community number and a distinct color\n",
" for name in community: \n",
" modularity_class[name] = community_number\n",
" modularity_color[name] = Spectral8[community_number]"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {
"tags": [
"hide-input"
],
"id": "peLrmOBPUsRP"
},
"outputs": [],
"source": [
"# Add modularity class and color as attributes from the network above\n",
"networkx.set_node_attributes(G, modularity_class, 'modularity_class')\n",
"networkx.set_node_attributes(G, modularity_color, 'modularity_color')"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 617
},
"id": "SOW2McpqUsRP",
"outputId": "557630c1-2cdf-4eaa-c85d-d72211fd6e79"
},
"outputs": [
{
"output_type": "display_data",
"data": {
"application/javascript": [
"\n",
"(function(root) {\n",
" function now() {\n",
" return new Date();\n",
" }\n",
"\n",
" var force = true;\n",
"\n",
" if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
" root._bokeh_onload_callbacks = [];\n",
" root._bokeh_is_loading = undefined;\n",
" }\n",
"\n",
" var JS_MIME_TYPE = 'application/javascript';\n",
" var HTML_MIME_TYPE = 'text/html';\n",
" var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
" var CLASS_NAME = 'output_bokeh rendered_html';\n",
"\n",
" /**\n",
" * Render data to the DOM node\n",
" */\n",
" function render(props, node) {\n",
" var script = document.createElement(\"script\");\n",
" node.appendChild(script);\n",
" }\n",
"\n",
" /**\n",
" * Handle when an output is cleared or removed\n",
" */\n",
" function handleClearOutput(event, handle) {\n",
" var cell = handle.cell;\n",
"\n",
" var id = cell.output_area._bokeh_element_id;\n",
" var server_id = cell.output_area._bokeh_server_id;\n",
" // Clean up Bokeh references\n",
" if (id != null && id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
"\n",
" if (server_id !== undefined) {\n",
" // Clean up Bokeh references\n",
" var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
" cell.notebook.kernel.execute(cmd, {\n",
" iopub: {\n",
" output: function(msg) {\n",
" var id = msg.content.text.trim();\n",
" if (id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
" }\n",
" }\n",
" });\n",
" // Destroy server and session\n",
" var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
" cell.notebook.kernel.execute(cmd);\n",
" }\n",
" }\n",
"\n",
" /**\n",
" * Handle when a new output is added\n",
" */\n",
" function handleAddOutput(event, handle) {\n",
" var output_area = handle.output_area;\n",
" var output = handle.output;\n",
"\n",
" // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
" if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n",
" return\n",
" }\n",
"\n",
" var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
"\n",
" if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
" toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
" // store reference to embed id on output_area\n",
" output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
" }\n",
" 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].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
" toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\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",
" function register_renderer(events, OutputArea) {\n",
"\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[toinsert.length - 1]);\n",
" element.append(toinsert);\n",
" return toinsert\n",
" }\n",
"\n",
" /* Handle when an output is cleared or removed */\n",
" events.on('clear_output.CodeCell', handleClearOutput);\n",
" events.on('delete.Cell', handleClearOutput);\n",
"\n",
" /* Handle when a new output is added */\n",
" events.on('output_added.OutputArea', handleAddOutput);\n",
"\n",
" /**\n",
" * Register the mime type and append_mime function with output_area\n",
" */\n",
" OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
" /* Is output safe? */\n",
" safe: true,\n",
" /* Index of renderer in `output_area.display_order` */\n",
" index: 0\n",
" });\n",
" }\n",
"\n",
" // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
" if (root.Jupyter !== undefined) {\n",
" var events = require('base/js/events');\n",
" var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
"\n",
" if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
" register_renderer(events, OutputArea);\n",
" }\n",
" }\n",
"\n",
" \n",
" if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
" root._bokeh_timeout = Date.now() + 5000;\n",
" root._bokeh_failed_load = false;\n",
" }\n",
"\n",
" var NB_LOAD_WARNING = {'data': {'text/html':\n",
" \"<div style='background-color: #fdd'>\\n\"+\n",
" \"<p>\\n\"+\n",
" \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
" \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
" \"</p>\\n\"+\n",
" \"<ul>\\n\"+\n",
" \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
" \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
" \"</ul>\\n\"+\n",
" \"<code>\\n\"+\n",
" \"from bokeh.resources import INLINE\\n\"+\n",
" \"output_notebook(resources=INLINE)\\n\"+\n",
" \"</code>\\n\"+\n",
" \"</div>\"}};\n",
"\n",
" function display_loaded() {\n",
" var el = document.getElementById(null);\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS is loading...\";\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
" }\n",
" } else if (Date.now() < root._bokeh_timeout) {\n",
" setTimeout(display_loaded, 100)\n",
" }\n",
" }\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, callback) {\n",
" if (css_urls == null) css_urls = [];\n",
" if (js_urls == null) js_urls = [];\n",
"\n",
" root._bokeh_onload_callbacks.push(callback);\n",
" if (root._bokeh_is_loading > 0) {\n",
" console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
" return null;\n",
" }\n",
" if (js_urls == null || js_urls.length === 0) {\n",
" run_callbacks();\n",
" return null;\n",
" }\n",
" console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
" root._bokeh_is_loading = css_urls.length + js_urls.length;\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",
"\n",
" function on_error(url) {\n",
" console.error(\"failed to load \" + url);\n",
" }\n",
"\n",
" for (let i = 0; i < css_urls.length; i++) {\n",
" const url = css_urls[i];\n",
" const element = document.createElement(\"link\");\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\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",
" }\n",
"\n",
" const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\": \"dM3QQsP+wXdHg42wTqW85BjZQdLNNIXqlPw/BgKoExPmTG7ZLML4EGqLMfqHT6ON\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\": \"8x57I4YuIfu8XyZfFo0XVr2WAT8EK4rh/uDe3wF7YuW2FNUSNEpJbsPaB1nJ2fz2\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\": \"3QTqdz9LyAm2i0sG5XTePsHec3UHWwVsrOL68SYRoAXsafvfAyqtQ+h440+qIBhS\"};\n",
"\n",
" for (let i = 0; i < js_urls.length; i++) {\n",
" const url = js_urls[i];\n",
" const element = document.createElement('script');\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\n",
" element.async = false;\n",
" element.src = url;\n",
" if (url in hashes) {\n",
" element.crossOrigin = \"anonymous\";\n",
" element.integrity = \"sha384-\" + hashes[url];\n",
" }\n",
" console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
" document.head.appendChild(element);\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",
" \n",
" var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\"];\n",
" var css_urls = [];\n",
" \n",
"\n",
" var inline_js = [\n",
" function(Bokeh) {\n",
" Bokeh.set_log_level(\"info\");\n",
" },\n",
" function(Bokeh) {\n",
" \n",
" \n",
" }\n",
" ];\n",
"\n",
" function run_inline_js() {\n",
" \n",
" if (root.Bokeh !== undefined || force === true) {\n",
" \n",
" for (var i = 0; i < inline_js.length; i++) {\n",
" inline_js[i].call(root, root.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",
" } else if (force !== true) {\n",
" var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n",
" cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
" }\n",
"\n",
" }\n",
"\n",
" if (root._bokeh_is_loading === 0) {\n",
" console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
" run_inline_js();\n",
" } else {\n",
" load_libs(css_urls, js_urls, function() {\n",
" console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
" run_inline_js();\n",
" });\n",
" }\n",
"}(window));"
],
"application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n \n\n \n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n var NB_LOAD_WARNING = {'data': {'text/html':\n \"<div style='background-color: #fdd'>\\n\"+\n \"<p>\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"</p>\\n\"+\n \"<ul>\\n\"+\n \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n \"<li>use INLINE resources instead, as so:</li>\\n\"+\n \"</ul>\\n\"+\n \"<code>\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"</code>\\n\"+\n \"</div>\"}};\n\n function display_loaded() {\n var el = document.getElementById(null);\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\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, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\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\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\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 }\n\n const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\": \"dM3QQsP+wXdHg42wTqW85BjZQdLNNIXqlPw/BgKoExPmTG7ZLML4EGqLMfqHT6ON\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\": \"8x57I4YuIfu8XyZfFo0XVr2WAT8EK4rh/uDe3wF7YuW2FNUSNEpJbsPaB1nJ2fz2\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\": \"3QTqdz9LyAm2i0sG5XTePsHec3UHWwVsrOL68SYRoAXsafvfAyqtQ+h440+qIBhS\"};\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n if (url in hashes) {\n element.crossOrigin = \"anonymous\";\n element.integrity = \"sha384-\" + hashes[url];\n }\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\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 \n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\"];\n var css_urls = [];\n \n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {\n \n \n }\n ];\n\n function run_inline_js() {\n \n if (root.Bokeh !== undefined || force === true) {\n \n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.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 } else if (force !== true) {\n var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));"
},
"metadata": {}
},
{
"output_type": "display_data",
"data": {
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
" <div class=\"bk-root\" id=\"649c478d-446e-47e2-bc52-e69fb9f85ef3\" data-root-id=\"3149\"></div>\n"
]
},
"metadata": {}
},
{
"output_type": "display_data",
"data": {
"application/javascript": [
"(function(root) {\n",
" function embed_document(root) {\n",
" \n",
" var docs_json = {\"7c4694c2-cc4a-44b3-b42f-5755e2a9a67a\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"3158\"}],\"center\":[{\"id\":\"3161\"},{\"id\":\"3165\"}],\"left\":[{\"id\":\"3162\"}],\"renderers\":[{\"id\":\"3177\"}],\"title\":{\"id\":\"3150\"},\"toolbar\":{\"id\":\"3171\"},\"x_range\":{\"id\":\"3147\"},\"x_scale\":{\"id\":\"3154\"},\"y_range\":{\"id\":\"3148\"},\"y_scale\":{\"id\":\"3156\"}},\"id\":\"3149\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"axis\":{\"id\":\"3162\"},\"dimension\":1,\"ticker\":null},\"id\":\"3165\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"3168\",\"type\":\"SaveTool\"},{\"attributes\":{\"fill_color\":{\"value\":\"white\"},\"line_width\":{\"value\":2},\"size\":{\"field\":\"adjusted_node_size\"}},\"id\":\"3192\",\"type\":\"Circle\"},{\"attributes\":{\"end\":10.1,\"start\":-10.1},\"id\":\"3148\",\"type\":\"Range1d\"},{\"attributes\":{\"end\":10.1,\"start\":-10.1},\"id\":\"3147\",\"type\":\"Range1d\"},{\"attributes\":{\"axis\":{\"id\":\"3158\"},\"ticker\":null},\"id\":\"3161\",\"type\":\"Grid\"},{\"attributes\":{\"data_source\":{\"id\":\"3183\"},\"glyph\":{\"id\":\"3202\"},\"hover_glyph\":{\"id\":\"3212\"},\"muted_glyph\":null,\"selection_glyph\":{\"id\":\"3207\"},\"view\":{\"id\":\"3185\"}},\"id\":\"3184\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"3400\",\"type\":\"AllLabels\"},{\"attributes\":{\"graph_layout\":{\"Acidity (pH)\":[-0.9288067370967372,-3.753744844409451],\"Archiving evidence of past ecosystem processes\":[2.355025155545907,4.427610333744575],\"Archiving evidence of past human activities\":[0.6639642462146761,3.372919732357205],\"Bulk Density\":[4.522927446360576,-3.967857775273672],\"Capturing Critical Zone processes\":[4.089721664736747,-5.741451650087346],\"Carbon Content\":[1.3962299184883091,-1.8869975294876948],\"Colour\":[-6.799821610416238,1.2892769144096645],\"Compaction\":[-4.390502421145668,3.32249615095953],\"Erosion\":[-2.507001747035856,-2.972606311502369],\"Evidencing ecosystem processes\":[-2.7471138377347084,2.840566488359548],\"Evidencing human-ecosystem interactions\":[-3.784688037467002,0.7938930713688003],\"Forming rural landscapes\":[3.0304764170668737,-8.681909353086132],\"Inorganic inclusions\":[-4.03085189368997,6.609432402168976],\"Modification\":[-1.9636600152010972,8.679560755588055],\"Moisture\":[0.634522983411775,-0.6349238660817218],\"Nutrient Content \":[-0.5178865809462553,2.7760966788960713],\"Organic Matter Content\":[0.7079005386200128,-2.7342628086582175],\"Organisms present\":[0.1437700532754986,10.0],\"Porosity \":[2.5519052707416083,0.07317482408491666],\"Regulating Climate\":[-3.848987923873605,-6.328175058104944],\"Resistivity \":[5.898021750756595,9.953044448229868],\"Restoration\":[6.600744202335157,-1.491385692963555],\"Storing Carbon\":[-1.9713559709715591,-1.6074518430081024],\"Structure\":[-0.4867755911711771,-5.315920066690588],\"Supporting a living ecosystem\":[0.2641576970644,1.1681811576472276],\"Sustaining animal health\":[2.286577202895324,-4.863377953103377],\"Sustaining human health\":[4.086464789309554,-2.7516129220873142],\"Sustaining plant health\":[-2.2187565717131656,-0.2477664863980291],\"Temperature\":[-6.924135564164507,-2.074708245499223],\"Texture\":[3.887935165804564,-0.2521005513727368]}},\"id\":\"3186\",\"type\":\"StaticLayoutProvider\"},{\"attributes\":{},\"id\":\"3398\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"line_width\":{\"value\":2}},\"id\":\"3207\",\"type\":\"MultiLine\"},{\"attributes\":{},\"id\":\"3404\",\"type\":\"Selection\"},{\"attributes\":{\"source\":{\"id\":\"3179\"}},\"id\":\"3181\",\"type\":\"CDSView\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"concept\",\"@index\"],[\"Degree\",\"@degree\"],[\"Modularity Class\",\"@modularity_class\"],[\"Modularity Color\",\"$color[swatch]:modularity_color\"]]},\"id\":\"3170\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"3405\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"active_multi\":null,\"active_scroll\":{\"id\":\"3167\"},\"tools\":[{\"id\":\"3166\"},{\"id\":\"3167\"},{\"id\":\"3168\"},{\"id\":\"3169\"},{\"id\":\"3170\"}]},\"id\":\"3171\",\"type\":\"Toolbar\"},{\"attributes\":{\"formatter\":{\"id\":\"3398\"},\"major_label_policy\":{\"id\":\"3397\"},\"ticker\":{\"id\":\"3159\"}},\"id\":\"3158\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"3154\",\"type\":\"LinearScale\"},{\"attributes\":{\"text\":\"soil health and heritage\"},\"id\":\"3150\",\"type\":\"Title\"},{\"attributes\":{\"line_width\":{\"value\":2}},\"id\":\"3212\",\"type\":\"MultiLine\"},{\"attributes\":{\"data_source\":{\"id\":\"3179\"},\"glyph\":{\"id\":\"3187\"},\"hover_glyph\":{\"id\":\"3192\"},\"muted_glyph\":null,\"selection_glyph\":{\"id\":\"3197\"},\"view\":{\"id\":\"3181\"}},\"id\":\"3180\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"3166\",\"type\":\"PanTool\"},{\"attributes\":{},\"id\":\"3167\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"3219\",\"type\":\"NodesAndLinkedEdges\"},{\"attributes\":{\"fill_color\":{\"value\":\"white\"},\"line_width\":{\"value\":2},\"size\":{\"field\":\"adjusted_node_size\"}},\"id\":\"3197\",\"type\":\"Circle\"},{\"attributes\":{\"source\":{\"id\":\"3183\"}},\"id\":\"3185\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"3159\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"3401\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"3169\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"3163\",\"type\":\"BasicTicker\"},{\"attributes\":{\"formatter\":{\"id\":\"3401\"},\"major_label_policy\":{\"id\":\"3400\"},\"ticker\":{\"id\":\"3163\"}},\"id\":\"3162\",\"type\":\"LinearAxis\"},{\"attributes\":{\"data\":{\"adjusted_node_size\":[14,13,15,13,14,11,10,17,17,18,10,19,14,16,8,12,12,11,12,9,20,7,15,19,7,16,7,14,10,14],\"degree\":[9,8,10,8,9,6,5,12,12,13,5,14,9,11,3,7,7,6,7,4,15,2,10,14,2,11,2,9,5,9],\"index\":[\"Acidity (pH)\",\"Capturing Critical Zone processes\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Restoration\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Bulk Density\",\"Carbon Content\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining human health\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Modification\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Porosity \",\"Resistivity \",\"Structure\",\"Temperature\",\"Texture\"],\"modularity_class\":[1,2,0,1,0,1,1,2,1,0,2,1,0,0,1,2,2,0,0,0,2,2,2,1,1,0,0,2,1,2],\"modularity_color\":[\"#66c2a5\",\"#abdda4\",\"#3288bd\",\"#66c2a5\",\"#3288bd\",\"#66c2a5\",\"#66c2a5\",\"#abdda4\",\"#66c2a5\",\"#3288bd\",\"#abdda4\",\"#66c2a5\",\"#3288bd\",\"#3288bd\",\"#66c2a5\",\"#abdda4\",\"#abdda4\",\"#3288bd\",\"#3288bd\",\"#3288bd\",\"#abdda4\",\"#abdda4\",\"#abdda4\",\"#66c2a5\",\"#66c2a5\",\"#3288bd\",\"#3288bd\",\"#abdda4\",\"#66c2a5\",\"#abdda4\"]},\"selected\":{\"id\":\"3404\"},\"selection_policy\":{\"id\":\"3405\"}},\"id\":\"3179\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"3402\",\"type\":\"Selection\"},{\"attributes\":{\"data\":{\"end\":[\"Capturing Critical Zone processes\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Restoration\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Bulk Density\",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Carbon Content\",\"Colour\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Temperature\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Structure\",\"Temperature\",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Compaction\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining human health\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Resistivity \",\"Texture\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Resistivity \",\"Structure\",\"Texture\",\"Moisture\",\"Organic Matter Content\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Modification\",\"Nutrient Content \"],\"start\":[\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Restoration\",\"Restoration\",\"Restoration\",\"Restoration\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Moisture\",\"Modification\"]},\"selected\":{\"id\":\"3402\"},\"selection_policy\":{\"id\":\"3403\"}},\"id\":\"3183\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"3156\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"3397\",\"type\":\"AllLabels\"},{\"attributes\":{\"line_alpha\":{\"value\":0.5}},\"id\":\"3202\",\"type\":\"MultiLine\"},{\"attributes\":{\"fill_color\":{\"field\":\"modularity_color\"},\"size\":{\"field\":\"adjusted_node_size\"}},\"id\":\"3187\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"3403\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"3217\",\"type\":\"NodesAndLinkedEdges\"},{\"attributes\":{\"edge_renderer\":{\"id\":\"3184\"},\"inspection_policy\":{\"id\":\"3219\"},\"layout_provider\":{\"id\":\"3186\"},\"node_renderer\":{\"id\":\"3180\"},\"selection_policy\":{\"id\":\"3217\"}},\"id\":\"3177\",\"type\":\"GraphRenderer\"}],\"root_ids\":[\"3149\"]},\"title\":\"Bokeh Application\",\"version\":\"2.3.3\"}};\n",
" var render_items = [{\"docid\":\"7c4694c2-cc4a-44b3-b42f-5755e2a9a67a\",\"root_ids\":[\"3149\"],\"roots\":{\"3149\":\"649c478d-446e-47e2-bc52-e69fb9f85ef3\"}}];\n",
" root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
"\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" embed_document(root);\n",
" } else {\n",
" var attempts = 0;\n",
" var timer = setInterval(function(root) {\n",
" if (root.Bokeh !== undefined) {\n",
" clearInterval(timer);\n",
" embed_document(root);\n",
" } else {\n",
" attempts++;\n",
" if (attempts > 100) {\n",
" clearInterval(timer);\n",
" console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
" }\n",
" }\n",
" }, 10, root)\n",
" }\n",
"})(window);"
],
"application/vnd.bokehjs_exec.v0+json": ""
},
"metadata": {
"application/vnd.bokehjs_exec.v0+json": {
"id": "3149"
}
}
}
],
"source": [
"from bokeh.models import EdgesAndLinkedNodes, NodesAndLinkedEdges\n",
"\n",
"#Choose colors for node and edge highlighting\n",
"node_highlight_color = 'white'\n",
"edge_highlight_color = 'black'\n",
"\n",
"#Choose attributes from G network to size and color by — setting manual size (e.g. 10) or color (e.g. 'skyblue') also allowed\n",
"size_by_this_attribute = 'adjusted_node_size'\n",
"color_by_this_attribute = 'modularity_color'\n",
"\n",
"#Pick a color palette — Blues8, Reds8, Purples8, Oranges8, Viridis8\n",
"color_palette = Blues8\n",
"\n",
"#Choose a title!\n",
"title = 'soil health and heritage'\n",
"\n",
"#Establish which categories will appear when hovering over each node\n",
"HOVER_TOOLTIPS = [\n",
" (\"concept\", \"@index\"),\n",
" (\"Degree\", \"@degree\"),\n",
" (\"Modularity Class\", \"@modularity_class\"),\n",
" (\"Modularity Color\", \"$color[swatch]:modularity_color\"),\n",
"]\n",
"\n",
"#Create a plot — set dimensions, toolbar, and title\n",
"plot = figure(tooltips = HOVER_TOOLTIPS,\n",
" tools=\"pan,wheel_zoom,save,reset\", active_scroll='wheel_zoom',\n",
" x_range=Range1d(-10.1, 10.1), y_range=Range1d(-10.1, 10.1), title=title)\n",
"\n",
"#Create a network graph object\n",
"# https://networkx.github.io/documentation/networkx-1.9/reference/generated/networkx.drawing.layout.spring_layout.html\n",
"network_graph = from_networkx(G, networkx.spring_layout, scale=10, center=(0, 0))\n",
"\n",
"#Set node sizes and colors according to node degree (color as category from attribute)\n",
"network_graph.node_renderer.glyph = Circle(size=size_by_this_attribute, fill_color=color_by_this_attribute)\n",
"#Set node highlight colors\n",
"network_graph.node_renderer.hover_glyph = Circle(size=size_by_this_attribute, fill_color=node_highlight_color, line_width=2)\n",
"network_graph.node_renderer.selection_glyph = Circle(size=size_by_this_attribute, fill_color=node_highlight_color, line_width=2)\n",
"\n",
"#Set edge opacity and width\n",
"network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.5, line_width=1)\n",
"#Set edge highlight colors\n",
"network_graph.edge_renderer.selection_glyph = MultiLine(line_color=edge_highlight_color, line_width=2)\n",
"network_graph.edge_renderer.hover_glyph = MultiLine(line_color=edge_highlight_color, line_width=2)\n",
"\n",
" #Highlight nodes and edges\n",
"network_graph.selection_policy = NodesAndLinkedEdges()\n",
"network_graph.inspection_policy = NodesAndLinkedEdges()\n",
"\n",
"plot.renderers.append(network_graph)\n",
"\n",
"show(plot)\n",
"#save(plot, filename=f\"{title}.html\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "HRSQ4qE4UsRP"
},
"source": [
"## Network with Labels"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MGBgK0FYUsRQ"
},
"source": [
"The code below shows how to create node labels, which you can read more about in [Bokeh's label documentation](https://docs.bokeh.org/en/latest/docs/user_guide/annotations.html#labels)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XKqHmr1MUsRQ"
},
"source": [
"**Include LabelSet**"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {
"id": "hWbmU6QrUsRQ"
},
"outputs": [],
"source": [
"from bokeh.io import output_notebook, show, save\n",
"from bokeh.models import Range1d, Circle, ColumnDataSource, MultiLine, EdgesAndLinkedNodes, NodesAndLinkedEdges, LabelSet\n",
"from bokeh.plotting import figure\n",
"from bokeh.plotting import from_networkx\n",
"from bokeh.palettes import Blues8, Reds8, Purples8, Oranges8, Viridis8, Spectral8\n",
"from bokeh.transform import linear_cmap\n",
"from networkx.algorithms import community"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9KUN8cWUUsRQ"
},
"source": [
"**Calculate degree for each node and add as node attribute**"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {
"tags": [
"hide-input"
],
"id": "cYorPtjdUsRQ"
},
"outputs": [],
"source": [
"degrees = dict(networkx.degree(G))\n",
"networkx.set_node_attributes(G, name='degree', values=degrees)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "0L_pyb_0UsRQ"
},
"source": [
"**Slightly adjust degree so that the nodes with very small degrees are still visible**"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {
"tags": [
"hide-input"
],
"id": "SkaHyaNuUsRQ"
},
"outputs": [],
"source": [
"number_to_adjust_by = 5\n",
"adjusted_node_size = dict([(node, degree+number_to_adjust_by) for node, degree in networkx.degree(G)])\n",
"networkx.set_node_attributes(G, name='adjusted_node_size', values=adjusted_node_size)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "zyUDVeimUsRQ"
},
"source": [
"**Calculate communities**"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {
"tags": [
"hide-input"
],
"id": "ePCuWEWAUsRR"
},
"outputs": [],
"source": [
"communities = community.greedy_modularity_communities(G)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_9FvJjCeUsRR"
},
"source": [
"**Add modularity class and color as attributes to network graph**"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {
"tags": [
"hide-input"
],
"id": "86xnfS0gUsRR"
},
"outputs": [],
"source": [
"# Create empty dictionaries\n",
"modularity_class = {}\n",
"modularity_color = {}\n",
"#Loop through each community in the network\n",
"for community_number, community in enumerate(communities):\n",
" #For each member of the community, add their community number and a distinct color\n",
" for name in community: \n",
" modularity_class[name] = community_number\n",
" modularity_color[name] = Spectral8[community_number]"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 617
},
"id": "ypZ_UHm5UsRR",
"outputId": "0d66fe71-545d-4bdb-da2d-1fbe1c19bb86"
},
"outputs": [
{
"output_type": "display_data",
"data": {
"application/javascript": [
"\n",
"(function(root) {\n",
" function now() {\n",
" return new Date();\n",
" }\n",
"\n",
" var force = true;\n",
"\n",
" if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
" root._bokeh_onload_callbacks = [];\n",
" root._bokeh_is_loading = undefined;\n",
" }\n",
"\n",
" var JS_MIME_TYPE = 'application/javascript';\n",
" var HTML_MIME_TYPE = 'text/html';\n",
" var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
" var CLASS_NAME = 'output_bokeh rendered_html';\n",
"\n",
" /**\n",
" * Render data to the DOM node\n",
" */\n",
" function render(props, node) {\n",
" var script = document.createElement(\"script\");\n",
" node.appendChild(script);\n",
" }\n",
"\n",
" /**\n",
" * Handle when an output is cleared or removed\n",
" */\n",
" function handleClearOutput(event, handle) {\n",
" var cell = handle.cell;\n",
"\n",
" var id = cell.output_area._bokeh_element_id;\n",
" var server_id = cell.output_area._bokeh_server_id;\n",
" // Clean up Bokeh references\n",
" if (id != null && id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
"\n",
" if (server_id !== undefined) {\n",
" // Clean up Bokeh references\n",
" var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
" cell.notebook.kernel.execute(cmd, {\n",
" iopub: {\n",
" output: function(msg) {\n",
" var id = msg.content.text.trim();\n",
" if (id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
" }\n",
" }\n",
" });\n",
" // Destroy server and session\n",
" var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
" cell.notebook.kernel.execute(cmd);\n",
" }\n",
" }\n",
"\n",
" /**\n",
" * Handle when a new output is added\n",
" */\n",
" function handleAddOutput(event, handle) {\n",
" var output_area = handle.output_area;\n",
" var output = handle.output;\n",
"\n",
" // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
" if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n",
" return\n",
" }\n",
"\n",
" var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
"\n",
" if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
" toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
" // store reference to embed id on output_area\n",
" output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
" }\n",
" 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].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
" toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\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",
" function register_renderer(events, OutputArea) {\n",
"\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[toinsert.length - 1]);\n",
" element.append(toinsert);\n",
" return toinsert\n",
" }\n",
"\n",
" /* Handle when an output is cleared or removed */\n",
" events.on('clear_output.CodeCell', handleClearOutput);\n",
" events.on('delete.Cell', handleClearOutput);\n",
"\n",
" /* Handle when a new output is added */\n",
" events.on('output_added.OutputArea', handleAddOutput);\n",
"\n",
" /**\n",
" * Register the mime type and append_mime function with output_area\n",
" */\n",
" OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
" /* Is output safe? */\n",
" safe: true,\n",
" /* Index of renderer in `output_area.display_order` */\n",
" index: 0\n",
" });\n",
" }\n",
"\n",
" // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
" if (root.Jupyter !== undefined) {\n",
" var events = require('base/js/events');\n",
" var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
"\n",
" if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
" register_renderer(events, OutputArea);\n",
" }\n",
" }\n",
"\n",
" \n",
" if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
" root._bokeh_timeout = Date.now() + 5000;\n",
" root._bokeh_failed_load = false;\n",
" }\n",
"\n",
" var NB_LOAD_WARNING = {'data': {'text/html':\n",
" \"<div style='background-color: #fdd'>\\n\"+\n",
" \"<p>\\n\"+\n",
" \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
" \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
" \"</p>\\n\"+\n",
" \"<ul>\\n\"+\n",
" \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
" \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
" \"</ul>\\n\"+\n",
" \"<code>\\n\"+\n",
" \"from bokeh.resources import INLINE\\n\"+\n",
" \"output_notebook(resources=INLINE)\\n\"+\n",
" \"</code>\\n\"+\n",
" \"</div>\"}};\n",
"\n",
" function display_loaded() {\n",
" var el = document.getElementById(null);\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS is loading...\";\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
" }\n",
" } else if (Date.now() < root._bokeh_timeout) {\n",
" setTimeout(display_loaded, 100)\n",
" }\n",
" }\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, callback) {\n",
" if (css_urls == null) css_urls = [];\n",
" if (js_urls == null) js_urls = [];\n",
"\n",
" root._bokeh_onload_callbacks.push(callback);\n",
" if (root._bokeh_is_loading > 0) {\n",
" console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
" return null;\n",
" }\n",
" if (js_urls == null || js_urls.length === 0) {\n",
" run_callbacks();\n",
" return null;\n",
" }\n",
" console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
" root._bokeh_is_loading = css_urls.length + js_urls.length;\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",
"\n",
" function on_error(url) {\n",
" console.error(\"failed to load \" + url);\n",
" }\n",
"\n",
" for (let i = 0; i < css_urls.length; i++) {\n",
" const url = css_urls[i];\n",
" const element = document.createElement(\"link\");\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\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",
" }\n",
"\n",
" const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\": \"dM3QQsP+wXdHg42wTqW85BjZQdLNNIXqlPw/BgKoExPmTG7ZLML4EGqLMfqHT6ON\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\": \"8x57I4YuIfu8XyZfFo0XVr2WAT8EK4rh/uDe3wF7YuW2FNUSNEpJbsPaB1nJ2fz2\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\": \"3QTqdz9LyAm2i0sG5XTePsHec3UHWwVsrOL68SYRoAXsafvfAyqtQ+h440+qIBhS\"};\n",
"\n",
" for (let i = 0; i < js_urls.length; i++) {\n",
" const url = js_urls[i];\n",
" const element = document.createElement('script');\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\n",
" element.async = false;\n",
" element.src = url;\n",
" if (url in hashes) {\n",
" element.crossOrigin = \"anonymous\";\n",
" element.integrity = \"sha384-\" + hashes[url];\n",
" }\n",
" console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
" document.head.appendChild(element);\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",
" \n",
" var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\"];\n",
" var css_urls = [];\n",
" \n",
"\n",
" var inline_js = [\n",
" function(Bokeh) {\n",
" Bokeh.set_log_level(\"info\");\n",
" },\n",
" function(Bokeh) {\n",
" \n",
" \n",
" }\n",
" ];\n",
"\n",
" function run_inline_js() {\n",
" \n",
" if (root.Bokeh !== undefined || force === true) {\n",
" \n",
" for (var i = 0; i < inline_js.length; i++) {\n",
" inline_js[i].call(root, root.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",
" } else if (force !== true) {\n",
" var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n",
" cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
" }\n",
"\n",
" }\n",
"\n",
" if (root._bokeh_is_loading === 0) {\n",
" console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
" run_inline_js();\n",
" } else {\n",
" load_libs(css_urls, js_urls, function() {\n",
" console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
" run_inline_js();\n",
" });\n",
" }\n",
"}(window));"
],
"application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n \n\n \n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n var NB_LOAD_WARNING = {'data': {'text/html':\n \"<div style='background-color: #fdd'>\\n\"+\n \"<p>\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"</p>\\n\"+\n \"<ul>\\n\"+\n \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n \"<li>use INLINE resources instead, as so:</li>\\n\"+\n \"</ul>\\n\"+\n \"<code>\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"</code>\\n\"+\n \"</div>\"}};\n\n function display_loaded() {\n var el = document.getElementById(null);\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\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, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\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\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\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 }\n\n const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\": \"dM3QQsP+wXdHg42wTqW85BjZQdLNNIXqlPw/BgKoExPmTG7ZLML4EGqLMfqHT6ON\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\": \"8x57I4YuIfu8XyZfFo0XVr2WAT8EK4rh/uDe3wF7YuW2FNUSNEpJbsPaB1nJ2fz2\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\": \"3QTqdz9LyAm2i0sG5XTePsHec3UHWwVsrOL68SYRoAXsafvfAyqtQ+h440+qIBhS\"};\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n if (url in hashes) {\n element.crossOrigin = \"anonymous\";\n element.integrity = \"sha384-\" + hashes[url];\n }\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\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 \n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.3.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.3.3.min.js\"];\n var css_urls = [];\n \n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {\n \n \n }\n ];\n\n function run_inline_js() {\n \n if (root.Bokeh !== undefined || force === true) {\n \n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.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 } else if (force !== true) {\n var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));"
},
"metadata": {}
},
{
"output_type": "display_data",
"data": {
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
" <div class=\"bk-root\" id=\"88f5e00f-3c2c-4f80-9f1f-925ae4f863f9\" data-root-id=\"3515\"></div>\n"
]
},
"metadata": {}
},
{
"output_type": "display_data",
"data": {
"application/javascript": [
"(function(root) {\n",
" function embed_document(root) {\n",
" \n",
" var docs_json = {\"ffb6bc5f-cf5d-493b-a7c4-822bb103d4bd\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"3524\"}],\"center\":[{\"id\":\"3527\"},{\"id\":\"3531\"}],\"left\":[{\"id\":\"3528\"}],\"renderers\":[{\"id\":\"3543\"},{\"id\":\"3588\"}],\"title\":{\"id\":\"3516\"},\"toolbar\":{\"id\":\"3537\"},\"x_range\":{\"id\":\"3513\"},\"x_scale\":{\"id\":\"3520\"},\"y_range\":{\"id\":\"3514\"},\"y_scale\":{\"id\":\"3522\"}},\"id\":\"3515\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"fill_color\":{\"value\":\"white\"},\"line_width\":{\"value\":2},\"size\":{\"field\":\"adjusted_node_size\"}},\"id\":\"3558\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"3794\",\"type\":\"Selection\"},{\"attributes\":{\"data\":{\"name\":[\"Acidity (pH)\",\"Capturing Critical Zone processes\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Restoration\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Bulk Density\",\"Carbon Content\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining human health\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Modification\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Porosity \",\"Resistivity \",\"Structure\",\"Temperature\",\"Texture\"],\"x\":[4.347342865217959,6.400950343669866,1.8618204002605898,-2.899272822873254,-1.8373701353172642,7.343743884799048,6.00548920332655,0.7335156945392783,-1.1330617116056143,-0.6682628230855774,5.268294218410094,2.0409562082946944,-4.298561125646851,-3.9287865078640696,9.467337025920228,0.7407650940172219,4.746760404692643,-6.071564399733329,-4.754473821892442,-8.313262239358416,2.026361439487673,-2.1323322143111034,-3.0433259774036086,2.550860092232231,-10.0,0.23581463121973026,-9.695809636391175,2.99107184329659,2.204645996551671,-0.18964593045334915],\"y\":[-2.293242605034335,2.2445932830946838,-2.6561180113100655,-3.473273985016058,-2.912702984343478,-1.9402767916115782,5.164627384713775,-2.1725481490165204,-0.9327657548538072,-1.8584603763947156,-5.005965480228244,2.08670922024741,4.2392218585137815,2.8331375610565948,3.249969109043215,6.66597559947256,2.404635322982228,-2.7893517872982203,-3.2818079566328384,0.9156669628887535,-0.1494317037178702,-8.658380101134618,0.24946780468213142,1.0939050448226364,-4.931557493211269,2.6335509811853055,8.881161293379026,3.454534113838058,-7.100620965958784,4.039348605842226]},\"selected\":{\"id\":\"3790\"},\"selection_policy\":{\"id\":\"3791\"}},\"id\":\"3587\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"3790\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"3795\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"3793\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"active_multi\":null,\"active_scroll\":{\"id\":\"3533\"},\"tools\":[{\"id\":\"3532\"},{\"id\":\"3533\"},{\"id\":\"3534\"},{\"id\":\"3535\"},{\"id\":\"3536\"}]},\"id\":\"3537\",\"type\":\"Toolbar\"},{\"attributes\":{\"line_width\":{\"value\":2}},\"id\":\"3573\",\"type\":\"MultiLine\"},{\"attributes\":{\"data_source\":{\"id\":\"3545\"},\"glyph\":{\"id\":\"3553\"},\"hover_glyph\":{\"id\":\"3558\"},\"muted_glyph\":null,\"selection_glyph\":{\"id\":\"3563\"},\"view\":{\"id\":\"3547\"}},\"id\":\"3546\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"line_width\":{\"value\":2}},\"id\":\"3578\",\"type\":\"MultiLine\"},{\"attributes\":{},\"id\":\"3520\",\"type\":\"LinearScale\"},{\"attributes\":{\"data_source\":{\"id\":\"3549\"},\"glyph\":{\"id\":\"3568\"},\"hover_glyph\":{\"id\":\"3578\"},\"muted_glyph\":null,\"selection_glyph\":{\"id\":\"3573\"},\"view\":{\"id\":\"3551\"}},\"id\":\"3550\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"concept\",\"@index\"],[\"Degree\",\"@degree\"],[\"Modularity Class\",\"@modularity_class\"],[\"Modularity Color\",\"$color[swatch]:modularity_color\"]]},\"id\":\"3536\",\"type\":\"HoverTool\"},{\"attributes\":{\"background_fill_alpha\":{\"value\":0.7},\"background_fill_color\":{\"value\":\"white\"},\"source\":{\"id\":\"3587\"},\"text\":{\"field\":\"name\"},\"text_font_size\":{\"value\":\"10px\"},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3588\",\"type\":\"LabelSet\"},{\"attributes\":{\"graph_layout\":{\"Acidity (pH)\":[4.347342865217959,-2.293242605034335],\"Archiving evidence of past ecosystem processes\":[-4.298561125646851,4.2392218585137815],\"Archiving evidence of past human activities\":[-3.9287865078640696,2.8331375610565948],\"Bulk Density\":[5.268294218410094,-5.005965480228244],\"Capturing Critical Zone processes\":[6.400950343669866,2.2445932830946838],\"Carbon Content\":[2.0409562082946944,2.08670922024741],\"Colour\":[-6.071564399733329,-2.7893517872982203],\"Compaction\":[-4.754473821892442,-3.2818079566328384],\"Erosion\":[1.8618204002605898,-2.6561180113100655],\"Evidencing ecosystem processes\":[-2.899272822873254,-3.473273985016058],\"Evidencing human-ecosystem interactions\":[-1.8373701353172642,-2.912702984343478],\"Forming rural landscapes\":[9.467337025920228,3.249969109043215],\"Inorganic inclusions\":[-8.313262239358416,0.9156669628887535],\"Modification\":[-2.1323322143111034,-8.658380101134618],\"Moisture\":[2.026361439487673,-0.1494317037178702],\"Nutrient Content \":[-3.0433259774036086,0.24946780468213142],\"Organic Matter Content\":[2.550860092232231,1.0939050448226364],\"Organisms present\":[-10.0,-4.931557493211269],\"Porosity \":[0.23581463121973026,2.6335509811853055],\"Regulating Climate\":[7.343743884799048,-1.9402767916115782],\"Resistivity \":[-9.695809636391175,8.881161293379026],\"Restoration\":[6.00548920332655,5.164627384713775],\"Storing Carbon\":[0.7335156945392783,-2.1725481490165204],\"Structure\":[2.99107184329659,3.454534113838058],\"Supporting a living ecosystem\":[-1.1330617116056143,-0.9327657548538072],\"Sustaining animal health\":[0.7407650940172219,6.66597559947256],\"Sustaining human health\":[4.746760404692643,2.404635322982228],\"Sustaining plant health\":[-0.6682628230855774,-1.8584603763947156],\"Temperature\":[2.204645996551671,-7.100620965958784],\"Texture\":[-0.18964593045334915,4.039348605842226]}},\"id\":\"3552\",\"type\":\"StaticLayoutProvider\"},{\"attributes\":{\"edge_renderer\":{\"id\":\"3550\"},\"inspection_policy\":{\"id\":\"3585\"},\"layout_provider\":{\"id\":\"3552\"},\"node_renderer\":{\"id\":\"3546\"},\"selection_policy\":{\"id\":\"3583\"}},\"id\":\"3543\",\"type\":\"GraphRenderer\"},{\"attributes\":{\"formatter\":{\"id\":\"3789\"},\"major_label_policy\":{\"id\":\"3788\"},\"ticker\":{\"id\":\"3529\"}},\"id\":\"3528\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"3525\",\"type\":\"BasicTicker\"},{\"attributes\":{\"data\":{\"adjusted_node_size\":[14,13,15,13,14,11,10,17,17,18,10,19,14,16,8,12,12,11,12,9,20,7,15,19,7,16,7,14,10,14],\"degree\":[9,8,10,8,9,6,5,12,12,13,5,14,9,11,3,7,7,6,7,4,15,2,10,14,2,11,2,9,5,9],\"index\":[\"Acidity (pH)\",\"Capturing Critical Zone processes\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Restoration\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Bulk Density\",\"Carbon Content\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining human health\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Modification\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Porosity \",\"Resistivity \",\"Structure\",\"Temperature\",\"Texture\"],\"modularity_class\":[1,2,0,1,0,1,1,2,1,0,2,1,0,0,1,2,2,0,0,0,2,2,2,1,1,0,0,2,1,2],\"modularity_color\":[\"#66c2a5\",\"#abdda4\",\"#3288bd\",\"#66c2a5\",\"#3288bd\",\"#66c2a5\",\"#66c2a5\",\"#abdda4\",\"#66c2a5\",\"#3288bd\",\"#abdda4\",\"#66c2a5\",\"#3288bd\",\"#3288bd\",\"#66c2a5\",\"#abdda4\",\"#abdda4\",\"#3288bd\",\"#3288bd\",\"#3288bd\",\"#abdda4\",\"#abdda4\",\"#abdda4\",\"#66c2a5\",\"#66c2a5\",\"#3288bd\",\"#3288bd\",\"#abdda4\",\"#66c2a5\",\"#abdda4\"]},\"selected\":{\"id\":\"3794\"},\"selection_policy\":{\"id\":\"3795\"}},\"id\":\"3545\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"end\":10.1,\"start\":-10.1},\"id\":\"3514\",\"type\":\"Range1d\"},{\"attributes\":{},\"id\":\"3533\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"3529\",\"type\":\"BasicTicker\"},{\"attributes\":{\"data\":{\"end\":[\"Capturing Critical Zone processes\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Restoration\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Bulk Density\",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Carbon Content\",\"Colour\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Temperature\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Structure\",\"Temperature\",\"Carbon Content\",\"Moisture\",\"Organic Matter Content\",\"Porosity \",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Compaction\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Organisms present\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Bulk Density\",\"Carbon Content\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Temperature\",\"Texture\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining human health\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Resistivity \",\"Texture\",\"Colour\",\"Compaction\",\"Inorganic inclusions\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Resistivity \",\"Structure\",\"Texture\",\"Moisture\",\"Organic Matter Content\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Moisture\",\"Nutrient Content \",\"Organic Matter Content\",\"Porosity \",\"Structure\",\"Texture\",\"Modification\",\"Nutrient Content \"],\"start\":[\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Acidity (pH)\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Capturing Critical Zone processes\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Erosion\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing ecosystem processes\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Evidencing human-ecosystem interactions\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Regulating Climate\",\"Restoration\",\"Restoration\",\"Restoration\",\"Restoration\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Storing Carbon\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Supporting a living ecosystem\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Sustaining plant health\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Carbon Content\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past ecosystem processes\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Archiving evidence of past human activities\",\"Forming rural landscapes\",\"Forming rural landscapes\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining animal health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Sustaining human health\",\"Moisture\",\"Modification\"]},\"selected\":{\"id\":\"3792\"},\"selection_policy\":{\"id\":\"3793\"}},\"id\":\"3549\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"formatter\":{\"id\":\"3786\"},\"major_label_policy\":{\"id\":\"3785\"},\"ticker\":{\"id\":\"3525\"}},\"id\":\"3524\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"3583\",\"type\":\"NodesAndLinkedEdges\"},{\"attributes\":{\"source\":{\"id\":\"3545\"}},\"id\":\"3547\",\"type\":\"CDSView\"},{\"attributes\":{\"line_alpha\":{\"value\":0.3}},\"id\":\"3568\",\"type\":\"MultiLine\"},{\"attributes\":{\"fill_color\":{\"field\":\"modularity_color\"},\"size\":{\"field\":\"adjusted_node_size\"}},\"id\":\"3553\",\"type\":\"Circle\"},{\"attributes\":{\"fill_color\":{\"value\":\"white\"},\"line_width\":{\"value\":2},\"size\":{\"field\":\"adjusted_node_size\"}},\"id\":\"3563\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"3785\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"3522\",\"type\":\"LinearScale\"},{\"attributes\":{\"axis\":{\"id\":\"3524\"},\"ticker\":null},\"id\":\"3527\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"3532\",\"type\":\"PanTool\"},{\"attributes\":{},\"id\":\"3535\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"3788\",\"type\":\"AllLabels\"},{\"attributes\":{\"text\":\"soil health and heritage\"},\"id\":\"3516\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"3789\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"end\":10.1,\"start\":-10.1},\"id\":\"3513\",\"type\":\"Range1d\"},{\"attributes\":{\"source\":{\"id\":\"3549\"}},\"id\":\"3551\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"3791\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"3585\",\"type\":\"NodesAndLinkedEdges\"},{\"attributes\":{},\"id\":\"3534\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"3792\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"3786\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"axis\":{\"id\":\"3528\"},\"dimension\":1,\"ticker\":null},\"id\":\"3531\",\"type\":\"Grid\"}],\"root_ids\":[\"3515\"]},\"title\":\"Bokeh Application\",\"version\":\"2.3.3\"}};\n",
" var render_items = [{\"docid\":\"ffb6bc5f-cf5d-493b-a7c4-822bb103d4bd\",\"root_ids\":[\"3515\"],\"roots\":{\"3515\":\"88f5e00f-3c2c-4f80-9f1f-925ae4f863f9\"}}];\n",
" root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
"\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" embed_document(root);\n",
" } else {\n",
" var attempts = 0;\n",
" var timer = setInterval(function(root) {\n",
" if (root.Bokeh !== undefined) {\n",
" clearInterval(timer);\n",
" embed_document(root);\n",
" } else {\n",
" attempts++;\n",
" if (attempts > 100) {\n",
" clearInterval(timer);\n",
" console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
" }\n",
" }\n",
" }, 10, root)\n",
" }\n",
"})(window);"
],
"application/vnd.bokehjs_exec.v0+json": ""
},
"metadata": {
"application/vnd.bokehjs_exec.v0+json": {
"id": "3515"
}
}
}
],
"source": [
"#Choose colors for node and edge highlighting\n",
"node_highlight_color = 'white'\n",
"edge_highlight_color = 'black'\n",
"\n",
"#Choose attributes from G network to size and color by — setting manual size (e.g. 10) or color (e.g. 'skyblue') also allowed\n",
"size_by_this_attribute = 'adjusted_node_size'\n",
"color_by_this_attribute = 'modularity_color'\n",
"\n",
"#Pick a color palette — Blues8, Reds8, Purples8, Oranges8, Viridis8\n",
"color_palette = Blues8\n",
"\n",
"#Choose a title!\n",
"title = 'soil health and heritage'\n",
"\n",
"#Establish which categories will appear when hovering over each node\n",
"HOVER_TOOLTIPS = [\n",
" (\"concept\", \"@index\"),\n",
" (\"Degree\", \"@degree\"),\n",
" (\"Modularity Class\", \"@modularity_class\"),\n",
" (\"Modularity Color\", \"$color[swatch]:modularity_color\"),\n",
"]\n",
"\n",
"#Create a plot — set dimensions, toolbar, and title\n",
"plot = figure(tooltips = HOVER_TOOLTIPS,\n",
" tools=\"pan,wheel_zoom,save,reset\", active_scroll='wheel_zoom',\n",
" x_range=Range1d(-10.1, 10.1), y_range=Range1d(-10.1, 10.1), title=title)\n",
"\n",
"#Create a network graph object\n",
"# https://networkx.github.io/documentation/networkx-1.9/reference/generated/networkx.drawing.layout.spring_layout.html\n",
"network_graph = from_networkx(G, networkx.spring_layout, scale=10, center=(0, 0))\n",
"\n",
"#Set node sizes and colors according to node degree (color as category from attribute)\n",
"network_graph.node_renderer.glyph = Circle(size=size_by_this_attribute, fill_color=color_by_this_attribute)\n",
"#Set node highlight colors\n",
"network_graph.node_renderer.hover_glyph = Circle(size=size_by_this_attribute, fill_color=node_highlight_color, line_width=2)\n",
"network_graph.node_renderer.selection_glyph = Circle(size=size_by_this_attribute, fill_color=node_highlight_color, line_width=2)\n",
"\n",
"#Set edge opacity and width\n",
"network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.3, line_width=1)\n",
"#Set edge highlight colors\n",
"network_graph.edge_renderer.selection_glyph = MultiLine(line_color=edge_highlight_color, line_width=2)\n",
"network_graph.edge_renderer.hover_glyph = MultiLine(line_color=edge_highlight_color, line_width=2)\n",
"\n",
"#Highlight nodes and edges\n",
"network_graph.selection_policy = NodesAndLinkedEdges()\n",
"network_graph.inspection_policy = NodesAndLinkedEdges()\n",
"\n",
"plot.renderers.append(network_graph)\n",
"\n",
"#Add Labels\n",
"x, y = zip(*network_graph.layout_provider.graph_layout.values())\n",
"node_labels = list(G.nodes())\n",
"source = ColumnDataSource({'x': x, 'y': y, 'name': [node_labels[i] for i in range(len(x))]})\n",
"labels = LabelSet(x='x', y='y', text='name', source=source, background_fill_color='white', text_font_size='10px', background_fill_alpha=.7)\n",
"plot.renderers.append(labels)\n",
"\n",
"show(plot)\n",
"#save(plot, filename=f\"{title}.html\")"
]
},
{
"cell_type": "code",
"source": [
"from operator import itemgetter"
],
"metadata": {
"id": "LmQuUUkWhtEO"
},
"execution_count": 71,
"outputs": []
},
{
"cell_type": "code",
"source": [
"#Betweenness Centrality\n",
"betweenness_dict = networkx.betweenness_centrality(G) #Create a dictionary and run the measurement\n",
"networkx.set_node_attributes(G, betweenness_dict, 'Betweenness') #Add the betweeness centrality as an attribute to the nodes\n",
"\n",
"#We'll now sort the cities by their betweenness centrality and print a \"Top 5\" list\n",
"sorted_betweenness = sorted(betweenness_dict.items(), key=itemgetter(1), reverse=True)\n",
"\n",
"print(\"Top 5 Concepts by Betweenness Centrality:\")\n",
"for b in sorted_betweenness[:5]:\n",
" print(b)\n"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Jr7sYX6jhcjm",
"outputId": "c267fce6-7454-44bf-aeb7-c34985ca4ad0"
},
"execution_count": 72,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Top 5 Concepts by Betweenness Centrality:\n",
"('Moisture', 0.12978910970052002)\n",
"('Supporting a living ecosystem', 0.08855583454258253)\n",
"('Carbon Content', 0.08796207142300787)\n",
"('Organic Matter Content', 0.08796207142300787)\n",
"('Sustaining plant health', 0.08035117215411909)\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"#Let's create a dictionary to add the degree and run \"G.degree()\" in it.\n",
"degree_dict = dict(G.degree(G.nodes()))\n",
"networkx.set_node_attributes(G, degree_dict, 'degree') #We add the degree as an attribute to the nodes\n",
"\n",
"#Now we sort the nodes by degree, making sure to put the higher degrees first with \"reverse=True\"\n",
"sorted_degree = sorted(degree_dict.items(), key=itemgetter(1), reverse=True)\n",
"print(\"Concepts by Degree:\", sorted_degree) #Remember to print and name your list!"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "cpHtIZvShEal",
"outputId": "32ce6bcf-aa86-4650-bc3a-189b6ffbb33d"
},
"execution_count": 73,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Concepts by Degree: [('Moisture', 15), ('Carbon Content', 14), ('Organic Matter Content', 14), ('Sustaining plant health', 13), ('Storing Carbon', 12), ('Supporting a living ecosystem', 12), ('Archiving evidence of past human activities', 11), ('Porosity ', 11), ('Erosion', 10), ('Nutrient Content ', 10), ('Acidity (pH)', 9), ('Evidencing human-ecosystem interactions', 9), ('Archiving evidence of past ecosystem processes', 9), ('Structure', 9), ('Texture', 9), ('Capturing Critical Zone processes', 8), ('Evidencing ecosystem processes', 8), ('Sustaining animal health', 7), ('Sustaining human health', 7), ('Compaction', 7), ('Regulating Climate', 6), ('Colour', 6), ('Restoration', 5), ('Bulk Density', 5), ('Temperature', 5), ('Inorganic inclusions', 4), ('Forming rural landscapes', 3), ('Modification', 2), ('Organisms present', 2), ('Resistivity ', 2)]\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"#Density Analysis\n",
"density = networkx.density(G) #This calculates the density\n",
"print(\"Concept Network Density:\", density) #Let's print it and name it so that we do not forget\n",
"\n",
"#Diameter Analysis\n",
"diameter = networkx.diameter(G)\n",
"print(\"Concept Network Diameter\", diameter)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "QY2X4Tn6iASv",
"outputId": "ad536879-885b-49b6-e627-c66c5457ae99"
},
"execution_count": 74,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Concept Network Density: 0.28045977011494255\n",
"Concept Network Diameter 4\n"
]
}
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.8.8"
},
"colab": {
"name": "soil-concept-network-viz.ipynb",
"provenance": [],
"collapsed_sections": [
"64JXZTsSUsRJ",
"YxRyQkfjUsRL"
],
"include_colab_link": true
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment