Spaces:
Running
Running
Commit
Β·
e01fd27
1
Parent(s):
be34ea2
Upload 4 files
Browse files
README.md
CHANGED
@@ -1,11 +1,23 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: static
|
7 |
pinned: false
|
8 |
license: mit
|
9 |
---
|
10 |
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
---
|
2 |
+
title: Bootstrap Dashboard
|
3 |
+
emoji: π
|
4 |
+
colorFrom: indigo
|
5 |
+
colorTo: pink
|
6 |
sdk: static
|
7 |
pinned: false
|
8 |
license: mit
|
9 |
---
|
10 |
|
11 |
+
See [bootstrap_dashboard](https://awesome-panel.org/resources/bootstrap_dashboard/) by [awesome-panel.org](https://awesome-panel.org) for more info.
|
12 |
+
|
13 |
+
## Serve
|
14 |
+
|
15 |
+
```python
|
16 |
+
panel serve index.py --autoreload
|
17 |
+
```
|
18 |
+
|
19 |
+
## Convert to Pyodide
|
20 |
+
|
21 |
+
```bash
|
22 |
+
panel convert index.py --to pyodide-worker
|
23 |
+
```
|
index.html
CHANGED
@@ -1,19 +1,197 @@
|
|
1 |
<!DOCTYPE html>
|
2 |
-
<html>
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="utf-8">
|
5 |
+
<title>Panel Application</title>
|
6 |
+
<style>
|
7 |
+
html, body {
|
8 |
+
box-sizing: border-box;
|
9 |
+
display: flow-root;
|
10 |
+
height: 100%;
|
11 |
+
margin: 0;
|
12 |
+
padding: 0;
|
13 |
+
}
|
14 |
+
</style>
|
15 |
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" type="text/css" />
|
16 |
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" type="text/css" />
|
17 |
+
|
18 |
+
<style type="text/css">
|
19 |
+
:host(.pn-loading),
|
20 |
+
.pn-loading {
|
21 |
+
overflow: hidden;
|
22 |
+
}
|
23 |
+
|
24 |
+
:host(.pn-loading):before,
|
25 |
+
.pn-loading:before {
|
26 |
+
position: absolute;
|
27 |
+
height: 100%;
|
28 |
+
width: 100%;
|
29 |
+
content: '';
|
30 |
+
z-index: 1000;
|
31 |
+
background-color: rgb(255, 255, 255, 0.5);
|
32 |
+
border-color: lightgray;
|
33 |
+
background-repeat: no-repeat;
|
34 |
+
background-position: center;
|
35 |
+
background-size: auto 50%;
|
36 |
+
border-width: 1px;
|
37 |
+
cursor: progress;
|
38 |
+
}
|
39 |
+
|
40 |
+
:host(.pn-loading) .pn-loading-msg,
|
41 |
+
.pn-loading .pn-loading-msg {
|
42 |
+
position: absolute;
|
43 |
+
top: 72%;
|
44 |
+
font-size: 2em;
|
45 |
+
color: black;
|
46 |
+
width: 100%;
|
47 |
+
text-align: center;
|
48 |
+
}
|
49 |
+
|
50 |
+
|
51 |
+
:host(.pn-loading.pn-arc):before, .pn-loading.pn-arc:before {
|
52 |
+
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IG5vbmU7IGRpc3BsYXk6IGJsb2NrOyBzaGFwZS1yZW5kZXJpbmc6IGF1dG87IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiPiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzNjM2MzIiBzdHJva2Utd2lkdGg9IjEwIiByPSIzNSIgc3Ryb2tlLWRhc2hhcnJheT0iMTY0LjkzMzYxNDMxMzQ2NDE1IDU2Ljk3Nzg3MTQzNzgyMTM4Ij4gICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJyb3RhdGUiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjFzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIj48L2FuaW1hdGVUcmFuc2Zvcm0+ICA8L2NpcmNsZT48L3N2Zz4=");
|
53 |
+
background-size: auto calc(min(50%, 400px));
|
54 |
+
}
|
55 |
+
</style><script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-3.3.2.min.js"></script>
|
56 |
+
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.3.2.min.js"></script>
|
57 |
+
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.3.2.min.js"></script>
|
58 |
+
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.3.2.min.js"></script>
|
59 |
+
<script type="text/javascript" src="https://cdn.holoviz.org/panel/1.3.6/dist/bundled/[email protected]/dist/material-components-web.min.js"></script>
|
60 |
+
<script type="text/javascript" src="https://cdn.holoviz.org/panel/1.3.6/dist/panel.min.js"></script>
|
61 |
+
|
62 |
+
<script type="text/javascript">
|
63 |
+
Bokeh.set_log_level("info");
|
64 |
+
</script> </head>
|
65 |
+
<body class="pn-loading pn-arc">
|
66 |
+
<div id="fa274ef9-7f7c-4f2c-af20-4ae6c40d71b9" data-root-id="p1002" style="display: contents;"></div>
|
67 |
+
<div id="c367c845-48f8-45d5-b513-e489cdcd5ad5" data-root-id="p1031" style="display: contents;"></div>
|
68 |
+
<div id="ae42b629-5425-4abc-9277-8eeb6eab6e9a" data-root-id="p1032" style="display: contents;"></div>
|
69 |
+
|
70 |
+
<script type="text/javascript">
|
71 |
+
const pyodideWorker = new Worker("./index.js");
|
72 |
+
pyodideWorker.busy = false
|
73 |
+
pyodideWorker.queue = []
|
74 |
+
|
75 |
+
function send_change(jsdoc, event) {
|
76 |
+
if (event.setter_id != null && event.setter_id == 'py') {
|
77 |
+
return
|
78 |
+
} else if (pyodideWorker.busy && event.model && event.attr) {
|
79 |
+
let events = []
|
80 |
+
for (const old_event of pyodideWorker.queue) {
|
81 |
+
if (!(old_event.model === event.model && old_event.attr === event.attr)) {
|
82 |
+
events.push(old_event)
|
83 |
+
}
|
84 |
+
}
|
85 |
+
events.push(event)
|
86 |
+
pyodideWorker.queue = events
|
87 |
+
return
|
88 |
+
}
|
89 |
+
const patch = jsdoc.create_json_patch([event])
|
90 |
+
pyodideWorker.busy = true
|
91 |
+
pyodideWorker.postMessage({type: 'patch', patch: patch})
|
92 |
+
}
|
93 |
+
|
94 |
+
pyodideWorker.onmessage = async (event) => {
|
95 |
+
const msg = event.data
|
96 |
+
|
97 |
+
const body = document.getElementsByTagName('body')[0]
|
98 |
+
const loading_msgs = document.getElementsByClassName('pn-loading-msg')
|
99 |
+
if (msg.type === 'idle') {
|
100 |
+
if (pyodideWorker.queue.length) {
|
101 |
+
const patch = pyodideWorker.jsdoc.create_json_patch(pyodideWorker.queue)
|
102 |
+
pyodideWorker.busy = true
|
103 |
+
pyodideWorker.queue = []
|
104 |
+
pyodideWorker.postMessage({type: 'patch', patch: patch})
|
105 |
+
} else {
|
106 |
+
pyodideWorker.busy = false
|
107 |
+
}
|
108 |
+
} else if (msg.type === 'status') {
|
109 |
+
let loading_msg
|
110 |
+
if (loading_msgs.length) {
|
111 |
+
loading_msg = loading_msgs[0]
|
112 |
+
} else if (body.classList.contains('pn-loading')) {
|
113 |
+
loading_msg = document.createElement('div')
|
114 |
+
loading_msg.classList.add('pn-loading-msg')
|
115 |
+
body.appendChild(loading_msg)
|
116 |
+
}
|
117 |
+
if (loading_msg != null) {
|
118 |
+
loading_msg.innerHTML = msg.msg
|
119 |
+
}
|
120 |
+
} else if (msg.type === 'render') {
|
121 |
+
const docs_json = JSON.parse(msg.docs_json)
|
122 |
+
const render_items = JSON.parse(msg.render_items)
|
123 |
+
const root_ids = JSON.parse(msg.root_ids)
|
124 |
+
|
125 |
+
// Remap roots in message to element IDs
|
126 |
+
const root_els = document.querySelectorAll('[data-root-id]')
|
127 |
+
const data_roots = []
|
128 |
+
for (const el of root_els) {
|
129 |
+
el.innerHTML = ''
|
130 |
+
data_roots.push([el.getAttribute('data-root-id'), el.id])
|
131 |
+
}
|
132 |
+
data_roots.sort((a, b) => a[0]<b[0] ? -1: 1)
|
133 |
+
const roots = {}
|
134 |
+
for (let i=0; i<data_roots.length; i++) {
|
135 |
+
roots[root_ids[i]] = data_roots[i][1]
|
136 |
+
}
|
137 |
+
render_items[0]['roots'] = roots
|
138 |
+
render_items[0]['root_ids'] = root_ids
|
139 |
+
|
140 |
+
// Embed content
|
141 |
+
const [views] = await Bokeh.embed.embed_items(docs_json, render_items)
|
142 |
+
|
143 |
+
// Remove loading spinner and message
|
144 |
+
body.classList.remove("pn-loading", "arc")
|
145 |
+
for (const loading_msg of loading_msgs) {
|
146 |
+
loading_msg.remove()
|
147 |
+
}
|
148 |
+
|
149 |
+
// Setup bi-directional syncing
|
150 |
+
pyodideWorker.jsdoc = jsdoc = [...views.roots.values()][0].model.document
|
151 |
+
jsdoc.on_change(send_change.bind(null, jsdoc), false)
|
152 |
+
pyodideWorker.postMessage({'type': 'rendered'})
|
153 |
+
pyodideWorker.postMessage({'type': 'location', location: JSON.stringify(window.location)})
|
154 |
+
} else if (msg.type === 'patch') {
|
155 |
+
pyodideWorker.jsdoc.apply_json_patch(msg.patch, msg.buffers, setter_id='py')
|
156 |
+
}
|
157 |
+
};
|
158 |
+
</script>
|
159 |
+
<script type="application/json" id="p1096">
|
160 |
+
{"51689a96-5032-4772-be79-93e65dccfbbb":{"version":"3.3.2","title":"Panel Application","roots":[{"type":"object","name":"panel.models.layout.Column","id":"p1002","attributes":{"name":"Column00867","stylesheets":["\n:host(.pn-loading.pn-arc):before, .pn-loading.pn-arc:before {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IG5vbmU7IGRpc3BsYXk6IGJsb2NrOyBzaGFwZS1yZW5kZXJpbmc6IGF1dG87IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiPiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzNjM2MzIiBzdHJva2Utd2lkdGg9IjEwIiByPSIzNSIgc3Ryb2tlLWRhc2hhcnJheT0iMTY0LjkzMzYxNDMxMzQ2NDE1IDU2Ljk3Nzg3MTQzNzgyMTM4Ij4gICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJyb3RhdGUiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjFzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIj48L2FuaW1hdGVUcmFuc2Zvcm0+ICA8L2NpcmNsZT48L3N2Zz4=\");\n background-size: auto calc(min(50%, 400px));\n}",{"type":"object","name":"ImportedStyleSheet","id":"p1007","attributes":{"url":"https://cdn.holoviz.org/panel/1.3.6/dist/css/loading.css"}},{"type":"object","name":"ImportedStyleSheet","id":"p1025","attributes":{"url":"https://cdn.holoviz.org/panel/1.3.6/dist/css/listpanel.css"}},{"type":"object","name":"ImportedStyleSheet","id":"p1003","attributes":{"url":"https://cdn.jsdelivr.net/npm/[email protected]/dist/material-components-web.min.css"}},{"type":"object","name":"ImportedStyleSheet","id":"p1004","attributes":{"url":"https://cdn.holoviz.org/panel/1.3.6/dist/bundled/theme/default.css"}},{"type":"object","name":"ImportedStyleSheet","id":"p1005","attributes":{"url":"https://cdn.holoviz.org/panel/1.3.6/dist/bundled/theme/material_variables.css"}},{"type":"object","name":"ImportedStyleSheet","id":"p1006","attributes":{"url":"https://cdn.holoviz.org/panel/1.3.6/dist/bundled/theme/material.css"}}],"min_width":300,"margin":0,"sizing_mode":"stretch_width","align":"start","children":[{"type":"object","name":"panel.models.markup.HTML","id":"p1009","attributes":{"css_classes":["markdown"],"stylesheets":["\n:host(.pn-loading.pn-arc):before, .pn-loading.pn-arc:before {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IG5vbmU7IGRpc3BsYXk6IGJsb2NrOyBzaGFwZS1yZW5kZXJpbmc6IGF1dG87IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiPiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzNjM2MzIiBzdHJva2Utd2lkdGg9IjEwIiByPSIzNSIgc3Ryb2tlLWRhc2hhcnJheT0iMTY0LjkzMzYxNDMxMzQ2NDE1IDU2Ljk3Nzg3MTQzNzgyMTM4Ij4gICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJyb3RhdGUiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjFzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIj48L2FuaW1hdGVUcmFuc2Zvcm0+ICA8L2NpcmNsZT48L3N2Zz4=\");\n background-size: auto calc(min(50%, 400px));\n}",{"id":"p1007"},{"type":"object","name":"ImportedStyleSheet","id":"p1008","attributes":{"url":"https://cdn.holoviz.org/panel/1.3.6/dist/css/markdown.css"}},{"id":"p1003"},{"id":"p1004"},{"id":"p1005"},{"id":"p1006"}],"margin":[5,10],"sizing_mode":"stretch_width","align":"start","text":"&lt;h1 id=&quot;speed-up-slow-functions-with-caching&quot;&gt;Speed up slow functions with caching &lt;a class=&quot;header-anchor&quot; href=&quot;#speed-up-slow-functions-with-caching&quot;&gt;\u00b6&lt;/a&gt;&lt;/h1&gt;\n"}},{"type":"object","name":"Slider","id":"p1011","attributes":{"stylesheets":["\n:host(.pn-loading.pn-arc):before, .pn-loading.pn-arc:before {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IG5vbmU7IGRpc3BsYXk6IGJsb2NrOyBzaGFwZS1yZW5kZXJpbmc6IGF1dG87IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiPiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzNjM2MzIiBzdHJva2Utd2lkdGg9IjEwIiByPSIzNSIgc3Ryb2tlLWRhc2hhcnJheT0iMTY0LjkzMzYxNDMxMzQ2NDE1IDU2Ljk3Nzg3MTQzNzgyMTM4Ij4gICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJyb3RhdGUiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjFzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIj48L2FuaW1hdGVUcmFuc2Zvcm0+ICA8L2NpcmNsZT48L3N2Zz4=\");\n background-size: auto calc(min(50%, 400px));\n}",{"id":"p1007"},{"id":"p1003"},{"id":"p1004"},{"id":"p1005"},{"id":"p1006"}],"margin":[5,10],"align":"start","title":"Fraction of data","start":0.1,"end":1.0,"value":0.1,"step":0.1}},{"type":"object","name":"Div","id":"p1013","attributes":{"stylesheets":["\n:host(.pn-loading.pn-arc):before, .pn-loading.pn-arc:before {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IG5vbmU7IGRpc3BsYXk6IGJsb2NrOyBzaGFwZS1yZW5kZXJpbmc6IGF1dG87IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiPiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzNjM2MzIiBzdHJva2Utd2lkdGg9IjEwIiByPSIzNSIgc3Ryb2tlLWRhc2hhcnJheT0iMTY0LjkzMzYxNDMxMzQ2NDE1IDU2Ljk3Nzg3MTQzNzgyMTM4Ij4gICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJyb3RhdGUiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjFzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIj48L2FuaW1hdGVUcmFuc2Zvcm0+ICA8L2NpcmNsZT48L3N2Zz4=\");\n background-size: auto calc(min(50%, 400px));\n}",{"id":"p1007"},{"id":"p1003"},{"id":"p1004"},{"id":"p1005"},{"id":"p1006"}],"margin":[5,10],"align":"start","text":"<b>Time to create plot</b>: 1.0674 seconds"}},{"type":"object","name":"Checkbox","id":"p1015","attributes":{"stylesheets":["\n:host(.pn-loading.pn-arc):before, .pn-loading.pn-arc:before {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IG5vbmU7IGRpc3BsYXk6IGJsb2NrOyBzaGFwZS1yZW5kZXJpbmc6IGF1dG87IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiPiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzNjM2MzIiBzdHJva2Utd2lkdGg9IjEwIiByPSIzNSIgc3Ryb2tlLWRhc2hhcnJheT0iMTY0LjkzMzYxNDMxMzQ2NDE1IDU2Ljk3Nzg3MTQzNzgyMTM4Ij4gICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJyb3RhdGUiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjFzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIj48L2FuaW1hdGVUcmFuc2Zvcm0+ICA8L2NpcmNsZT48L3N2Zz4=\");\n background-size: auto calc(min(50%, 400px));\n}",{"id":"p1007"},{"id":"p1003"},{"id":"p1004"},{"id":"p1005"},{"id":"p1006"}],"margin":[5,10],"align":"start","label":"Use Cache"}},{"type":"object","name":"Figure","id":"p1040","attributes":{"width":700,"height":300,"min_height":500,"margin":[5,10],"sizing_mode":"stretch_both","align":"start","x_range":{"type":"object","name":"Range1d","id":"p1033","attributes":{"tags":[[["time","time",null]],[]],"start":1577836920000.0,"end":1577922900000.0,"reset_start":1577836920000.0,"reset_end":1577922900000.0}},"y_range":{"type":"object","name":"Range1d","id":"p1034","attributes":{"tags":[[["price","price",null]],{"type":"map","entries":[["invert_yaxis",false],["autorange",false]]}],"start":95.31531063143329,"end":101.09907085910173,"reset_start":95.31531063143329,"reset_end":101.09907085910173}},"x_scale":{"type":"object","name":"LinearScale","id":"p1050"},"y_scale":{"type":"object","name":"LinearScale","id":"p1051"},"title":{"type":"object","name":"Title","id":"p1043","attributes":{"text_font":"Roboto, sans-serif, Verdana","text_font_size":"1.15em"}},"renderers":[{"type":"object","name":"GlyphRenderer","id":"p1092","attributes":{"data_source":{"type":"object","name":"ColumnDataSource","id":"p1083","attributes":{"selected":{"type":"object","name":"Selection","id":"p1084","attributes":{"indices":[],"line_indices":[]}},"selection_policy":{"type":"object","name":"UnionRenderers","id":"p1085"},"data":{"type":"map","entries":[["time",{"type":"ndarray","array":{"type":"bytes","data":"AADMi+b1dkIAAL635vV2QgAAlDvn9XZCAABAQ+j1dkIAACSb6PV2QgAAYuTo9XZCAABUEOn1dkIAAN526fV2QgAAYALr9XZCAACsH+v1dkIAAIKj6/V2QgAA8GHs9XZCAADijez1dkIAAHrI7PV2QgAAXiDt9XZCAACAwe31dkIAAPxT7vV2QgAAhrru9XZCAAAsye71dkIAAMQD7/V2QgAAqFvv9XZCAABOau/1dkIAAJqH7/V2QgAAJO7v9XZCAADK/O/1dkIAAHAL8PV2QgAAbiny9XZCAACQyvL1dkIAAAxd8/V2QgAA9q309XZCAACitfX1dkIAAMRW9vV2QgAAXJH29XZCAACa2vb1dkIAAIwG9/V2QgAAOA749XZCAABgqPn1dkIAAHR1+vV2QgAAGoT69XZCAAA8Jfv1dkIAAIhC+/V2QgAAbJr79XZCAADoLPz1dkIAAPz5/PV2QgAAogj99XZCAACUNP31dkIAAE4Q/vV2QgAAMmj+9XZCAADYdv71dkIAAK76/vV2QgAA8FoC9nZCAADihgL2dkIAAPZTA/Z2QgAAjo4D9nZCAAD8TAT2dkIAAOCkBPZ2QgAAjKwF9nZCAAAk5wX2dkIAAHAEBvZ2QgAAhNEG9nZCAAAq4Ab2dkIAAGgpB/Z2QgAAWlUH9nZCAACsawj2dkIAAMA4CfZ2QgAAZkcJ9nZCAABsQAr2dkIAAPamCvZ2QgAANPAK9nZCAAAYSAv2dkIAAO7LC/Z2QgAAtnsM9nZCAAD0xAz2dkIAAIz/DPZ2QgAAOAcO9nZCAAAcXw72dkIAAMJtDvZ2QgAAtJkO9nZCAACsvg/2dkIAABDAE/Z2QgAAQDUU9nZCAAB+fhT2dkIAAMqbFPZ2QgAAcKoU9nZCAACEdxX2dkIAAA7eFfZ2QgAAFNcW9nZCAABETBf2dkIAADZ4F/Z2QgAA1KsY9nZCAABCahn2dkIAAMzQGfZ2QgAAct8Z9nZCAACUgBr2dkIAAHzvHfZ2QgAA+IEe9nZCAACQvB72dkIAACj3HvZ2QgAA8KYf9nZCAACI4R/2dkIAAI7aIPZ2QgAAvk8h9nZCAAA64iH2dkIAACQzI/Z2QgAAFl8j9nZCAACEHST2dkIAAGh1JPZ2QgAAZpMm9nZCAADoHij2dkIAAL6iKPZ2QgAAVt0o9nZCAACGUin2dkIAACSGKvZ2QgAAkkQr9nZCAADeYSv2dkIAAHacK/Z2QgAAPGou9nZCAADUpC72dkIAAMbQLvZ2QgAAVjAw9nZCAAD8PjD2dkIAAEhcMPZ2QgAA7mow9nZCAAAstDD2dkIAAKhGMfZ2QgAAjJ4x9nZCAADK5zH2dkIAAAgxMvZ2QgAAVE4y9nZCAAAOKjP2dkIAAJ6JNPZ2QgAARJg09nZCAACC4TT2dkIAAGY5NfZ2QgAA/nM19nZCAADwnzX2dkIAABJBNvZ2QgAABG029nZCAABQijb2dkIAAGRXN/Z2QgAAsHQ39nZCAADg6Tf2dkIAACwHOPZ2QgAAAos49nZC"},"shape":[144],"dtype":"float64","order":"little"}],["price",{"type":"ndarray","array":{"type":"bytes","data":"KCJCVeMBWECvZ4deRn5YQN2Cnb+oRVhAu5cE8WdGWEAx4AAUsLxYQCaHv11silhAqNeYw9zVWEBh3YTlEbpYQLqaNUEca1hAhlP4MGmgWEBN7SsRXbpYQBmPlY09DllA1WNsyZ1sWED/eSqH8WpYQIZ+B9wXYVhAsgTJqXRpWEAzYrZYsW1YQGY3KB7UIVhADMxQsEeRWEBRRpEEo7VYQMMAvgdDUVhASE5axUaHWEDj+tow631YQM191aWkf1hAya3xbIZbWEDeYUmJgihYQKaYUgG0y1hA3MHEn1Z0WEAMlKA8uf9YQLpp8qzYqVhA4wXchxZNWEAgx7iqXe1YQFxRYzpB31hAY4f3eqpDWECT8BVEAH9YQI8dmG+zhVhAtqABXKecWEAIsxfGf3RYQF6VEB39i1hApQGphqUvWEAuIRaX265YQFmjvBpsblhAKC3zJEjVWEBxYZ/Pu7tYQFlYOxu7UlhA8zZeQRumWEDTkoj3q7JYQOJEtrsgqVhAz8VzbfafWEBY7Xd6+JBYQK9XaBO4jVhArEoMqcL8WEDL8awj0oVYQJvpV+zfZ1hAhzldzwbzV0CAUuiop3VYQLmSa1nSZFhADerLm1+SWEBgpkFV8ZVYQA1vtPPj21hAldsbkH1/WEDbiwwXFItYQOini1pkR1hAE0GUan4nWUDBNXlKeyxYQOdVKmkpoVhABh9mHaNxWECqweaN8KVYQCfltiF5SVhA3+XKrhRZWECAwsLcVjxYQHm+06P59VhAa26EmON+WEAOzhOMD7FYQHrCVS0el1hAeEJXD4GtWECrkyHuQ49YQF/RnxQFvFhAbkwiDZuyWEDlEl5JiLRYQM5gNIoph1hACzffT2K9WEDcLvbASbdYQJlwLPIXeVhA+17kgZJkWEBKX8c1DeNYQNNYqFyCdVhAtDU5g9JfWEC5DC4lVnxYQDWIx4iz9VdAxwKR+0GGWEA5IbhZX8VYQE5hoLVFrVhAZsx2VglzWECSNUlcBVxYQLDgebQGM1hALdPo/zefWEBcNF0h+5xYQHbzhm/7dlhA8HrCvY18WEAcO4vPTqlYQPe5d0MeC1hAta3laNQTWED5cmneuqtYQA4Hlz0wC1lAC5JWKLLRWEBCyznR4sRYQAqyD2fJtFhAa2GC2qChWEAVZGsO4IZYQMrVY/nihlhAOZR26/ZbWEAUdtSQjbVYQP/wWlZqWVhAiRhBM62/WECjEhrCDIpYQOz6t8nM/VhADzwExllLWEB5cVzZN8NYQLXbrDZDm1hAX0P4dv8KWUCWCmegD1lYQGen4KSQllhAh53j1YyxWEDTvcnjNqNYQEAqUCddfVhAkmx5Ddm0WEDKoazbfM5YQI5BmYj8jVhAihooxNLMWED2D4nO1FhYQD24PfsNdFhAnZNsk03bWEAUjI8s8rRYQNBKYlldhVhAinYJkQ5uWEDwoykXVJRYQNccG/ywnFhAZoe2aXhtWECLplUNIn1YQCpixIvou1hAcvy0JKyAWEBdmfJM/gpYQDAqPKyQOlhA"},"shape":[144],"dtype":"float64","order":"little"}]]}}},"view":{"type":"object","name":"CDSView","id":"p1093","attributes":{"filter":{"type":"object","name":"AllIndices","id":"p1094"}}},"glyph":{"type":"object","name":"Line","id":"p1089","attributes":{"tags":["apply_ranges"],"x":{"type":"field","field":"time"},"y":{"type":"field","field":"price"},"line_color":"#1f77b4","line_width":2}},"selection_glyph":{"type":"object","name":"Line","id":"p1095","attributes":{"tags":["apply_ranges"],"x":{"type":"field","field":"time"},"y":{"type":"field","field":"price"},"line_color":"#1f77b4","line_width":2}},"nonselection_glyph":{"type":"object","name":"Line","id":"p1090","attributes":{"tags":["apply_ranges"],"x":{"type":"field","field":"time"},"y":{"type":"field","field":"price"},"line_color":"#1f77b4","line_alpha":0.1,"line_width":2}},"muted_glyph":{"type":"object","name":"Line","id":"p1091","attributes":{"tags":["apply_ranges"],"x":{"type":"field","field":"time"},"y":{"type":"field","field":"price"},"line_color":"#1f77b4","line_alpha":0.2,"line_width":2}}}}],"toolbar":{"type":"object","name":"Toolbar","id":"p1049","attributes":{"tools":[{"type":"object","name":"WheelZoomTool","id":"p1038","attributes":{"tags":["hv_created"],"renderers":"auto","zoom_together":"none"}},{"type":"object","name":"HoverTool","id":"p1039","attributes":{"tags":["hv_created"],"renderers":[{"id":"p1092"}],"tooltips":[["time","@{time}{%F %T}"],["price","@{price}"]],"formatters":{"type":"map","entries":[["@{time}","datetime"]]}}},{"type":"object","name":"SaveTool","id":"p1074"},{"type":"object","name":"PanTool","id":"p1075"},{"type":"object","name":"BoxZoomTool","id":"p1076","attributes":{"overlay":{"type":"object","name":"BoxAnnotation","id":"p1077","attributes":{"syncable":false,"level":"overlay","visible":false,"left":{"type":"number","value":"nan"},"right":{"type":"number","value":"nan"},"top":{"type":"number","value":"nan"},"bottom":{"type":"number","value":"nan"},"left_units":"canvas","right_units":"canvas","top_units":"canvas","bottom_units":"canvas","line_color":"black","line_alpha":1.0,"line_width":2,"line_dash":[4,4],"fill_color":"lightgrey","fill_alpha":0.5}}}},{"type":"object","name":"ResetTool","id":"p1082"}],"active_drag":{"id":"p1075"},"active_scroll":{"id":"p1038"}}},"left":[{"type":"object","name":"LinearAxis","id":"p1069","attributes":{"ticker":{"type":"object","name":"BasicTicker","id":"p1070","attributes":{"mantissas":[1,2,5]}},"formatter":{"type":"object","name":"BasicTickFormatter","id":"p1071"},"axis_label":"price","axis_label_standoff":10,"axis_label_text_font":"Roboto, sans-serif, Verdana","axis_label_text_font_size":"1.25em","axis_label_text_font_style":"normal","major_label_policy":{"type":"object","name":"AllLabels","id":"p1072"},"major_label_text_font":"Roboto, sans-serif, Verdana","major_label_text_font_size":"1.025em"}}],"below":[{"type":"object","name":"DatetimeAxis","id":"p1052","attributes":{"ticker":{"type":"object","name":"DatetimeTicker","id":"p1053","attributes":{"num_minor_ticks":5,"tickers":[{"type":"object","name":"AdaptiveTicker","id":"p1054","attributes":{"num_minor_ticks":0,"mantissas":[1,2,5],"max_interval":500.0}},{"type":"object","name":"AdaptiveTicker","id":"p1055","attributes":{"num_minor_ticks":0,"base":60,"mantissas":[1,2,5,10,15,20,30],"min_interval":1000.0,"max_interval":1800000.0}},{"type":"object","name":"AdaptiveTicker","id":"p1056","attributes":{"num_minor_ticks":0,"base":24,"mantissas":[1,2,4,6,8,12],"min_interval":3600000.0,"max_interval":43200000.0}},{"type":"object","name":"DaysTicker","id":"p1057","attributes":{"days":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]}},{"type":"object","name":"DaysTicker","id":"p1058","attributes":{"days":[1,4,7,10,13,16,19,22,25,28]}},{"type":"object","name":"DaysTicker","id":"p1059","attributes":{"days":[1,8,15,22]}},{"type":"object","name":"DaysTicker","id":"p1060","attributes":{"days":[1,15]}},{"type":"object","name":"MonthsTicker","id":"p1061","attributes":{"months":[0,1,2,3,4,5,6,7,8,9,10,11]}},{"type":"object","name":"MonthsTicker","id":"p1062","attributes":{"months":[0,2,4,6,8,10]}},{"type":"object","name":"MonthsTicker","id":"p1063","attributes":{"months":[0,4,8]}},{"type":"object","name":"MonthsTicker","id":"p1064","attributes":{"months":[0,6]}},{"type":"object","name":"YearsTicker","id":"p1065"}]}},"formatter":{"type":"object","name":"DatetimeTickFormatter","id":"p1066"},"axis_label":"time","axis_label_standoff":10,"axis_label_text_font":"Roboto, sans-serif, Verdana","axis_label_text_font_size":"1.25em","axis_label_text_font_style":"normal","major_label_policy":{"type":"object","name":"AllLabels","id":"p1067"},"major_label_text_font":"Roboto, sans-serif, Verdana","major_label_text_font_size":"1.025em"}}],"center":[{"type":"object","name":"Grid","id":"p1068","attributes":{"axis":{"id":"p1052"},"grid_line_color":null}},{"type":"object","name":"Grid","id":"p1073","attributes":{"dimension":1,"axis":{"id":"p1069"},"grid_line_color":null}}],"min_border_top":10,"min_border_bottom":10,"min_border_left":10,"min_border_right":10,"output_backend":"webgl"}},{"type":"object","name":"Row","id":"p1017","attributes":{"name":"Row00866","stylesheets":["\n:host(.pn-loading.pn-arc):before, .pn-loading.pn-arc:before {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IG5vbmU7IGRpc3BsYXk6IGJsb2NrOyBzaGFwZS1yZW5kZXJpbmc6IGF1dG87IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiPiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzNjM2MzIiBzdHJva2Utd2lkdGg9IjEwIiByPSIzNSIgc3Ryb2tlLWRhc2hhcnJheT0iMTY0LjkzMzYxNDMxMzQ2NDE1IDU2Ljk3Nzg3MTQzNzgyMTM4Ij4gICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJyb3RhdGUiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjFzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIj48L2FuaW1hdGVUcmFuc2Zvcm0+ICA8L2NpcmNsZT48L3N2Zz4=\");\n background-size: auto calc(min(50%, 400px));\n}",{"id":"p1007"},{"id":"p1025"},{"id":"p1003"},{"id":"p1004"},{"id":"p1005"},{"id":"p1006"}],"margin":0,"align":"start","children":[{"type":"object","name":"panel.models.widgets.Button","id":"p1020","attributes":{"button_type":"primary","subscribed_events":{"type":"set","entries":["button_click"]},"css_classes":["solid"],"stylesheets":["\n:host(.pn-loading.pn-arc):before, .pn-loading.pn-arc:before {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IG5vbmU7IGRpc3BsYXk6IGJsb2NrOyBzaGFwZS1yZW5kZXJpbmc6IGF1dG87IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiPiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzNjM2MzIiBzdHJva2Utd2lkdGg9IjEwIiByPSIzNSIgc3Ryb2tlLWRhc2hhcnJheT0iMTY0LjkzMzYxNDMxMzQ2NDE1IDU2Ljk3Nzg3MTQzNzgyMTM4Ij4gICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJyb3RhdGUiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjFzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIj48L2FuaW1hdGVUcmFuc2Zvcm0+ICA8L2NpcmNsZT48L3N2Zz4=\");\n background-size: auto calc(min(50%, 400px));\n}",{"id":"p1007"},{"type":"object","name":"ImportedStyleSheet","id":"p1019","attributes":{"url":"https://cdn.holoviz.org/panel/1.3.6/dist/css/button.css"}},{"id":"p1003"},{"id":"p1004"},{"id":"p1005"},{"id":"p1006"}],"disabled":true,"margin":[5,10],"align":"start","label":"Preload Cache"}},{"type":"object","name":"panel.models.widgets.Button","id":"p1023","attributes":{"subscribed_events":{"type":"set","entries":["button_click"]},"css_classes":["solid"],"stylesheets":["\n:host(.pn-loading.pn-arc):before, .pn-loading.pn-arc:before {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IG5vbmU7IGRpc3BsYXk6IGJsb2NrOyBzaGFwZS1yZW5kZXJpbmc6IGF1dG87IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiPiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzNjM2MzIiBzdHJva2Utd2lkdGg9IjEwIiByPSIzNSIgc3Ryb2tlLWRhc2hhcnJheT0iMTY0LjkzMzYxNDMxMzQ2NDE1IDU2Ljk3Nzg3MTQzNzgyMTM4Ij4gICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJyb3RhdGUiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjFzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIj48L2FuaW1hdGVUcmFuc2Zvcm0+ICA8L2NpcmNsZT48L3N2Zz4=\");\n background-size: auto calc(min(50%, 400px));\n}",{"id":"p1007"},{"id":"p1019"},{"id":"p1003"},{"id":"p1004"},{"id":"p1005"},{"id":"p1006"}],"disabled":true,"margin":[5,10],"align":"start","label":"Clear Cache"}}]}},{"type":"object","name":"panel.models.widgets.Progress","id":"p1028","attributes":{"stylesheets":["\n:host(.pn-loading.pn-arc):before, .pn-loading.pn-arc:before {\n background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IG5vbmU7IGRpc3BsYXk6IGJsb2NrOyBzaGFwZS1yZW5kZXJpbmc6IGF1dG87IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiPiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzNjM2MzIiBzdHJva2Utd2lkdGg9IjEwIiByPSIzNSIgc3Ryb2tlLWRhc2hhcnJheT0iMTY0LjkzMzYxNDMxMzQ2NDE1IDU2Ljk3Nzg3MTQzNzgyMTM4Ij4gICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJyb3RhdGUiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBkdXI9IjFzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIj48L2FuaW1hdGVUcmFuc2Zvcm0+ICA8L2NpcmNsZT48L3N2Zz4=\");\n background-size: auto calc(min(50%, 400px));\n}",{"id":"p1007"},{"type":"object","name":"ImportedStyleSheet","id":"p1027","attributes":{"url":"https://cdn.holoviz.org/panel/1.3.6/dist/css/progress.css"}},{"id":"p1003"},{"id":"p1004"},{"id":"p1005"},{"id":"p1006"}],"disabled":true,"width":300,"margin":[5,10],"sizing_mode":"stretch_width","align":"start","active":false,"bar_color":"success","value":0}}]}},{"type":"object","name":"panel.models.location.Location","id":"p1031","attributes":{"name":"location","reload":false}},{"type":"object","name":"panel.models.browser.BrowserInfo","id":"p1032","attributes":{"name":"browser_info"}}],"defs":[{"type":"model","name":"ReactiveHTML1"},{"type":"model","name":"FlexBox1","properties":[{"name":"align_content","kind":"Any","default":"flex-start"},{"name":"align_items","kind":"Any","default":"flex-start"},{"name":"flex_direction","kind":"Any","default":"row"},{"name":"flex_wrap","kind":"Any","default":"wrap"},{"name":"justify_content","kind":"Any","default":"flex-start"}]},{"type":"model","name":"FloatPanel1","properties":[{"name":"config","kind":"Any","default":{"type":"map"}},{"name":"contained","kind":"Any","default":true},{"name":"position","kind":"Any","default":"right-top"},{"name":"offsetx","kind":"Any","default":null},{"name":"offsety","kind":"Any","default":null},{"name":"theme","kind":"Any","default":"primary"},{"name":"status","kind":"Any","default":"normalized"}]},{"type":"model","name":"GridStack1","properties":[{"name":"mode","kind":"Any","default":"warn"},{"name":"ncols","kind":"Any","default":null},{"name":"nrows","kind":"Any","default":null},{"name":"allow_resize","kind":"Any","default":true},{"name":"allow_drag","kind":"Any","default":true},{"name":"state","kind":"Any","default":[]}]},{"type":"model","name":"drag1","properties":[{"name":"slider_width","kind":"Any","default":5},{"name":"slider_color","kind":"Any","default":"black"},{"name":"value","kind":"Any","default":50}]},{"type":"model","name":"click1","properties":[{"name":"terminal_output","kind":"Any","default":""},{"name":"debug_name","kind":"Any","default":""},{"name":"clears","kind":"Any","default":0}]},{"type":"model","name":"copy_to_clipboard1","properties":[{"name":"fill","kind":"Any","default":"none"},{"name":"value","kind":"Any","default":null}]},{"type":"model","name":"FastWrapper1","properties":[{"name":"object","kind":"Any","default":null},{"name":"style","kind":"Any","default":null}]},{"type":"model","name":"NotificationAreaBase1","properties":[{"name":"js_events","kind":"Any","default":{"type":"map"}},{"name":"position","kind":"Any","default":"bottom-right"},{"name":"_clear","kind":"Any","default":0}]},{"type":"model","name":"NotificationArea1","properties":[{"name":"js_events","kind":"Any","default":{"type":"map"}},{"name":"notifications","kind":"Any","default":[]},{"name":"position","kind":"Any","default":"bottom-right"},{"name":"_clear","kind":"Any","default":0},{"name":"types","kind":"Any","default":[{"type":"map","entries":[["type","warning"],["background","#ffc107"],["icon",{"type":"map","entries":[["className","fas fa-exclamation-triangle"],["tagName","i"],["color","white"]]}]]},{"type":"map","entries":[["type","info"],["background","#007bff"],["icon",{"type":"map","entries":[["className","fas fa-info-circle"],["tagName","i"],["color","white"]]}]]}]}]},{"type":"model","name":"Notification","properties":[{"name":"background","kind":"Any","default":null},{"name":"duration","kind":"Any","default":3000},{"name":"icon","kind":"Any","default":null},{"name":"message","kind":"Any","default":""},{"name":"notification_type","kind":"Any","default":null},{"name":"_destroyed","kind":"Any","default":false}]},{"type":"model","name":"TemplateActions1","properties":[{"name":"open_modal","kind":"Any","default":0},{"name":"close_modal","kind":"Any","default":0}]},{"type":"model","name":"BootstrapTemplateActions1","properties":[{"name":"open_modal","kind":"Any","default":0},{"name":"close_modal","kind":"Any","default":0}]},{"type":"model","name":"MaterialTemplateActions1","properties":[{"name":"open_modal","kind":"Any","default":0},{"name":"close_modal","kind":"Any","default":0}]}]}}
|
161 |
+
</script>
|
162 |
+
<script type="text/javascript">
|
163 |
+
(function() {
|
164 |
+
const fn = function() {
|
165 |
+
Bokeh.safely(function() {
|
166 |
+
(function(root) {
|
167 |
+
function embed_document(root) {
|
168 |
+
const docs_json = document.getElementById('p1096').textContent;
|
169 |
+
const render_items = [{"docid":"51689a96-5032-4772-be79-93e65dccfbbb","roots":{"p1002":"fa274ef9-7f7c-4f2c-af20-4ae6c40d71b9","p1031":"c367c845-48f8-45d5-b513-e489cdcd5ad5","p1032":"ae42b629-5425-4abc-9277-8eeb6eab6e9a"},"root_ids":["p1002","p1031","p1032"]}];
|
170 |
+
root.Bokeh.embed.embed_items(docs_json, render_items);
|
171 |
+
}
|
172 |
+
if (root.Bokeh !== undefined) {
|
173 |
+
embed_document(root);
|
174 |
+
} else {
|
175 |
+
let attempts = 0;
|
176 |
+
const timer = setInterval(function(root) {
|
177 |
+
if (root.Bokeh !== undefined) {
|
178 |
+
clearInterval(timer);
|
179 |
+
embed_document(root);
|
180 |
+
} else {
|
181 |
+
attempts++;
|
182 |
+
if (attempts > 100) {
|
183 |
+
clearInterval(timer);
|
184 |
+
console.log("Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing");
|
185 |
+
}
|
186 |
+
}
|
187 |
+
}, 10, root)
|
188 |
+
}
|
189 |
+
})(window);
|
190 |
+
});
|
191 |
+
};
|
192 |
+
if (document.readyState != "loading") fn();
|
193 |
+
else document.addEventListener("DOMContentLoaded", fn);
|
194 |
+
})();
|
195 |
+
</script>
|
196 |
+
</body>
|
197 |
+
</html>
|
index.js
ADDED
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
importScripts("https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js");
|
2 |
+
|
3 |
+
function sendPatch(patch, buffers, msg_id) {
|
4 |
+
self.postMessage({
|
5 |
+
type: 'patch',
|
6 |
+
patch: patch,
|
7 |
+
buffers: buffers
|
8 |
+
})
|
9 |
+
}
|
10 |
+
|
11 |
+
async function startApplication() {
|
12 |
+
console.log("Loading pyodide!");
|
13 |
+
self.postMessage({type: 'status', msg: 'Loading pyodide'})
|
14 |
+
self.pyodide = await loadPyodide();
|
15 |
+
self.pyodide.globals.set("sendPatch", sendPatch);
|
16 |
+
console.log("Loaded!");
|
17 |
+
await self.pyodide.loadPackage("micropip");
|
18 |
+
const env_spec = ['https://cdn.holoviz.org/panel/wheels/bokeh-3.3.2-py3-none-any.whl', 'https://cdn.holoviz.org/panel/1.3.6/dist/wheels/panel-1.3.6-py3-none-any.whl', 'pyodide-http==0.2.1', 'hvplot', 'numpy', 'pandas']
|
19 |
+
for (const pkg of env_spec) {
|
20 |
+
let pkg_name;
|
21 |
+
if (pkg.endsWith('.whl')) {
|
22 |
+
pkg_name = pkg.split('/').slice(-1)[0].split('-')[0]
|
23 |
+
} else {
|
24 |
+
pkg_name = pkg
|
25 |
+
}
|
26 |
+
self.postMessage({type: 'status', msg: `Installing ${pkg_name}`})
|
27 |
+
try {
|
28 |
+
await self.pyodide.runPythonAsync(`
|
29 |
+
import micropip
|
30 |
+
await micropip.install('${pkg}');
|
31 |
+
`);
|
32 |
+
} catch(e) {
|
33 |
+
console.log(e)
|
34 |
+
self.postMessage({
|
35 |
+
type: 'status',
|
36 |
+
msg: `Error while installing ${pkg_name}`
|
37 |
+
});
|
38 |
+
}
|
39 |
+
}
|
40 |
+
console.log("Packages loaded!");
|
41 |
+
self.postMessage({type: 'status', msg: 'Executing code'})
|
42 |
+
const code = `
|
43 |
+
|
44 |
+
import asyncio
|
45 |
+
|
46 |
+
from panel.io.pyodide import init_doc, write_doc
|
47 |
+
|
48 |
+
init_doc()
|
49 |
+
|
50 |
+
"""
|
51 |
+
# Caching Example
|
52 |
+
|
53 |
+
See https://awesome-panel.org/resources/caching_example
|
54 |
+
"""
|
55 |
+
import time
|
56 |
+
|
57 |
+
import hvplot.pandas # pylint: disable=unused-import
|
58 |
+
import numpy as np
|
59 |
+
import pandas as pd
|
60 |
+
import panel as pn
|
61 |
+
|
62 |
+
pn.extension(design="material")
|
63 |
+
|
64 |
+
ACCENT_COLOR = "#1f77b4"
|
65 |
+
|
66 |
+
np.random.seed([3, 1415])
|
67 |
+
PERIODS = 1 * 24 * 60 # minutes. I.e. 1 days
|
68 |
+
DATA = pd.DataFrame(
|
69 |
+
{
|
70 |
+
"time": pd.date_range("2020-01-01", periods=PERIODS, freq="T"),
|
71 |
+
"price": np.random.randn(PERIODS) + 98,
|
72 |
+
}
|
73 |
+
)
|
74 |
+
|
75 |
+
def _load_data(frac=0.1):
|
76 |
+
time.sleep(0.5 + frac * 0.5)
|
77 |
+
return DATA.sample(frac=frac)
|
78 |
+
|
79 |
+
def _plot_data(frac=0.1):
|
80 |
+
time.sleep(0.5)
|
81 |
+
data = _load_data(frac)
|
82 |
+
return data.hvplot(x="time", y="price")
|
83 |
+
|
84 |
+
@pn.cache(per_session=True, ttl=60*60*24)
|
85 |
+
def _plot_data_cached(frac):
|
86 |
+
return _plot_data(frac)
|
87 |
+
|
88 |
+
|
89 |
+
# Create Widgets
|
90 |
+
fraction = pn.widgets.FloatSlider(value=0.1, start=0.1, end=1.0, step=0.1, name="Fraction of data")
|
91 |
+
duration = pn.widgets.StaticText(value="", name="Time to create plot")
|
92 |
+
use_cache = pn.widgets.Checkbox(value=False, name="Use Cache")
|
93 |
+
preload_cache = pn.widgets.Button(name="Preload Cache", button_type="primary", disabled=True)
|
94 |
+
clear_cache = pn.widgets.Button(name="Clear Cache", disabled=True)
|
95 |
+
preload_progress = pn.widgets.Progress(
|
96 |
+
name="Progress", active=False, value=0, max=100, sizing_mode="stretch_width", disabled=True
|
97 |
+
)
|
98 |
+
|
99 |
+
plot_panel = pn.pane.HoloViews(min_height=500, sizing_mode="stretch_both")
|
100 |
+
|
101 |
+
# Setup interactivity
|
102 |
+
def _clear_cache(*_):
|
103 |
+
_plot_data_cached.clear()
|
104 |
+
|
105 |
+
|
106 |
+
clear_cache.on_click(_clear_cache)
|
107 |
+
|
108 |
+
|
109 |
+
def _preload_cache(*_):
|
110 |
+
for index in range(0, 11, 1):
|
111 |
+
frac_ = round(index / 10, 1)
|
112 |
+
preload_progress.value = int(frac_ * 100)
|
113 |
+
_plot_data_cached(frac_)
|
114 |
+
preload_progress.value = 0
|
115 |
+
|
116 |
+
|
117 |
+
preload_cache.on_click(_preload_cache)
|
118 |
+
|
119 |
+
|
120 |
+
@pn.depends(frac=fraction, watch=True)
|
121 |
+
def _update_plot(frac):
|
122 |
+
start_counter = time.perf_counter()
|
123 |
+
|
124 |
+
frac = round(frac, 1)
|
125 |
+
if use_cache.value:
|
126 |
+
plot = _plot_data_cached(frac)
|
127 |
+
else:
|
128 |
+
plot = _plot_data(frac)
|
129 |
+
|
130 |
+
end_counter = time.perf_counter()
|
131 |
+
duration.value = str(round(end_counter - start_counter, 4)) + " seconds"
|
132 |
+
|
133 |
+
# Please note DiskCache does not cache the options
|
134 |
+
plot.opts(color=ACCENT_COLOR, responsive=True)
|
135 |
+
plot_panel.object = plot
|
136 |
+
|
137 |
+
|
138 |
+
@pn.depends(use_cache=use_cache, watch=True)
|
139 |
+
def _update_cache_widgets(use_cache): # pylint: disable=redefined-outer-name
|
140 |
+
disabled = not use_cache
|
141 |
+
preload_cache.disabled = disabled
|
142 |
+
clear_cache.disabled = disabled
|
143 |
+
preload_progress.disabled = disabled
|
144 |
+
|
145 |
+
|
146 |
+
# Layout the app
|
147 |
+
pn.Column(
|
148 |
+
pn.pane.Markdown(
|
149 |
+
"# Speed up slow functions with caching", sizing_mode="stretch_width"
|
150 |
+
),
|
151 |
+
fraction,
|
152 |
+
duration,
|
153 |
+
use_cache,
|
154 |
+
plot_panel,
|
155 |
+
pn.Row(preload_cache, clear_cache,),
|
156 |
+
preload_progress,
|
157 |
+
).servable()
|
158 |
+
|
159 |
+
pn.state.onload(lambda: fraction.param.trigger("value"))
|
160 |
+
|
161 |
+
|
162 |
+
await write_doc()
|
163 |
+
`
|
164 |
+
|
165 |
+
try {
|
166 |
+
const [docs_json, render_items, root_ids] = await self.pyodide.runPythonAsync(code)
|
167 |
+
self.postMessage({
|
168 |
+
type: 'render',
|
169 |
+
docs_json: docs_json,
|
170 |
+
render_items: render_items,
|
171 |
+
root_ids: root_ids
|
172 |
+
})
|
173 |
+
} catch(e) {
|
174 |
+
const traceback = `${e}`
|
175 |
+
const tblines = traceback.split('\n')
|
176 |
+
self.postMessage({
|
177 |
+
type: 'status',
|
178 |
+
msg: tblines[tblines.length-2]
|
179 |
+
});
|
180 |
+
throw e
|
181 |
+
}
|
182 |
+
}
|
183 |
+
|
184 |
+
self.onmessage = async (event) => {
|
185 |
+
const msg = event.data
|
186 |
+
if (msg.type === 'rendered') {
|
187 |
+
self.pyodide.runPythonAsync(`
|
188 |
+
from panel.io.state import state
|
189 |
+
from panel.io.pyodide import _link_docs_worker
|
190 |
+
|
191 |
+
_link_docs_worker(state.curdoc, sendPatch, setter='js')
|
192 |
+
`)
|
193 |
+
} else if (msg.type === 'patch') {
|
194 |
+
self.pyodide.globals.set('patch', msg.patch)
|
195 |
+
self.pyodide.runPythonAsync(`
|
196 |
+
state.curdoc.apply_json_patch(patch.to_py(), setter='js')
|
197 |
+
`)
|
198 |
+
self.postMessage({type: 'idle'})
|
199 |
+
} else if (msg.type === 'location') {
|
200 |
+
self.pyodide.globals.set('location', msg.location)
|
201 |
+
self.pyodide.runPythonAsync(`
|
202 |
+
import json
|
203 |
+
from panel.io.state import state
|
204 |
+
from panel.util import edit_readonly
|
205 |
+
if state.location:
|
206 |
+
loc_data = json.loads(location)
|
207 |
+
with edit_readonly(state.location):
|
208 |
+
state.location.param.update({
|
209 |
+
k: v for k, v in loc_data.items() if k in state.location.param
|
210 |
+
})
|
211 |
+
`)
|
212 |
+
}
|
213 |
+
}
|
214 |
+
|
215 |
+
startApplication()
|
index.py
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
# Caching Example
|
3 |
+
|
4 |
+
See https://awesome-panel.org/resources/caching_example
|
5 |
+
"""
|
6 |
+
import time
|
7 |
+
|
8 |
+
import hvplot.pandas # pylint: disable=unused-import
|
9 |
+
import numpy as np
|
10 |
+
import pandas as pd
|
11 |
+
import panel as pn
|
12 |
+
|
13 |
+
pn.extension(design="material")
|
14 |
+
|
15 |
+
ACCENT_COLOR = "#1f77b4"
|
16 |
+
|
17 |
+
np.random.seed([3, 1415])
|
18 |
+
PERIODS = 1 * 24 * 60 # minutes. I.e. 1 days
|
19 |
+
DATA = pd.DataFrame(
|
20 |
+
{
|
21 |
+
"time": pd.date_range("2020-01-01", periods=PERIODS, freq="T"),
|
22 |
+
"price": np.random.randn(PERIODS) + 98,
|
23 |
+
}
|
24 |
+
)
|
25 |
+
|
26 |
+
def _load_data(frac=0.1):
|
27 |
+
time.sleep(0.5 + frac * 0.5)
|
28 |
+
return DATA.sample(frac=frac)
|
29 |
+
|
30 |
+
def _plot_data(frac=0.1):
|
31 |
+
time.sleep(0.5)
|
32 |
+
data = _load_data(frac)
|
33 |
+
return data.hvplot(x="time", y="price")
|
34 |
+
|
35 |
+
@pn.cache(per_session=True, ttl=60*60*24)
|
36 |
+
def _plot_data_cached(frac):
|
37 |
+
return _plot_data(frac)
|
38 |
+
|
39 |
+
|
40 |
+
# Create Widgets
|
41 |
+
fraction = pn.widgets.FloatSlider(value=0.1, start=0.1, end=1.0, step=0.1, name="Fraction of data")
|
42 |
+
duration = pn.widgets.StaticText(value="", name="Time to create plot")
|
43 |
+
use_cache = pn.widgets.Checkbox(value=False, name="Use Cache")
|
44 |
+
preload_cache = pn.widgets.Button(name="Preload Cache", button_type="primary", disabled=True)
|
45 |
+
clear_cache = pn.widgets.Button(name="Clear Cache", disabled=True)
|
46 |
+
preload_progress = pn.widgets.Progress(
|
47 |
+
name="Progress", active=False, value=0, max=100, sizing_mode="stretch_width", disabled=True
|
48 |
+
)
|
49 |
+
|
50 |
+
plot_panel = pn.pane.HoloViews(min_height=500, sizing_mode="stretch_both")
|
51 |
+
|
52 |
+
# Setup interactivity
|
53 |
+
def _clear_cache(*_):
|
54 |
+
_plot_data_cached.clear()
|
55 |
+
|
56 |
+
|
57 |
+
clear_cache.on_click(_clear_cache)
|
58 |
+
|
59 |
+
|
60 |
+
def _preload_cache(*_):
|
61 |
+
for index in range(0, 11, 1):
|
62 |
+
frac_ = round(index / 10, 1)
|
63 |
+
preload_progress.value = int(frac_ * 100)
|
64 |
+
_plot_data_cached(frac_)
|
65 |
+
preload_progress.value = 0
|
66 |
+
|
67 |
+
|
68 |
+
preload_cache.on_click(_preload_cache)
|
69 |
+
|
70 |
+
|
71 |
+
@pn.depends(frac=fraction, watch=True)
|
72 |
+
def _update_plot(frac):
|
73 |
+
start_counter = time.perf_counter()
|
74 |
+
|
75 |
+
frac = round(frac, 1)
|
76 |
+
if use_cache.value:
|
77 |
+
plot = _plot_data_cached(frac)
|
78 |
+
else:
|
79 |
+
plot = _plot_data(frac)
|
80 |
+
|
81 |
+
end_counter = time.perf_counter()
|
82 |
+
duration.value = str(round(end_counter - start_counter, 4)) + " seconds"
|
83 |
+
|
84 |
+
# Please note DiskCache does not cache the options
|
85 |
+
plot.opts(color=ACCENT_COLOR, responsive=True)
|
86 |
+
plot_panel.object = plot
|
87 |
+
|
88 |
+
|
89 |
+
@pn.depends(use_cache=use_cache, watch=True)
|
90 |
+
def _update_cache_widgets(use_cache): # pylint: disable=redefined-outer-name
|
91 |
+
disabled = not use_cache
|
92 |
+
preload_cache.disabled = disabled
|
93 |
+
clear_cache.disabled = disabled
|
94 |
+
preload_progress.disabled = disabled
|
95 |
+
|
96 |
+
|
97 |
+
# Layout the app
|
98 |
+
pn.Column(
|
99 |
+
pn.pane.Markdown(
|
100 |
+
"# Speed up slow functions with caching", sizing_mode="stretch_width"
|
101 |
+
),
|
102 |
+
fraction,
|
103 |
+
duration,
|
104 |
+
use_cache,
|
105 |
+
plot_panel,
|
106 |
+
pn.Row(preload_cache, clear_cache,),
|
107 |
+
preload_progress,
|
108 |
+
).servable()
|
109 |
+
|
110 |
+
pn.state.onload(lambda: fraction.param.trigger("value"))
|