diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 122fc11..b45f102 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -15,20 +15,20 @@ jobs:
strategy:
matrix:
os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
- python-version: [3.7, 3.8, 3.9, '3.10']
+ python-version: [3.8, 3.9, '3.10', '3.11']
exclude:
- - os: windows-latest
- python-version: 3.8
- os: windows-latest
python-version: 3.9
- os: windows-latest
python-version: '3.10'
- - os: macos-latest
- python-version: 3.8
+ - os: windows-latest
+ python-version: '3.11'
- os: macos-latest
python-version: 3.9
- os: macos-latest
python-version: '3.10'
+ - os: macos-latest
+ python-version: '3.11'
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md
index c4104d6..2981169 100644
--- a/DEVELOPER_GUIDE.md
+++ b/DEVELOPER_GUIDE.md
@@ -18,7 +18,7 @@ Below we describe how to install and use this project for development.
To install for development you will need to create and activate a virtual environment
```bash
-conda create --name panel-chemistry python=3.9 nodejs
+conda create --name panel-chemistry python=3.10 nodejs
conda activate panel-chemistry
```
diff --git a/examples/reference/JSMEEditor.ipynb b/examples/reference/JSMEEditor.ipynb
index 37e1691..c02b6a5 100644
--- a/examples/reference/JSMEEditor.ipynb
+++ b/examples/reference/JSMEEditor.ipynb
@@ -161,7 +161,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@@ -175,7 +175,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.8.4"
+ "version": "3.11.6"
}
},
"nbformat": 4,
diff --git a/examples/reference/NGLViewer.ipynb b/examples/reference/NGLViewer.ipynb
index a376afb..bde4304 100644
--- a/examples/reference/NGLViewer.ipynb
+++ b/examples/reference/NGLViewer.ipynb
@@ -83,14 +83,7 @@
"cell_type": "code",
"execution_count": null,
"id": "6e35c77b",
- "metadata": {
- "jupyter": {
- "outputs_hidden": false
- },
- "pycharm": {
- "name": "#%%\n"
- }
- },
+ "metadata": {},
"outputs": [],
"source": [
"file_input = pn.widgets.FileInput(accept=','.join('.' + s for s in EXTENSIONS[1:]))\n",
@@ -183,7 +176,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@@ -197,7 +190,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.8.4"
+ "version": "3.11.6"
}
},
"nbformat": 4,
diff --git a/examples/reference/PDBe_MolStar.ipynb b/examples/reference/PDBe_MolStar.ipynb
index 34fefc7..cae9558 100644
--- a/examples/reference/PDBe_MolStar.ipynb
+++ b/examples/reference/PDBe_MolStar.ipynb
@@ -26,424 +26,9 @@
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "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",
- " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
- " root._bokeh_timeout = Date.now() + 5000;\n",
- " root._bokeh_failed_load = false;\n",
- " }\n",
- "\n",
- " function run_callbacks() {\n",
- " try {\n",
- " root._bokeh_onload_callbacks.forEach(function(callback) {\n",
- " if (callback != null)\n",
- " callback();\n",
- " });\n",
- " } finally {\n",
- " delete root._bokeh_onload_callbacks\n",
- " }\n",
- " console.debug(\"Bokeh: all callbacks have finished\");\n",
- " }\n",
- "\n",
- " function load_libs(css_urls, js_urls, js_modules, callback) {\n",
- " if (css_urls == null) css_urls = [];\n",
- " if (js_urls == null) js_urls = [];\n",
- " if (js_modules == null) js_modules = [];\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.length === 0 && js_modules.length === 0) {\n",
- " run_callbacks();\n",
- " return null;\n",
- " }\n",
- " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\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() {\n",
- " console.error(\"failed to load \" + url);\n",
- " }\n",
- "\n",
- " for (var i = 0; i < css_urls.length; i++) {\n",
- " var url = css_urls[i];\n",
- " const element = document.createElement(\"link\");\n",
- " element.onload = on_load;\n",
- " element.onerror = on_error;\n",
- " element.rel = \"stylesheet\";\n",
- " element.type = \"text/css\";\n",
- " element.href = url;\n",
- " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n",
- " document.body.appendChild(element);\n",
- " }\n",
- "\n",
- " var skip = [];\n",
- " if (window.requirejs) {\n",
- " window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n",
- " \n",
- " root._bokeh_is_loading = css_urls.length + 0;\n",
- " } else {\n",
- " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length;\n",
- " }\n",
- " for (var i = 0; i < js_urls.length; i++) {\n",
- " var url = js_urls[i];\n",
- " if (skip.indexOf(url) >= 0) {\n",
- "\tif (!window.requirejs) {\n",
- "\t on_load();\n",
- "\t}\n",
- "\tcontinue;\n",
- " }\n",
- " var element = document.createElement('script');\n",
- " element.onload = on_load;\n",
- " element.onerror = on_error;\n",
- " element.async = false;\n",
- " element.src = url;\n",
- " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
- " document.head.appendChild(element);\n",
- " }\n",
- " for (var i = 0; i < js_modules.length; i++) {\n",
- " var url = js_modules[i];\n",
- " if (skip.indexOf(url) >= 0) {\n",
- "\tif (!window.requirejs) {\n",
- "\t on_load();\n",
- "\t}\n",
- "\tcontinue;\n",
- " }\n",
- " var element = document.createElement('script');\n",
- " element.onload = on_load;\n",
- " element.onerror = on_error;\n",
- " element.async = false;\n",
- " element.src = url;\n",
- " element.type = \"module\";\n",
- " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
- " document.head.appendChild(element);\n",
- " }\n",
- " if (!js_urls.length && !js_modules.length) {\n",
- " on_load()\n",
- " }\n",
- " };\n",
- "\n",
- " function inject_raw_css(css) {\n",
- " const element = document.createElement(\"style\");\n",
- " element.appendChild(document.createTextNode(css));\n",
- " document.body.appendChild(element);\n",
- " }\n",
- "\n",
- " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.2.min.js\", \"https://www.ebi.ac.uk/pdbe/pdb-component-library/js/pdbe-molstar-plugin-1.2.1.js\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/panel.min.js\"];\n",
- " var js_modules = [];\n",
- " var css_urls = [\"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/card.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/dataframe.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/json.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/loading.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/widgets.css\"];\n",
- " var inline_js = [\n",
- " function(Bokeh) {\n",
- " inject_raw_css(\"\\n .bk.pn-loading.arcs:before {\\n background-image: url(\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiBub25lOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4gIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZT0iI2MzYzNjMyIgc3Ryb2tlLWRhc2hhcnJheT0iNTAuMjY1NDgyNDU3NDM2NjkgNTAuMjY1NDgyNDU3NDM2NjkiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+ICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxcyIga2V5VGltZXM9IjA7MSIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCI+PC9hbmltYXRlVHJhbnNmb3JtPiAgPC9jaXJjbGU+PC9zdmc+\\\");\\n max-height: 400px;\\n }\\n \");\n",
- " },\n",
- " function(Bokeh) {\n",
- " Bokeh.set_log_level(\"info\");\n",
- " },\n",
- " function(Bokeh) {} // ensure no trailing comma for IE\n",
- " ];\n",
- "\n",
- " function run_inline_js() {\n",
- " if ((root.Bokeh !== undefined) || (force === true)) {\n",
- " for (var i = 0; i < inline_js.length; i++) {\n",
- " inline_js[i].call(root, root.Bokeh);\n",
- " }} else if (Date.now() < root._bokeh_timeout) {\n",
- " setTimeout(run_inline_js, 100);\n",
- " } else if (!root._bokeh_failed_load) {\n",
- " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
- " root._bokeh_failed_load = true;\n",
- " }\n",
- " }\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, js_modules, function() {\n",
- " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
- " run_inline_js();\n",
- " });\n",
- " }\n",
- "}(window));"
- ],
- "application/vnd.holoviews_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 if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\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.length === 0 && js_modules.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\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() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n \n root._bokeh_is_loading = css_urls.length + 0;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length;\n }\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.2.min.js\", \"https://www.ebi.ac.uk/pdbe/pdb-component-library/js/pdbe-molstar-plugin-1.2.1.js\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/panel.min.js\"];\n var js_modules = [];\n var css_urls = [\"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/card.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/dataframe.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/json.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/loading.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.12.6/dist/css/widgets.css\"];\n var inline_js = [\n function(Bokeh) {\n inject_raw_css(\"\\n .bk.pn-loading.arcs:before {\\n background-image: url(\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiBub25lOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4gIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZT0iI2MzYzNjMyIgc3Ryb2tlLWRhc2hhcnJheT0iNTAuMjY1NDgyNDU3NDM2NjkgNTAuMjY1NDgyNDU3NDM2NjkiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+ICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxcyIga2V5VGltZXM9IjA7MSIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCI+PC9hbmltYXRlVHJhbnNmb3JtPiAgPC9jaXJjbGU+PC9zdmc+\\\");\\n max-height: 400px;\\n }\\n \");\n },\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n }\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, js_modules, 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": {
- "application/javascript": [
- "\n",
- "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n",
- " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n",
- "}\n",
- "\n",
- "\n",
- " function JupyterCommManager() {\n",
- " }\n",
- "\n",
- " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n",
- " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n",
- " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n",
- " comm_manager.register_target(comm_id, function(comm) {\n",
- " comm.on_msg(msg_handler);\n",
- " });\n",
- " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n",
- " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n",
- " comm.onMsg = msg_handler;\n",
- " });\n",
- " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n",
- " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n",
- " var messages = comm.messages[Symbol.asyncIterator]();\n",
- " function processIteratorResult(result) {\n",
- " var message = result.value;\n",
- " console.log(message)\n",
- " var content = {data: message.data, comm_id};\n",
- " var buffers = []\n",
- " for (var buffer of message.buffers || []) {\n",
- " buffers.push(new DataView(buffer))\n",
- " }\n",
- " var metadata = message.metadata || {};\n",
- " var msg = {content, buffers, metadata}\n",
- " msg_handler(msg);\n",
- " return messages.next().then(processIteratorResult);\n",
- " }\n",
- " return messages.next().then(processIteratorResult);\n",
- " })\n",
- " }\n",
- " }\n",
- "\n",
- " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n",
- " if (comm_id in window.PyViz.comms) {\n",
- " return window.PyViz.comms[comm_id];\n",
- " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n",
- " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n",
- " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n",
- " if (msg_handler) {\n",
- " comm.on_msg(msg_handler);\n",
- " }\n",
- " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n",
- " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n",
- " comm.open();\n",
- " if (msg_handler) {\n",
- " comm.onMsg = msg_handler;\n",
- " }\n",
- " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n",
- " var comm_promise = google.colab.kernel.comms.open(comm_id)\n",
- " comm_promise.then((comm) => {\n",
- " window.PyViz.comms[comm_id] = comm;\n",
- " if (msg_handler) {\n",
- " var messages = comm.messages[Symbol.asyncIterator]();\n",
- " function processIteratorResult(result) {\n",
- " var message = result.value;\n",
- " var content = {data: message.data};\n",
- " var metadata = message.metadata || {comm_id};\n",
- " var msg = {content, metadata}\n",
- " msg_handler(msg);\n",
- " return messages.next().then(processIteratorResult);\n",
- " }\n",
- " return messages.next().then(processIteratorResult);\n",
- " }\n",
- " }) \n",
- " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n",
- " return comm_promise.then((comm) => {\n",
- " comm.send(data, metadata, buffers, disposeOnDone);\n",
- " });\n",
- " };\n",
- " var comm = {\n",
- " send: sendClosure\n",
- " };\n",
- " }\n",
- " window.PyViz.comms[comm_id] = comm;\n",
- " return comm;\n",
- " }\n",
- " window.PyViz.comm_manager = new JupyterCommManager();\n",
- " \n",
- "\n",
- "\n",
- "var JS_MIME_TYPE = 'application/javascript';\n",
- "var HTML_MIME_TYPE = 'text/html';\n",
- "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n",
- "var CLASS_NAME = 'output';\n",
- "\n",
- "/**\n",
- " * Render data to the DOM node\n",
- " */\n",
- "function render(props, node) {\n",
- " var div = document.createElement(\"div\");\n",
- " var script = document.createElement(\"script\");\n",
- " node.appendChild(div);\n",
- " node.appendChild(script);\n",
- "}\n",
- "\n",
- "/**\n",
- " * Handle when a new output is added\n",
- " */\n",
- "function handle_add_output(event, handle) {\n",
- " var output_area = handle.output_area;\n",
- " var output = handle.output;\n",
- " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n",
- " return\n",
- " }\n",
- " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
- " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
- " if (id !== undefined) {\n",
- " var nchildren = toinsert.length;\n",
- " var html_node = toinsert[nchildren-1].children[0];\n",
- " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n",
- " var scripts = [];\n",
- " var nodelist = html_node.querySelectorAll(\"script\");\n",
- " for (var i in nodelist) {\n",
- " if (nodelist.hasOwnProperty(i)) {\n",
- " scripts.push(nodelist[i])\n",
- " }\n",
- " }\n",
- "\n",
- " scripts.forEach( function (oldScript) {\n",
- " var newScript = document.createElement(\"script\");\n",
- " var attrs = [];\n",
- " var nodemap = oldScript.attributes;\n",
- " for (var j in nodemap) {\n",
- " if (nodemap.hasOwnProperty(j)) {\n",
- " attrs.push(nodemap[j])\n",
- " }\n",
- " }\n",
- " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n",
- " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n",
- " oldScript.parentNode.replaceChild(newScript, oldScript);\n",
- " });\n",
- " if (JS_MIME_TYPE in output.data) {\n",
- " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n",
- " }\n",
- " output_area._hv_plot_id = id;\n",
- " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n",
- " window.PyViz.plot_index[id] = Bokeh.index[id];\n",
- " } else {\n",
- " window.PyViz.plot_index[id] = null;\n",
- " }\n",
- " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
- " var bk_div = document.createElement(\"div\");\n",
- " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
- " var script_attrs = bk_div.children[0].attributes;\n",
- " for (var i = 0; i < script_attrs.length; i++) {\n",
- " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
- " }\n",
- " // store reference to server id on output_area\n",
- " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
- " }\n",
- "}\n",
- "\n",
- "/**\n",
- " * Handle when an output is cleared or removed\n",
- " */\n",
- "function handle_clear_output(event, handle) {\n",
- " var id = handle.cell.output_area._hv_plot_id;\n",
- " var server_id = handle.cell.output_area._bokeh_server_id;\n",
- " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n",
- " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n",
- " if (server_id !== null) {\n",
- " comm.send({event_type: 'server_delete', 'id': server_id});\n",
- " return;\n",
- " } else if (comm !== null) {\n",
- " comm.send({event_type: 'delete', 'id': id});\n",
- " }\n",
- " delete PyViz.plot_index[id];\n",
- " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n",
- " var doc = window.Bokeh.index[id].model.document\n",
- " doc.clear();\n",
- " const i = window.Bokeh.documents.indexOf(doc);\n",
- " if (i > -1) {\n",
- " window.Bokeh.documents.splice(i, 1);\n",
- " }\n",
- " }\n",
- "}\n",
- "\n",
- "/**\n",
- " * Handle kernel restart event\n",
- " */\n",
- "function handle_kernel_cleanup(event, handle) {\n",
- " delete PyViz.comms[\"hv-extension-comm\"];\n",
- " window.PyViz.plot_index = {}\n",
- "}\n",
- "\n",
- "/**\n",
- " * Handle update_display_data messages\n",
- " */\n",
- "function handle_update_output(event, handle) {\n",
- " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n",
- " handle_add_output(event, handle)\n",
- "}\n",
- "\n",
- "function register_renderer(events, OutputArea) {\n",
- " function append_mime(data, metadata, element) {\n",
- " // create a DOM node to render to\n",
- " var toinsert = this.create_output_subarea(\n",
- " metadata,\n",
- " CLASS_NAME,\n",
- " EXEC_MIME_TYPE\n",
- " );\n",
- " this.keyboard_manager.register_events(toinsert);\n",
- " // Render to node\n",
- " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
- " render(props, toinsert[0]);\n",
- " element.append(toinsert);\n",
- " return toinsert\n",
- " }\n",
- "\n",
- " events.on('output_added.OutputArea', handle_add_output);\n",
- " events.on('output_updated.OutputArea', handle_update_output);\n",
- " events.on('clear_output.CodeCell', handle_clear_output);\n",
- " events.on('delete.Cell', handle_clear_output);\n",
- " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n",
- "\n",
- " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
- " safe: true,\n",
- " index: 0\n",
- " });\n",
- "}\n",
- "\n",
- "if (window.Jupyter !== undefined) {\n",
- " try {\n",
- " var events = require('base/js/events');\n",
- " var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
- " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
- " register_renderer(events, OutputArea);\n",
- " }\n",
- " } catch(err) {\n",
- " }\n",
- "}\n"
- ],
- "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n"
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"from panel_chemistry.pane import PDBeMolStar\n",
"import param\n",
@@ -462,64 +47,9 @@
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {},
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "application/vnd.holoviews_exec.v0+json": "",
- "text/html": [
- "
\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "
\n",
- "
\n",
- ""
- ],
- "text/plain": [
- "PDBeMolStar(height=500, molecule_id='1qyn', sizing_mode='stretch_width')"
- ]
- },
- "execution_count": 5,
- "metadata": {
- "application/vnd.holoviews_exec.v0+json": {
- "id": "1007"
- }
- },
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"PDBeMolStar(\n",
" height=500,\n",
@@ -536,64 +66,9 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {},
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "application/vnd.holoviews_exec.v0+json": "",
- "text/html": [
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "
\n",
- "
\n",
- ""
- ],
- "text/plain": [
- "PDBeMolStar(custom_data={'url': 'http://localhost:...}, height=500, name='Local File', sizing_mode='stretch_width')"
- ]
- },
- "execution_count": 6,
- "metadata": {
- "application/vnd.holoviews_exec.v0+json": {
- "id": "1010"
- }
- },
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"PDBeMolStar(\n",
" name='Local File',\n",
@@ -894,8 +369,7 @@
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.7"
+ "pygments_lexer": "ipython3"
}
},
"nbformat": 4,
diff --git a/examples/reference/Py3DMol.ipynb b/examples/reference/Py3DMol.ipynb
index ccde4af..6f946eb 100644
--- a/examples/reference/Py3DMol.ipynb
+++ b/examples/reference/Py3DMol.ipynb
@@ -307,8 +307,7 @@
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.4"
+ "pygments_lexer": "ipython3"
}
},
"nbformat": 4,
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..160b51d
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,10 @@
+{
+ "name": "panel-chemistry",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "panel-chemistry"
+ }
+ }
+}
diff --git a/pyproject.toml b/pyproject.toml
index b295611..85792ae 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -34,7 +34,7 @@ classifiers = [
"Topic :: Software Development :: Libraries",
]
dependencies = [
- "panel",
+ "panel>=1.0",
]
dynamic = ["version"]
@@ -65,7 +65,7 @@ profile = "black"
src_paths = ["src", "tests"]
[tool.pylint.main]
-py-version=3.9
+py-version=3.10
output-format = "colorized"
max-attributes=12
max-args=10
@@ -75,7 +75,7 @@ max-module-lines = 1000
max-line-length=100
[tool.mypy]
-python_version = "3.9"
+python_version = "3.10"
namespace_packages = true
explicit_package_bases = true
mypy_path = "src"
@@ -84,11 +84,13 @@ exclude = []
[[tool.mypy.overrides]]
module = [
"bokeh.*",
+ "comm.*",
"holoviews.*",
"hvplot.*",
"param",
- "pyviz_comms",
"py3Dmol",
+ "pydantic.*",
+ "pyviz_comms",
]
ignore_missing_imports = true
diff --git a/script.py b/script.py
new file mode 100644
index 0000000..f95a393
--- /dev/null
+++ b/script.py
@@ -0,0 +1,49 @@
+import panel as pn
+from panel_chemistry.pane import NGLViewer # panel_chemistry needs to be imported before you run pn.extension()
+from panel_chemistry.pane.ngl_viewer import EXTENSIONS
+
+pn.extension("ngl_viewer", sizing_mode="stretch_width")
+
+viewer = NGLViewer(object="1CRN", background_color="#F7F7F7", styles={"border": "1px solid lightgray"}, min_height=700, sizing_mode="stretch_both")
+
+settings = pn.Param(
+ viewer,
+ parameters=["object","extension","representation","color_scheme","custom_color_scheme","effect",],
+ name="⚙️ Settings"
+)
+
+file_input = pn.widgets.FileInput(accept=','.join('.' + s for s in EXTENSIONS[1:]))
+
+def filename_callback(target, event):
+ target.extension = event.new.split('.')[1]
+
+def value_callback(target, event):
+ target.object = event.new.decode('utf-8')
+
+file_input.link(viewer, callbacks={'value': value_callback, 'filename': filename_callback})
+
+header = pn.widgets.StaticText(value='{0}'.format("💾 File Input"))
+file_column = pn.layout.Column(header, file_input)
+
+layout = pn.Param(
+ viewer,
+ parameters=["sizing_mode", "width", "height", "background_color"],
+ name="📐 Layout"
+)
+
+pn.Row(
+ viewer,
+ pn.WidgetBox(settings, layout, width=300, sizing_mode="fixed",),
+)
+
+
+accent="#D2386C"
+
+pn.template.FastListTemplate(
+ site="Panel Chemistry", site_url="./",
+ title="NGLViewer",
+ sidebar=[file_column, settings, layout],
+ main=[viewer],
+ accent_base_color=accent, header_background=accent,
+).servable();
+
diff --git a/src/panel_chemistry/__init__.py b/src/panel_chemistry/__init__.py
index 5710cf0..b0828c8 100644
--- a/src/panel_chemistry/__init__.py
+++ b/src/panel_chemistry/__init__.py
@@ -2,4 +2,4 @@
develop high-quality [Panel](https://awesome-panel.org) **data apps** within the domain of
**chemistry**.
"""
-VERSION = "0.2.2"
+VERSION = "0.3.0"
diff --git a/src/panel_chemistry/bokeh_extensions/jsme_editor.py b/src/panel_chemistry/bokeh_extensions/jsme_editor.py
index 15f87a4..7cb2384 100644
--- a/src/panel_chemistry/bokeh_extensions/jsme_editor.py
+++ b/src/panel_chemistry/bokeh_extensions/jsme_editor.py
@@ -1,27 +1,35 @@
"""A Bokeh model for the JSMEEditor"""
from bokeh.core.properties import List, String
-from bokeh.models import HTMLBox
from panel import extension
+from panel.models.layout import HTMLBox
# pylint: disable=protected-access
extension._imports["jsme"] = "panel_chemistry.bokeh_extensions.jsme_editor"
# pylint: enable=protected-access
-class JSMEEditor(HTMLBox):
+class JSMEEditor(HTMLBox): # pylint: disable=too-few-public-methods,too-many-ancestors
"""JSMEEditor Bokeh Model"""
- __javascript__ = ["https://unpkg.com/jsme-editor@0.8.2/jsme.nocache.js"]
+ __javascript__ = [
+ "https://cdn.jsdelivr.net/npm/jsme-editor@2023.7.31/jsme.nocache.js",
+ ]
- value = String()
- format = String()
- subscriptions = List(String())
- options = List(String())
+ __css__ = [
+ "https://cdn.jsdelivr.net/npm/jsme-editor@2023.7.31/gwt/chrome/mosaic.css",
+ "https://cdn.jsdelivr.net/npm/jsme-editor@2023.7.31/jsa.css",
+ "https://cdn.jsdelivr.net/npm/jsme-editor@2023.7.31/gwt/chrome/chrome.css",
+ ]
- jme = String()
- smiles = String()
- mol = String()
- mol3000 = String()
- sdf = String()
+ value = String(default="")
+ format = String(default="smiles")
+ subscriptions = List(String, default=[]) # type: ignore
+ options = List(String, default=[]) # type: ignore
- guicolor = String()
+ jme = String(default="")
+ smiles = String(default="")
+ mol = String(default="")
+ mol3000 = String(default="")
+ sdf = String(default="")
+
+ guicolor = String(default="#c0c0c0")
diff --git a/src/panel_chemistry/bokeh_extensions/jsme_editor.ts b/src/panel_chemistry/bokeh_extensions/jsme_editor.ts
index 6f048c7..64783b1 100644
--- a/src/panel_chemistry/bokeh_extensions/jsme_editor.ts
+++ b/src/panel_chemistry/bokeh_extensions/jsme_editor.ts
@@ -1,17 +1,10 @@
// See https://docs.bokeh.org/en/latest/docs/reference/models/layouts.html
-import { HTMLBox, HTMLBoxView } from "@bokehjs/models/layouts/html_box"
+import { uuidv4, HTMLBox, HTMLBoxView } from "./layout"
// See https://docs.bokeh.org/en/latest/docs/reference/core/properties.html
import * as p from "@bokehjs/core/properties"
import {div} from "@bokehjs/core/dom"
-function uuidv4() {
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
- var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
- return v.toString(16);
- });
- }
-
const notSubscribed = "Not Subscribed"
function readSDFValue(jsmeElement: any) {
@@ -24,12 +17,9 @@ function readSDFValue(jsmeElement: any) {
}
function setModelValue(model: JSMEEditor, jsmeElement: any){
- console.log("setValue - start", model.value)
var value = model.value
if (model.format==="smiles"){
- console.log("getting smiles")
value = jsmeElement.smiles()
- console.log("got smiles")
} else if (model.format==="mol"){
value = jsmeElement.molFile(false)
} else if (model.format==="mol3000"){
@@ -40,17 +30,13 @@ function setModelValue(model: JSMEEditor, jsmeElement: any){
value = jsmeElement.jmeFile()
}
if (model.value!==value && value!==null){
- console.log("setting value", value)
model.value = value
}
- console.log("setValue - end", model.value)
}
function setModelValues(model: JSMEEditor, jsmeElement: any){
- console.log("setValues - start")
setModelValue(model, jsmeElement)
- setOtherModelValues(model, jsmeElement)
- console.log("setValues - end")
+ setOtherModelValues(model, jsmeElement)
}
function resetOtherModelValues(model: JSMEEditor, jsmeElement: any){
@@ -72,13 +58,11 @@ function cleanValue(value: any){
}
function setOtherModelValues(model: JSMEEditor, jsmeElement: any){
- console.log("setOtherValues - start")
if (model.subscriptions.includes("jme")){model.jme = cleanValue(jsmeElement.jmeFile())}
if (model.subscriptions.includes("smiles")){model.smiles = cleanValue(jsmeElement.smiles())}
if (model.subscriptions.includes("mol")){model.mol = cleanValue(jsmeElement.molFile(false))}
if (model.subscriptions.includes("mol3000")){model.mol3000 = cleanValue(jsmeElement.molFile(true))}
if (model.subscriptions.includes("sdf")){model.sdf = cleanValue(readSDFValue(jsmeElement))}
- console.log("setOtherValues - end")
}
// The view of the Bokeh extension/ HTML element
@@ -89,12 +73,20 @@ export class JSMEEditorView extends HTMLBoxView {
JSME = (window as any).JSApplet.JSME
valueFunc: any
valueChanging: boolean = true
+ container: HTMLDivElement
+ _intialized: boolean = false
+
+ initialize(): void {
+ super.initialize()
+ this.container = div({
+ style: {display: "contents"}
+ })
+ }
connect_signals(): void {
super.connect_signals()
this.connect(this.model.properties.value.change, () => {
- console.log("value change", this.model.value)
if (!this.valueChanging){
if (this.model.value===""){
this.jsmeElement.reset()
@@ -104,29 +96,40 @@ export class JSMEEditorView extends HTMLBoxView {
}
})
this.connect(this.model.properties.format.change, () => {
- console.log("format change", this.model.format)
setModelValue(this.model, this.jsmeElement);
})
this.connect(this.model.properties.subscriptions.change, () => {
- console.log("subscriptions change", this.model.subscriptions)
resetOtherModelValues(this.model, this.jsmeElement);
})
this.connect(this.model.properties.options.change, () => {
- console.log("options change", this.model.options)
this.setJSMEOptions()
})
this.connect(this.model.properties.guicolor.change, () => {
- console.log("options change", this.model.options)
this.setGUIColor()
})
}
render(): void {
- console.log("render - start")
super.render()
const id = "jsme-" + uuidv4()
- const container = div({class: "jsme-editor", id: id});
- this.el.appendChild(container)
+ const el = div({
+ class: "jsme-editor",
+ id: id,
+ style: {width: "100%", height: "100%"}
+ })
+ this.container.appendChild(el)
+ this._intialized = false
+ }
+
+ createJSMEElement() {
+ if (this._intialized)
+ return
+
+ const id = this.container.children[0].id
+
+ // Need to add it to document body for JSME to be able to find the id
+ document.body.appendChild(this.container)
+
this.jsmeElement = new this.JSME(id, this.getHeight(), this.getWidth(), {
"options": this.model.options.join(","),
"guicolor": this.model.guicolor
@@ -136,25 +139,26 @@ export class JSMEEditorView extends HTMLBoxView {
setModelValues(this.model, this.jsmeElement)
const this_ = this;
- function showEvent(event: any){
- console.log("event", event)
+ function showEvent(_: any){
this_.valueChanging = true
setModelValues(this_.model, this_.jsmeElement)
this_.valueChanging = false
}
this.jsmeElement.setAfterStructureModifiedCallback(showEvent);
- console.log("render - end")
+ // Remove from document body and add to shadow DOM
+ document.body.removeChild(this.container)
+ this.shadow_el.appendChild(this.container)
+
+ this._intialized = true
}
setGUIColor(){
- console.log("setGUIColor", this.model.guicolor)
this.jsmeElement.setUserInterfaceBackgroundColor(this.model.guicolor)
}
setJSMEOptions(){
const options = this.model.options.join(",")
- console.log("setJSMEOptions", options)
this.jsmeElement.options(options)
}
@@ -185,6 +189,7 @@ export class JSMEEditorView extends HTMLBoxView {
after_layout(): void{
super.after_layout()
+ this.createJSMEElement()
this.resizeJSMEElement()
}
}
@@ -213,6 +218,7 @@ export interface JSMEEditor extends JSMEEditor.Attrs { }
// The Bokeh .ts model corresponding to the Bokeh .py model
export class JSMEEditor extends HTMLBox {
properties: JSMEEditor.Props
+ __view_type__: JSMEEditorView
constructor(attrs?: Partial) {
super(attrs)
@@ -220,7 +226,7 @@ export class JSMEEditor extends HTMLBox {
static __module__ = "panel_chemistry.bokeh_extensions.jsme_editor"
- static init_JSMEEditor(): void {
+ static {
this.prototype.default_view = JSMEEditorView;
this.define(({String, Array}) => ({
@@ -236,4 +242,4 @@ export class JSMEEditor extends HTMLBox {
guicolor: [String, "#c0c0c0"],
}))
}
-}
\ No newline at end of file
+}
diff --git a/src/panel_chemistry/bokeh_extensions/layout.ts b/src/panel_chemistry/bokeh_extensions/layout.ts
new file mode 100644
index 0000000..cda8b97
--- /dev/null
+++ b/src/panel_chemistry/bokeh_extensions/layout.ts
@@ -0,0 +1,104 @@
+import {isArray} from "@bokehjs/core/util/types"
+import {LayoutDOM, LayoutDOMView} from "@bokehjs/models/layouts/layout_dom"
+import * as p from "@bokehjs/core/properties"
+
+export function uuidv4() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+}
+
+export function set_size(el: HTMLElement, model: HTMLBox, adjustMargin: boolean = true): void {
+ let width_policy = model.width != null ? "fixed" : "fit"
+ let height_policy = model.height != null ? "fixed" : "fit"
+ const {sizing_mode, margin} = model
+ if (sizing_mode != null) {
+ if (sizing_mode == "fixed")
+ width_policy = height_policy = "fixed"
+ else if (sizing_mode == "stretch_both")
+ width_policy = height_policy = "max"
+ else if (sizing_mode == "stretch_width")
+ width_policy = "max"
+ else if (sizing_mode == "stretch_height")
+ height_policy = "max"
+ else {
+ switch (sizing_mode) {
+ case "scale_width":
+ width_policy = "max"
+ height_policy = "min"
+ break
+ case "scale_height":
+ width_policy = "min"
+ height_policy = "max"
+ break
+ case "scale_both":
+ width_policy = "max"
+ height_policy = "max"
+ break
+ default:
+ throw new Error("unreachable")
+ }
+ }
+ }
+ let wm: number, hm: number
+ if (!adjustMargin) {
+ hm = wm = 0
+ } else if (isArray(margin)) {
+ if (margin.length === 4) {
+ hm = margin[0] + margin[2]
+ wm = margin[1] + margin[3]
+ } else {
+ hm = margin[0] * 2
+ wm = margin[1] * 2
+ }
+ } else if (margin == null) {
+ hm = wm = 0
+ } else {
+ wm = hm = margin * 2
+ }
+ if (width_policy == "fixed" && model.width)
+ el.style.width = model.width + "px";
+ else if (width_policy == "max")
+ el.style.width = wm ? `calc(100% - ${wm}px)`: "100%";
+ if (model.min_width != null)
+ el.style.minWidth = model.min_width + "px";
+ if (model.max_width != null)
+ el.style.maxWidth = model.max_width + "px";
+ if (height_policy == "fixed" && model.height)
+ el.style.height = model.height + "px";
+ else if (height_policy == "max")
+ el.style.height = hm ? `calc(100% - ${hm}px)`: "100%";
+ if (model.min_height != null)
+ el.style.minHeight = model.min_height + "px";
+ if (model.max_width != null)
+ el.style.maxHeight = model.max_height + "px";
+ }
+
+ export abstract class HTMLBoxView extends LayoutDOMView {
+ override model: HTMLBox
+
+ render(): void {
+ super.render()
+ set_size(this.el, this.model)
+ }
+
+ get child_models(): LayoutDOM[] {
+ return []
+ }
+ }
+
+ export namespace HTMLBox {
+ export type Attrs = p.AttrsOf
+ export type Props = LayoutDOM.Props
+ }
+
+ export interface HTMLBox extends HTMLBox.Attrs {}
+
+ export abstract class HTMLBox extends LayoutDOM {
+ override properties: HTMLBox.Props
+
+ constructor(attrs?: Partial) {
+ super(attrs)
+ }
+ }
\ No newline at end of file
diff --git a/src/panel_chemistry/bokeh_extensions/ngl_viewer.py b/src/panel_chemistry/bokeh_extensions/ngl_viewer.py
index a40a2bd..940b228 100644
--- a/src/panel_chemistry/bokeh_extensions/ngl_viewer.py
+++ b/src/panel_chemistry/bokeh_extensions/ngl_viewer.py
@@ -3,19 +3,20 @@
from bokeh.models import LayoutDOM
-class NGLViewer(LayoutDOM):
+class NGLViewer(LayoutDOM): # pylint: disable=too-many-ancestors
"""The [NGL Viewer](https://github.com/nglviewer/ngl) can be used
to show and analyse pdb molecule structures"""
- object = String()
- extension = String()
- representation = String()
- color_scheme = String()
- effect = String()
+ object = String("")
+ extension = String("")
+ background_color = String("")
+ representation = String("ball+stick")
+ color_scheme = String("element")
custom_color_scheme = List(List(String))
+ effect = String("")
__javascript__ = [
- "https://unpkg.com/ngl@2.0.0-dev.37/dist/ngl.js",
+ "https://unpkg.com/ngl@2.2.1/dist/ngl.js",
]
__js_skip__ = {
@@ -24,7 +25,7 @@ class NGLViewer(LayoutDOM):
__js_require__ = {
"paths": {
- "NGL": "https://unpkg.com/ngl@2.0.0-dev.37/dist/ngl",
+ "NGL": "https://unpkg.com/ngl@2.2.1/dist/ngl",
},
"exports": {"NGL": "NGL"},
}
diff --git a/src/panel_chemistry/bokeh_extensions/ngl_viewer.ts b/src/panel_chemistry/bokeh_extensions/ngl_viewer.ts
index e69f961..826b8c3 100644
--- a/src/panel_chemistry/bokeh_extensions/ngl_viewer.ts
+++ b/src/panel_chemistry/bokeh_extensions/ngl_viewer.ts
@@ -1,5 +1,6 @@
import * as p from "@bokehjs/core/properties"
-import {HTMLBox, HTMLBoxView} from "@bokehjs/models/layouts/html_box"
+import {uuidv4, HTMLBox, HTMLBoxView} from "./layout"
+import {div} from "@bokehjs/core/dom"
declare namespace NGL {
class AtomProxy{
@@ -86,8 +87,19 @@ declare namespace NGL {
}
export class NGLViewerView extends HTMLBoxView {
model: NGLViewer
+ container: HTMLDivElement;
+ _intialized: boolean = false
_stage: any
+ initialize(): void {
+ super.initialize()
+ this.container = div({
+ class: "ngl-viewer",
+ id: "ngl-viewer-" + uuidv4(),
+ style: {width: "100%", height: "100%"}
+ })
+ }
+
connect_signals(): void {
super.connect_signals()
this.connect(this.model.properties.object.change, this.updateStage)
@@ -96,27 +108,39 @@ export class NGLViewerView extends HTMLBoxView {
this.connect(this.model.properties.color_scheme.change, this.updateParameters)
this.connect(this.model.properties.custom_color_scheme.change, this.updateParameters)
this.connect(this.model.properties.effect.change, this.updateEffect)
- this.connect(this.model.properties.background.change, this.setBackgroundcolor)
+ this.connect(this.model.properties.background_color.change, this.setBackgroundcolor)
}
render(): void {
super.render()
- this.el.id = "viewport"
+ this._intialized = false
+ this.createNGLViewer()
+ }
+ setBackgroundcolor(): void {
+ this._stage.setParameters( { backgroundColor: this.model.background_color} );
+ }
+ createNGLViewer(){
+ if (this._intialized)
+ return
+ document.body.appendChild(this.container)
+
const wn = (window as any)
const ngl = wn.NGL
-
- this._stage = new ngl.Stage(this.el);
+
+ this._stage = new ngl.Stage(this.container.id);
this.setBackgroundcolor()
const stage = this._stage
this.updateStage();
window.addEventListener( "resize", function(){
stage.handleResize();
}, false );
- }
- setBackgroundcolor(): void {
- console.log(this.model.background)
- this._stage.setParameters( { backgroundColor: this.model.background} );
+
+ // Remove from document body and add to shadow DOM
+ document.body.removeChild(this.container)
+ this.shadow_el.appendChild(this.container)
+
+ this._intialized = true
}
after_layout(): void {
super.after_layout()
@@ -177,6 +201,7 @@ export namespace NGLViewer {
export type Attrs = p.AttrsOf
export type Props = HTMLBox.Props & {
object: p.Property,
+ background_color: p.Property,
extension: p.Property,
representation: p.Property,
color_scheme: p.Property,
@@ -188,6 +213,7 @@ export namespace NGLViewer {
export interface NGLViewer extends NGLViewer.Attrs { }
export class NGLViewer extends HTMLBox {
properties: NGLViewer.Props
+ __view_type__: NGLViewerView
constructor(attrs?: Partial) {
super(attrs)
@@ -195,15 +221,16 @@ export class NGLViewer extends HTMLBox {
static __module__ = "panel_chemistry.bokeh_extensions.ngl_viewer"
- static init_NGLViewer(): void {
+ static {
this.prototype.default_view = NGLViewerView;
this.define(({ String, Any }) => ({
object: [ String, ""],
extension: [ String, ""],
- representation: [ String, "ribbon"],
- color_scheme: [ String, "chainid"],
- custom_color_scheme: [ Any, "chainid"],
+ background_color: [ String, ""],
+ representation: [ String, "ball+stick"],
+ color_scheme: [ String, "element"],
+ custom_color_scheme: [ Any, ["white", "*"]],
effect: [ String, ""],
}))
diff --git a/src/panel_chemistry/package-lock.json b/src/panel_chemistry/package-lock.json
index bdf256f..84e63b4 100644
--- a/src/panel_chemistry/package-lock.json
+++ b/src/panel_chemistry/package-lock.json
@@ -1,784 +1,25 @@
{
"name": "panel_chemistry",
- "version": "0.2.2",
- "lockfileVersion": 2,
+ "version": "0.3.0",
+ "lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "panel_chemistry",
- "version": "0.2.2",
+ "version": "0.3.0",
"license": "Apache 2.0",
"dependencies": {
- "@bokeh/bokehjs": "^2.4.3"
- }
- },
- "node_modules/@babel/runtime": {
- "version": "7.14.0",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
- "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
- "dependencies": {
- "regenerator-runtime": "^0.13.4"
+ "@bokeh/bokehjs": "~3.3.1"
}
},
"node_modules/@bokeh/bokehjs": {
- "version": "2.4.3",
- "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-2.4.3.tgz",
- "integrity": "sha512-zORGCM+3A2if+owfH03QFCL4GdnkhZizMlGjjGekAOp7Hc4TRqH9rQolEKKaNov7pmIay/VAMjZX4pyMXYW+Ag==",
- "dependencies": {
- "@bokeh/numbro": "^1.6.2",
- "@bokeh/slickgrid": "~2.4.2702",
- "choices.js": "^9.0.1",
- "es5-ext": "^0.10.53",
- "es6-map": "^0.1.5",
- "es6-promise": "4.2.8",
- "es6-set": "^0.1.5",
- "es6-symbol": "^3.1.3",
- "es6-weak-map": "^2.0.2",
- "flatbush": "^3.2.1",
- "flatpickr": "4.6.6",
- "hammerjs": "^2.0.4",
- "mathjax-full": "^3.2.0",
- "nouislider": "^15.4.0",
- "proj4": "^2.7.5",
- "regl": "^2.1.0",
- "sprintf-js": "^1.1.2",
- "timezone": "^1.0.23",
- "tslib": "^2.3.1",
- "underscore.template": "^0.1.7"
- },
- "engines": {
- "node": ">=14",
- "npm": ">=7.4"
- }
- },
- "node_modules/@bokeh/numbro": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/@bokeh/numbro/-/numbro-1.6.2.tgz",
- "integrity": "sha512-owIECPc3T3QXHCb2v5Ez+/uE9SIxI7N4nd9iFlWnfBrOelr0/omvFn09VisRn37AAFAY39sJiCVgECwryHWUPA==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-3.3.1.tgz",
+ "integrity": "sha512-orQM4d6MP1g7sXpG6B76HcwQLZIwVAMfopU6n7pZEB5430mINNH5VXlAWloBDveavcEpOwy+c0vBZLTYqOsgBg==",
"engines": {
- "node": "*"
- }
- },
- "node_modules/@bokeh/slickgrid": {
- "version": "2.4.2702",
- "resolved": "https://registry.npmjs.org/@bokeh/slickgrid/-/slickgrid-2.4.2702.tgz",
- "integrity": "sha512-W9tm8Qdw5BrylbZbaVWaQMgLfW/klesnj6J3FnyWpo18hCCOFApccUD8iOnRv7bF6PHlgWk84mW3JT5RSzYKjA==",
- "dependencies": {
- "@types/slickgrid": "^2.1.30",
- "jquery": ">=3.4.0",
- "jquery-ui": ">=1.8.0",
- "tslib": "^1.10.0"
+ "node": ">=16.0",
+ "npm": ">=8.0"
}
- },
- "node_modules/@bokeh/slickgrid/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@types/jquery": {
- "version": "3.5.5",
- "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.5.tgz",
- "integrity": "sha512-6RXU9Xzpc6vxNrS6FPPapN1SxSHgQ336WC6Jj/N8q30OiaBZ00l1GBgeP7usjVZPivSkGUfL1z/WW6TX989M+w==",
- "dependencies": {
- "@types/sizzle": "*"
- }
- },
- "node_modules/@types/sizzle": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
- "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ=="
- },
- "node_modules/@types/slickgrid": {
- "version": "2.1.30",
- "resolved": "https://registry.npmjs.org/@types/slickgrid/-/slickgrid-2.1.30.tgz",
- "integrity": "sha512-9nTqNWD3BtEVK0CP+G+mBtvSrKTfQy3Dg5/al+GdTSVMHFm37UxsHJ1eURwPg7rYu6vc7xU95fGTCKMZbxsD5w==",
- "dependencies": {
- "@types/jquery": "*"
- }
- },
- "node_modules/choices.js": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/choices.js/-/choices.js-9.0.1.tgz",
- "integrity": "sha512-JgpeDY0Tmg7tqY6jaW/druSklJSt7W68tXFJIw0GSGWmO37SDAL8o60eICNGbzIODjj02VNNtf5h6TgoHDtCsA==",
- "dependencies": {
- "deepmerge": "^4.2.0",
- "fuse.js": "^3.4.5",
- "redux": "^4.0.4"
- }
- },
- "node_modules/commander": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
- "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/d": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
- "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
- "dependencies": {
- "es5-ext": "^0.10.50",
- "type": "^1.0.1"
- }
- },
- "node_modules/deepmerge": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
- "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/es5-ext": {
- "version": "0.10.53",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
- "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
- "dependencies": {
- "es6-iterator": "~2.0.3",
- "es6-symbol": "~3.1.3",
- "next-tick": "~1.0.0"
- }
- },
- "node_modules/es6-iterator": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
- "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
- "dependencies": {
- "d": "1",
- "es5-ext": "^0.10.35",
- "es6-symbol": "^3.1.1"
- }
- },
- "node_modules/es6-map": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
- "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
- "dependencies": {
- "d": "1",
- "es5-ext": "~0.10.14",
- "es6-iterator": "~2.0.1",
- "es6-set": "~0.1.5",
- "es6-symbol": "~3.1.1",
- "event-emitter": "~0.3.5"
- }
- },
- "node_modules/es6-promise": {
- "version": "4.2.8",
- "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
- "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
- },
- "node_modules/es6-set": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
- "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
- "dependencies": {
- "d": "1",
- "es5-ext": "~0.10.14",
- "es6-iterator": "~2.0.1",
- "es6-symbol": "3.1.1",
- "event-emitter": "~0.3.5"
- }
- },
- "node_modules/es6-set/node_modules/es6-symbol": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
- "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
- "dependencies": {
- "d": "1",
- "es5-ext": "~0.10.14"
- }
- },
- "node_modules/es6-symbol": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
- "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
- "dependencies": {
- "d": "^1.0.1",
- "ext": "^1.1.2"
- }
- },
- "node_modules/es6-weak-map": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
- "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
- "dependencies": {
- "d": "1",
- "es5-ext": "^0.10.46",
- "es6-iterator": "^2.0.3",
- "es6-symbol": "^3.1.1"
- }
- },
- "node_modules/esm": {
- "version": "3.2.25",
- "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
- "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/event-emitter": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
- "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
- "dependencies": {
- "d": "1",
- "es5-ext": "~0.10.14"
- }
- },
- "node_modules/ext": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
- "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
- "dependencies": {
- "type": "^2.0.0"
- }
- },
- "node_modules/ext/node_modules/type": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz",
- "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw=="
- },
- "node_modules/flatbush": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/flatbush/-/flatbush-3.3.0.tgz",
- "integrity": "sha512-F3EzQvKpdmXUbFwWxLKBpytOFEGYQMCTBLuqZ4GEajFOEAvnOIBiyxW3OFSZXIOtpCS8teN6bFEpNZtnVXuDQA==",
- "dependencies": {
- "flatqueue": "^1.2.0"
- }
- },
- "node_modules/flatpickr": {
- "version": "4.6.6",
- "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.6.tgz",
- "integrity": "sha512-EZ48CJMttMg3maMhJoX+GvTuuEhX/RbA1YeuI19attP3pwBdbYy6+yqAEVm0o0hSBFYBiLbVxscLW6gJXq6H3A=="
- },
- "node_modules/flatqueue": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/flatqueue/-/flatqueue-1.2.1.tgz",
- "integrity": "sha512-X86TpWS1rGuY7m382HuA9vngLeDuWA9lJvhEG+GfgKMV5onSvx5a71cl7GMbXzhWtlN9dGfqOBrpfqeOtUfGYQ=="
- },
- "node_modules/fuse.js": {
- "version": "3.6.1",
- "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.6.1.tgz",
- "integrity": "sha512-hT9yh/tiinkmirKrlv4KWOjztdoZo1mx9Qh4KvWqC7isoXwdUY3PNWUxceF4/qO9R6riA2C29jdTOeQOIROjgw==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/hammerjs": {
- "version": "2.0.8",
- "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
- "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=",
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/jquery": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
- "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
- },
- "node_modules/jquery-ui": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.2.tgz",
- "integrity": "sha512-wBZPnqWs5GaYJmo1Jj0k/mrSkzdQzKDwhXNtHKcBdAcKVxMM3KNYFq+iJ2i1rwiG53Z8M4mTn3Qxrm17uH1D4Q==",
- "dependencies": {
- "jquery": ">=1.8.0 <4.0.0"
- }
- },
- "node_modules/mathjax-full": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.0.tgz",
- "integrity": "sha512-D2EBNvUG+mJyhn+M1C858k0f2Fc4KxXvbEX2WCMXroV10212JwfYqaBJ336ECBSz5X9L5LRoamxb7AJtg3KaJA==",
- "dependencies": {
- "esm": "^3.2.25",
- "mhchemparser": "^4.1.0",
- "mj-context-menu": "^0.6.1",
- "speech-rule-engine": "^3.3.3"
- }
- },
- "node_modules/mgrs": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz",
- "integrity": "sha1-+5FYjnjJACVnI5XLQLJffNatGCk="
- },
- "node_modules/mhchemparser": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.1.1.tgz",
- "integrity": "sha512-R75CUN6O6e1t8bgailrF1qPq+HhVeFTM3XQ0uzI+mXTybmphy3b6h4NbLOYhemViQ3lUs+6CKRkC3Ws1TlYREA=="
- },
- "node_modules/mj-context-menu": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
- "integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA=="
- },
- "node_modules/next-tick": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
- "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
- },
- "node_modules/nouislider": {
- "version": "15.5.0",
- "resolved": "https://registry.npmjs.org/nouislider/-/nouislider-15.5.0.tgz",
- "integrity": "sha512-p0Rn0a4XzrBJ+JZRhNDYpRYr6sDPkajsjbvEQoTp/AZlNI3NirO15s1t11D25Gk3zVyvNJAzc1DO48cq/KX5Sw=="
- },
- "node_modules/proj4": {
- "version": "2.7.5",
- "resolved": "https://registry.npmjs.org/proj4/-/proj4-2.7.5.tgz",
- "integrity": "sha512-5ecXUXbHAfvdhfBQpU7EhUfPCQGUCPmVup/4gnZA3bJY3JcK/xxzm4QQDz1xiXokN6ux65VDczlCtBtKrTSpAQ==",
- "dependencies": {
- "mgrs": "1.0.0",
- "wkt-parser": "^1.3.1"
- }
- },
- "node_modules/redux": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz",
- "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==",
- "dependencies": {
- "@babel/runtime": "^7.9.2"
- }
- },
- "node_modules/regenerator-runtime": {
- "version": "0.13.7",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
- "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
- },
- "node_modules/regl": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/regl/-/regl-2.1.0.tgz",
- "integrity": "sha512-oWUce/aVoEvW5l2V0LK7O5KJMzUSKeiOwFuJehzpSFd43dO5spP9r+sSUfhKtsky4u6MCqWJaRL+abzExynfTg=="
- },
- "node_modules/speech-rule-engine": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/speech-rule-engine/-/speech-rule-engine-3.3.3.tgz",
- "integrity": "sha512-0exWw+0XauLjat+f/aFeo5T8SiDsO1JtwpY3qgJE4cWt+yL/Stl0WP4VNDWdh7lzGkubUD9lWP4J1ASnORXfyQ==",
- "dependencies": {
- "commander": ">=7.0.0",
- "wicked-good-xpath": "^1.3.0",
- "xmldom-sre": "^0.1.31"
- },
- "bin": {
- "sre": "bin/sre"
- }
- },
- "node_modules/sprintf-js": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
- "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
- },
- "node_modules/timezone": {
- "version": "1.0.23",
- "resolved": "https://registry.npmjs.org/timezone/-/timezone-1.0.23.tgz",
- "integrity": "sha512-yhQgk6qmSLB+TF8HGmApZAVI5bfzR1CoKUGr+WMZWmx75ED1uDewAZA8QMGCQ70TEv4GmM8pDB9jrHuxdaQ1PA=="
- },
- "node_modules/tslib": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
- },
- "node_modules/type": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
- "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
- },
- "node_modules/underscore.template": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/underscore.template/-/underscore.template-0.1.7.tgz",
- "integrity": "sha1-MBPg6hgXVjBvFgnpWcr7xyKts+k="
- },
- "node_modules/wicked-good-xpath": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz",
- "integrity": "sha1-gbDpXoZQ5JyUsiKY//hoa1VTz2w="
- },
- "node_modules/wkt-parser": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.3.1.tgz",
- "integrity": "sha512-XK5qV+Y5gsygQfHx2/cS5a7Zxsgleaw8iX5UPC5eOXPc0TgJAu1JB9lr0iYYX3zAnN3p0aNiaN5c+1Bdblxwrg=="
- },
- "node_modules/xmldom-sre": {
- "version": "0.1.31",
- "resolved": "https://registry.npmjs.org/xmldom-sre/-/xmldom-sre-0.1.31.tgz",
- "integrity": "sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw==",
- "engines": {
- "node": ">=0.1"
- }
- }
- },
- "dependencies": {
- "@babel/runtime": {
- "version": "7.14.0",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
- "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
- "requires": {
- "regenerator-runtime": "^0.13.4"
- }
- },
- "@bokeh/bokehjs": {
- "version": "2.4.3",
- "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-2.4.3.tgz",
- "integrity": "sha512-zORGCM+3A2if+owfH03QFCL4GdnkhZizMlGjjGekAOp7Hc4TRqH9rQolEKKaNov7pmIay/VAMjZX4pyMXYW+Ag==",
- "requires": {
- "@bokeh/numbro": "^1.6.2",
- "@bokeh/slickgrid": "~2.4.2702",
- "choices.js": "^9.0.1",
- "es5-ext": "^0.10.53",
- "es6-map": "^0.1.5",
- "es6-promise": "4.2.8",
- "es6-set": "^0.1.5",
- "es6-symbol": "^3.1.3",
- "es6-weak-map": "^2.0.2",
- "flatbush": "^3.2.1",
- "flatpickr": "4.6.6",
- "hammerjs": "^2.0.4",
- "mathjax-full": "^3.2.0",
- "nouislider": "^15.4.0",
- "proj4": "^2.7.5",
- "regl": "^2.1.0",
- "sprintf-js": "^1.1.2",
- "timezone": "^1.0.23",
- "tslib": "^2.3.1",
- "underscore.template": "^0.1.7"
- }
- },
- "@bokeh/numbro": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/@bokeh/numbro/-/numbro-1.6.2.tgz",
- "integrity": "sha512-owIECPc3T3QXHCb2v5Ez+/uE9SIxI7N4nd9iFlWnfBrOelr0/omvFn09VisRn37AAFAY39sJiCVgECwryHWUPA=="
- },
- "@bokeh/slickgrid": {
- "version": "2.4.2702",
- "resolved": "https://registry.npmjs.org/@bokeh/slickgrid/-/slickgrid-2.4.2702.tgz",
- "integrity": "sha512-W9tm8Qdw5BrylbZbaVWaQMgLfW/klesnj6J3FnyWpo18hCCOFApccUD8iOnRv7bF6PHlgWk84mW3JT5RSzYKjA==",
- "requires": {
- "@types/slickgrid": "^2.1.30",
- "jquery": ">=3.4.0",
- "jquery-ui": ">=1.8.0",
- "tslib": "^1.10.0"
- },
- "dependencies": {
- "tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- }
- }
- },
- "@types/jquery": {
- "version": "3.5.5",
- "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.5.tgz",
- "integrity": "sha512-6RXU9Xzpc6vxNrS6FPPapN1SxSHgQ336WC6Jj/N8q30OiaBZ00l1GBgeP7usjVZPivSkGUfL1z/WW6TX989M+w==",
- "requires": {
- "@types/sizzle": "*"
- }
- },
- "@types/sizzle": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
- "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ=="
- },
- "@types/slickgrid": {
- "version": "2.1.30",
- "resolved": "https://registry.npmjs.org/@types/slickgrid/-/slickgrid-2.1.30.tgz",
- "integrity": "sha512-9nTqNWD3BtEVK0CP+G+mBtvSrKTfQy3Dg5/al+GdTSVMHFm37UxsHJ1eURwPg7rYu6vc7xU95fGTCKMZbxsD5w==",
- "requires": {
- "@types/jquery": "*"
- }
- },
- "choices.js": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/choices.js/-/choices.js-9.0.1.tgz",
- "integrity": "sha512-JgpeDY0Tmg7tqY6jaW/druSklJSt7W68tXFJIw0GSGWmO37SDAL8o60eICNGbzIODjj02VNNtf5h6TgoHDtCsA==",
- "requires": {
- "deepmerge": "^4.2.0",
- "fuse.js": "^3.4.5",
- "redux": "^4.0.4"
- }
- },
- "commander": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
- "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
- },
- "d": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
- "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
- "requires": {
- "es5-ext": "^0.10.50",
- "type": "^1.0.1"
- }
- },
- "deepmerge": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
- "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
- },
- "es5-ext": {
- "version": "0.10.53",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
- "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
- "requires": {
- "es6-iterator": "~2.0.3",
- "es6-symbol": "~3.1.3",
- "next-tick": "~1.0.0"
- }
- },
- "es6-iterator": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
- "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
- "requires": {
- "d": "1",
- "es5-ext": "^0.10.35",
- "es6-symbol": "^3.1.1"
- }
- },
- "es6-map": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
- "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
- "requires": {
- "d": "1",
- "es5-ext": "~0.10.14",
- "es6-iterator": "~2.0.1",
- "es6-set": "~0.1.5",
- "es6-symbol": "~3.1.1",
- "event-emitter": "~0.3.5"
- }
- },
- "es6-promise": {
- "version": "4.2.8",
- "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
- "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
- },
- "es6-set": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
- "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
- "requires": {
- "d": "1",
- "es5-ext": "~0.10.14",
- "es6-iterator": "~2.0.1",
- "es6-symbol": "3.1.1",
- "event-emitter": "~0.3.5"
- },
- "dependencies": {
- "es6-symbol": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
- "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
- "requires": {
- "d": "1",
- "es5-ext": "~0.10.14"
- }
- }
- }
- },
- "es6-symbol": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
- "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
- "requires": {
- "d": "^1.0.1",
- "ext": "^1.1.2"
- }
- },
- "es6-weak-map": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
- "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
- "requires": {
- "d": "1",
- "es5-ext": "^0.10.46",
- "es6-iterator": "^2.0.3",
- "es6-symbol": "^3.1.1"
- }
- },
- "esm": {
- "version": "3.2.25",
- "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
- "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="
- },
- "event-emitter": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
- "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
- "requires": {
- "d": "1",
- "es5-ext": "~0.10.14"
- }
- },
- "ext": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
- "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
- "requires": {
- "type": "^2.0.0"
- },
- "dependencies": {
- "type": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz",
- "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw=="
- }
- }
- },
- "flatbush": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/flatbush/-/flatbush-3.3.0.tgz",
- "integrity": "sha512-F3EzQvKpdmXUbFwWxLKBpytOFEGYQMCTBLuqZ4GEajFOEAvnOIBiyxW3OFSZXIOtpCS8teN6bFEpNZtnVXuDQA==",
- "requires": {
- "flatqueue": "^1.2.0"
- }
- },
- "flatpickr": {
- "version": "4.6.6",
- "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.6.tgz",
- "integrity": "sha512-EZ48CJMttMg3maMhJoX+GvTuuEhX/RbA1YeuI19attP3pwBdbYy6+yqAEVm0o0hSBFYBiLbVxscLW6gJXq6H3A=="
- },
- "flatqueue": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/flatqueue/-/flatqueue-1.2.1.tgz",
- "integrity": "sha512-X86TpWS1rGuY7m382HuA9vngLeDuWA9lJvhEG+GfgKMV5onSvx5a71cl7GMbXzhWtlN9dGfqOBrpfqeOtUfGYQ=="
- },
- "fuse.js": {
- "version": "3.6.1",
- "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.6.1.tgz",
- "integrity": "sha512-hT9yh/tiinkmirKrlv4KWOjztdoZo1mx9Qh4KvWqC7isoXwdUY3PNWUxceF4/qO9R6riA2C29jdTOeQOIROjgw=="
- },
- "hammerjs": {
- "version": "2.0.8",
- "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
- "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
- },
- "jquery": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
- "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
- },
- "jquery-ui": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.2.tgz",
- "integrity": "sha512-wBZPnqWs5GaYJmo1Jj0k/mrSkzdQzKDwhXNtHKcBdAcKVxMM3KNYFq+iJ2i1rwiG53Z8M4mTn3Qxrm17uH1D4Q==",
- "requires": {
- "jquery": ">=1.8.0 <4.0.0"
- }
- },
- "mathjax-full": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.0.tgz",
- "integrity": "sha512-D2EBNvUG+mJyhn+M1C858k0f2Fc4KxXvbEX2WCMXroV10212JwfYqaBJ336ECBSz5X9L5LRoamxb7AJtg3KaJA==",
- "requires": {
- "esm": "^3.2.25",
- "mhchemparser": "^4.1.0",
- "mj-context-menu": "^0.6.1",
- "speech-rule-engine": "^3.3.3"
- }
- },
- "mgrs": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz",
- "integrity": "sha1-+5FYjnjJACVnI5XLQLJffNatGCk="
- },
- "mhchemparser": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.1.1.tgz",
- "integrity": "sha512-R75CUN6O6e1t8bgailrF1qPq+HhVeFTM3XQ0uzI+mXTybmphy3b6h4NbLOYhemViQ3lUs+6CKRkC3Ws1TlYREA=="
- },
- "mj-context-menu": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
- "integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA=="
- },
- "next-tick": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
- "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
- },
- "nouislider": {
- "version": "15.5.0",
- "resolved": "https://registry.npmjs.org/nouislider/-/nouislider-15.5.0.tgz",
- "integrity": "sha512-p0Rn0a4XzrBJ+JZRhNDYpRYr6sDPkajsjbvEQoTp/AZlNI3NirO15s1t11D25Gk3zVyvNJAzc1DO48cq/KX5Sw=="
- },
- "proj4": {
- "version": "2.7.5",
- "resolved": "https://registry.npmjs.org/proj4/-/proj4-2.7.5.tgz",
- "integrity": "sha512-5ecXUXbHAfvdhfBQpU7EhUfPCQGUCPmVup/4gnZA3bJY3JcK/xxzm4QQDz1xiXokN6ux65VDczlCtBtKrTSpAQ==",
- "requires": {
- "mgrs": "1.0.0",
- "wkt-parser": "^1.3.1"
- }
- },
- "redux": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz",
- "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==",
- "requires": {
- "@babel/runtime": "^7.9.2"
- }
- },
- "regenerator-runtime": {
- "version": "0.13.7",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
- "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
- },
- "regl": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/regl/-/regl-2.1.0.tgz",
- "integrity": "sha512-oWUce/aVoEvW5l2V0LK7O5KJMzUSKeiOwFuJehzpSFd43dO5spP9r+sSUfhKtsky4u6MCqWJaRL+abzExynfTg=="
- },
- "speech-rule-engine": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/speech-rule-engine/-/speech-rule-engine-3.3.3.tgz",
- "integrity": "sha512-0exWw+0XauLjat+f/aFeo5T8SiDsO1JtwpY3qgJE4cWt+yL/Stl0WP4VNDWdh7lzGkubUD9lWP4J1ASnORXfyQ==",
- "requires": {
- "commander": ">=7.0.0",
- "wicked-good-xpath": "^1.3.0",
- "xmldom-sre": "^0.1.31"
- }
- },
- "sprintf-js": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
- "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
- },
- "timezone": {
- "version": "1.0.23",
- "resolved": "https://registry.npmjs.org/timezone/-/timezone-1.0.23.tgz",
- "integrity": "sha512-yhQgk6qmSLB+TF8HGmApZAVI5bfzR1CoKUGr+WMZWmx75ED1uDewAZA8QMGCQ70TEv4GmM8pDB9jrHuxdaQ1PA=="
- },
- "tslib": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
- },
- "type": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
- "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
- },
- "underscore.template": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/underscore.template/-/underscore.template-0.1.7.tgz",
- "integrity": "sha1-MBPg6hgXVjBvFgnpWcr7xyKts+k="
- },
- "wicked-good-xpath": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz",
- "integrity": "sha1-gbDpXoZQ5JyUsiKY//hoa1VTz2w="
- },
- "wkt-parser": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.3.1.tgz",
- "integrity": "sha512-XK5qV+Y5gsygQfHx2/cS5a7Zxsgleaw8iX5UPC5eOXPc0TgJAu1JB9lr0iYYX3zAnN3p0aNiaN5c+1Bdblxwrg=="
- },
- "xmldom-sre": {
- "version": "0.1.31",
- "resolved": "https://registry.npmjs.org/xmldom-sre/-/xmldom-sre-0.1.31.tgz",
- "integrity": "sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw=="
}
}
}
diff --git a/src/panel_chemistry/package.json b/src/panel_chemistry/package.json
index 7c42cae..e9d0a3e 100644
--- a/src/panel_chemistry/package.json
+++ b/src/panel_chemistry/package.json
@@ -1,10 +1,10 @@
{
"name": "panel_chemistry",
- "version": "0.2.2",
+ "version": "0.3.0",
"description": "Panel extension for data analysis and data apps within the domain of Chemistry",
"license": "Apache 2.0",
"keywords": [],
"dependencies": {
- "@bokeh/bokehjs": "^2.4.3"
+ "@bokeh/bokehjs": "~3.3.1"
}
}
diff --git a/src/panel_chemistry/pane/ngl_viewer.py b/src/panel_chemistry/pane/ngl_viewer.py
index 383e0ec..7ab361c 100644
--- a/src/panel_chemistry/pane/ngl_viewer.py
+++ b/src/panel_chemistry/pane/ngl_viewer.py
@@ -8,8 +8,6 @@
"""
-from typing import Dict
-
import param
from panel import extension
from panel.pane.base import PaneBase
@@ -98,10 +96,15 @@ class NGLViewer(PaneBase): # pylint: disable=too-many-ancestors
to show and analyse pdb molecule structures"""
object = param.String(
+ default="",
doc="""
The object to display. For example an url like 'rcsb://3dqb.pdb', 'rcsb://1NKT', '1NKT'.
You can also specify a extension string if you define the extension
- in the extension parameter"""
+ in the extension parameter""",
+ )
+ background_color = param.Color(
+ doc="""
+ A custom background color"""
)
extension = param.ObjectSelector(
default="",
@@ -161,15 +164,6 @@ def _get_model(self, doc, root=None, parent=None, comm=None):
props["object"] = self.object
model = _NGLViewer(**props)
root = root or model
- # self._link_props(
- # model,
- # [
- # "event",
- # ],
- # doc,
- # root,
- # comm,
- # )
self._models[root.ref["id"]] = (model, parent)
return model
diff --git a/src/panel_chemistry/pane/pdbe_molstar.py b/src/panel_chemistry/pane/pdbe_molstar.py
index ce84a3d..c8d18c4 100644
--- a/src/panel_chemistry/pane/pdbe_molstar.py
+++ b/src/panel_chemistry/pane/pdbe_molstar.py
@@ -29,6 +29,7 @@
"spacefill",
]
+
# See https://embed.plnkr.co/plunk/m3GxFYx9cBjIanBp for an example JS implementation
class PDBeMolStar(ReactiveHTML): # pylint: disable=too-many-ancestors
"""PDBe MolStar structure viewer.
@@ -127,10 +128,10 @@ class PDBeMolStar(ReactiveHTML): # pylint: disable=too-many-ancestors
)
hide_controls = param.Boolean(default=True, doc="Hide the control menu")
-
+
sequence_panel = param.Boolean(
- default=True,
- doc="Show the sequence panel. Currently shown only when the controls are toggled"
+ default=True,
+ doc="Show the sequence panel. Currently shown only when the controls are toggled",
)
expanded = param.Boolean(default=False, doc="""Display full-screen by default on load""")
diff --git a/src/panel_chemistry/pane/py3dmol_viewer.py b/src/panel_chemistry/pane/py3dmol_viewer.py
index 9ad7657..d01d3b7 100644
--- a/src/panel_chemistry/pane/py3dmol_viewer.py
+++ b/src/panel_chemistry/pane/py3dmol_viewer.py
@@ -12,7 +12,7 @@
try:
import py3Dmol
except ModuleNotFoundError:
- # pylint: disable=invalid-name
+ # pylint: disable=invalid-name, too-few-public-methods
class py3Dmol(param.Parameterized): # type: ignore
"""Dummy py3Dmol class"""
diff --git a/src/panel_chemistry/tsconfig.json b/src/panel_chemistry/tsconfig.json
index 41720fb..6b4e52d 100644
--- a/src/panel_chemistry/tsconfig.json
+++ b/src/panel_chemistry/tsconfig.json
@@ -33,4 +33,4 @@
}
},
"include": ["./**/*.ts"]
-}
\ No newline at end of file
+}
diff --git a/src/panel_chemistry/widgets/jsme_editor.py b/src/panel_chemistry/widgets/jsme_editor.py
index fdece4f..d862b03 100644
--- a/src/panel_chemistry/widgets/jsme_editor.py
+++ b/src/panel_chemistry/widgets/jsme_editor.py
@@ -3,6 +3,10 @@
It is a wrapper of the free javascript JSME Molecule Editor. See https://jsme-editor.github.io/
"""
+from __future__ import annotations
+
+from typing import ClassVar, Mapping
+
import param
from panel.widgets.base import Widget
@@ -67,11 +71,7 @@ class JSMEEditor(Widget): # pylint: disable=too-many-ancestors
# Set the Bokeh model to use
_widget_type = _BkJSMEEditor
- # Rename Panel Parameters -> Bokeh Model properties
- # Parameters like title that does not exist on the Bokeh model should be renamed to None
- _rename = {
- "title": None,
- }
+ _rename: ClassVar[Mapping[str, str | None]] = {"name": None}
# Parameters to be mapped to Bokeh model properties
value = param.String(
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..d681a1c
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,16 @@
+"""Shared fixtures"""
+import pytest
+from bokeh.document import Document
+from pyviz_comms import Comm
+
+
+@pytest.fixture
+def document():
+ """A Bokeh Document"""
+ return Document()
+
+
+@pytest.fixture
+def comm():
+ """The pyviz communications"""
+ return Comm()
diff --git a/tests/pane/test_ngl_viewer.py b/tests/pane/test_ngl_viewer.py
index 2c17c63..f26db6c 100644
--- a/tests/pane/test_ngl_viewer.py
+++ b/tests/pane/test_ngl_viewer.py
@@ -5,21 +5,23 @@
from panel_chemistry.pane import NGLViewer
-def test_can_create():
+def test_can_create(document, comm):
"""Test of the NGLViewer constructor"""
- NGLViewer(object="1CRN", background="yellow", height=500)
+ viewer = NGLViewer(object="1CRN", background_color="yellow", height=500)
+ pane = viewer.get_root(document, comm=comm)
+ assert isinstance(pane, _BkNGLViewer)
def test_has_bokeh_model():
"""Test that the NGL Viewer Exists"""
- assert _BkNGLViewer
+ assert _BkNGLViewer.__name__
-def test_app():
+def _create_app():
"""Returns an app for manually testing the NGL Molecule Viewer"""
pn.extension(sizing_mode="stretch_width")
# 1NKT, 2GQ5, 3UOG and 5TXH
- viewer = NGLViewer(object="1CRN", background="yellow", height=500)
+ viewer = NGLViewer(object="1CRN", background_color="yellow", height=500)
parameters = [
"object",
"extension",
@@ -30,7 +32,7 @@ def test_app():
"sizing_mode",
"width",
"height",
- "background",
+ "background_color",
]
settings = pn.Param(
viewer,
@@ -46,5 +48,10 @@ def test_app():
)
+def test_app():
+ """Can create test app"""
+ assert _create_app()
+
+
if __name__.startswith("bokeh"):
- test_app().servable()
+ _create_app().servable()
diff --git a/tests/pane/test_pdbe_molstar_viewer.py b/tests/pane/test_pdbe_molstar_viewer.py
index 6766e75..998f520 100644
--- a/tests/pane/test_pdbe_molstar_viewer.py
+++ b/tests/pane/test_pdbe_molstar_viewer.py
@@ -4,9 +4,11 @@
from panel_chemistry.pane import PDBeMolStar
-def test_can_create():
+def test_can_create(document, comm):
"""Test of the PDBeMolStar constructor"""
- PDBeMolStar(molecule_id="1qyn", lighting="metallic", height=300, width=300)
+ molstar = PDBeMolStar(molecule_id="1qyn", lighting="metallic", height=300, width=300)
+ widget = molstar.get_root(document, comm=comm)
+ assert widget
def test_functions():
@@ -49,7 +51,7 @@ def test_functions():
viewer.reset(data)
-def test_app():
+def _create_app():
"""Returns an app for manually testing the PDBe Mol* Viewer"""
pn.extension(sizing_mode="stretch_width")
# 1NKT, 2GQ5, 3UOG and 5TXH
@@ -102,5 +104,10 @@ def test_app():
return pn.Row(pn.WidgetBox(settings, width=300, sizing_mode="fixed"), viewer)
+def test_app():
+ """Can create test app"""
+ assert _create_app()
+
+
if __name__.startswith("bokeh"):
- test_app().servable()
+ _create_app().servable()
diff --git a/tests/tests/test_jsme_editor.py b/tests/tests/test_jsme_editor.py
index 13b5e1c..2b203a8 100644
--- a/tests/tests/test_jsme_editor.py
+++ b/tests/tests/test_jsme_editor.py
@@ -5,11 +5,13 @@
from panel_chemistry.widgets import JSMEEditor
-def test_can_construct():
- JSMEEditor()
+def test_can_construct(document, comm):
+ editor = JSMEEditor()
+ widget = editor.get_root(document, comm=comm)
+ assert isinstance(widget, editor._widget_type) # pylint: disable=protected-access
-def test_jsme_editor_app():
+def _create_app():
pn.extension("jsme", sizing_mode="stretch_width")
smiles = "N[C@@H](CCC(=O)N[C@@H](CS)C(=O)NCC(=O)O)C(=O)O"
editor = JSMEEditor(value=smiles, height=500)
@@ -49,5 +51,9 @@ def test_jsme_editor_app():
)
+def test_app():
+ assert _create_app()
+
+
if __name__.startswith("bokeh"):
- test_jsme_editor_app().servable()
+ _create_app().servable()