Spaces:
Running
Running
File size: 5,789 Bytes
e01fd27 |
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
importScripts("https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js");
function sendPatch(patch, buffers, msg_id) {
self.postMessage({
type: 'patch',
patch: patch,
buffers: buffers
})
}
async function startApplication() {
console.log("Loading pyodide!");
self.postMessage({type: 'status', msg: 'Loading pyodide'})
self.pyodide = await loadPyodide();
self.pyodide.globals.set("sendPatch", sendPatch);
console.log("Loaded!");
await self.pyodide.loadPackage("micropip");
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']
for (const pkg of env_spec) {
let pkg_name;
if (pkg.endsWith('.whl')) {
pkg_name = pkg.split('/').slice(-1)[0].split('-')[0]
} else {
pkg_name = pkg
}
self.postMessage({type: 'status', msg: `Installing ${pkg_name}`})
try {
await self.pyodide.runPythonAsync(`
import micropip
await micropip.install('${pkg}');
`);
} catch(e) {
console.log(e)
self.postMessage({
type: 'status',
msg: `Error while installing ${pkg_name}`
});
}
}
console.log("Packages loaded!");
self.postMessage({type: 'status', msg: 'Executing code'})
const code = `
import asyncio
from panel.io.pyodide import init_doc, write_doc
init_doc()
"""
# Caching Example
See https://awesome-panel.org/resources/caching_example
"""
import time
import hvplot.pandas # pylint: disable=unused-import
import numpy as np
import pandas as pd
import panel as pn
pn.extension(design="material")
ACCENT_COLOR = "#1f77b4"
np.random.seed([3, 1415])
PERIODS = 1 * 24 * 60 # minutes. I.e. 1 days
DATA = pd.DataFrame(
{
"time": pd.date_range("2020-01-01", periods=PERIODS, freq="T"),
"price": np.random.randn(PERIODS) + 98,
}
)
def _load_data(frac=0.1):
time.sleep(0.5 + frac * 0.5)
return DATA.sample(frac=frac)
def _plot_data(frac=0.1):
time.sleep(0.5)
data = _load_data(frac)
return data.hvplot(x="time", y="price")
@pn.cache(per_session=True, ttl=60*60*24)
def _plot_data_cached(frac):
return _plot_data(frac)
# Create Widgets
fraction = pn.widgets.FloatSlider(value=0.1, start=0.1, end=1.0, step=0.1, name="Fraction of data")
duration = pn.widgets.StaticText(value="", name="Time to create plot")
use_cache = pn.widgets.Checkbox(value=False, name="Use Cache")
preload_cache = pn.widgets.Button(name="Preload Cache", button_type="primary", disabled=True)
clear_cache = pn.widgets.Button(name="Clear Cache", disabled=True)
preload_progress = pn.widgets.Progress(
name="Progress", active=False, value=0, max=100, sizing_mode="stretch_width", disabled=True
)
plot_panel = pn.pane.HoloViews(min_height=500, sizing_mode="stretch_both")
# Setup interactivity
def _clear_cache(*_):
_plot_data_cached.clear()
clear_cache.on_click(_clear_cache)
def _preload_cache(*_):
for index in range(0, 11, 1):
frac_ = round(index / 10, 1)
preload_progress.value = int(frac_ * 100)
_plot_data_cached(frac_)
preload_progress.value = 0
preload_cache.on_click(_preload_cache)
@pn.depends(frac=fraction, watch=True)
def _update_plot(frac):
start_counter = time.perf_counter()
frac = round(frac, 1)
if use_cache.value:
plot = _plot_data_cached(frac)
else:
plot = _plot_data(frac)
end_counter = time.perf_counter()
duration.value = str(round(end_counter - start_counter, 4)) + " seconds"
# Please note DiskCache does not cache the options
plot.opts(color=ACCENT_COLOR, responsive=True)
plot_panel.object = plot
@pn.depends(use_cache=use_cache, watch=True)
def _update_cache_widgets(use_cache): # pylint: disable=redefined-outer-name
disabled = not use_cache
preload_cache.disabled = disabled
clear_cache.disabled = disabled
preload_progress.disabled = disabled
# Layout the app
pn.Column(
pn.pane.Markdown(
"# Speed up slow functions with caching", sizing_mode="stretch_width"
),
fraction,
duration,
use_cache,
plot_panel,
pn.Row(preload_cache, clear_cache,),
preload_progress,
).servable()
pn.state.onload(lambda: fraction.param.trigger("value"))
await write_doc()
`
try {
const [docs_json, render_items, root_ids] = await self.pyodide.runPythonAsync(code)
self.postMessage({
type: 'render',
docs_json: docs_json,
render_items: render_items,
root_ids: root_ids
})
} catch(e) {
const traceback = `${e}`
const tblines = traceback.split('\n')
self.postMessage({
type: 'status',
msg: tblines[tblines.length-2]
});
throw e
}
}
self.onmessage = async (event) => {
const msg = event.data
if (msg.type === 'rendered') {
self.pyodide.runPythonAsync(`
from panel.io.state import state
from panel.io.pyodide import _link_docs_worker
_link_docs_worker(state.curdoc, sendPatch, setter='js')
`)
} else if (msg.type === 'patch') {
self.pyodide.globals.set('patch', msg.patch)
self.pyodide.runPythonAsync(`
state.curdoc.apply_json_patch(patch.to_py(), setter='js')
`)
self.postMessage({type: 'idle'})
} else if (msg.type === 'location') {
self.pyodide.globals.set('location', msg.location)
self.pyodide.runPythonAsync(`
import json
from panel.io.state import state
from panel.util import edit_readonly
if state.location:
loc_data = json.loads(location)
with edit_readonly(state.location):
state.location.param.update({
k: v for k, v in loc_data.items() if k in state.location.param
})
`)
}
}
startApplication() |