libre-code / app.py
mic3333's picture
Update app.py
b4d9d47 verified
#!/usr/bin/env python3
"""
Minimal Working Plotly - Simple and Clean
"""
import gradio as gr
def create_interface():
html = '''
<div style="border: 1px solid #ddd; padding: 20px; border-radius: 5px;">
<div id="status">πŸ”„ Loading...</div>
<div id="output" style="display:none; margin-top: 20px;">
<pre id="text" style="background: #f5f5f5; padding: 10px; max-height: 150px; overflow-y: auto;"></pre>
<div id="plots"></div>
</div>
</div>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script src="https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.js"></script>
<script>
let pyodide, ready = false, plotNum = 0;
function status(msg, color = 'black') {
document.getElementById('status').innerHTML = msg;
document.getElementById('status').style.color = color;
}
window.makePlot = function(data, layout) {
const id = 'plot' + (++plotNum);
const div = document.createElement('div');
div.innerHTML = `<h4>Plot ${plotNum}</h4><div id="${id}" style="width:100%; height:400px; border:1px solid #ccc;"></div>`;
document.getElementById('plots').appendChild(div);
Plotly.newPlot(id, JSON.parse(data), JSON.parse(layout));
return true;
};
async function init() {
status('Loading...', 'blue');
pyodide = await loadPyodide();
await pyodide.loadPackage(['numpy', 'pandas', 'micropip']);
await pyodide.runPythonAsync('import micropip; await micropip.install("plotly")');
pyodide.runPython(`
import json, numpy as np
from js import makePlot
def show(fig):
d = fig.to_dict()
# Convert numpy arrays to lists
for trace in d.get('data', []):
if 'x' in trace and hasattr(trace['x'], 'tolist'):
trace['x'] = trace['x'].tolist()
if 'y' in trace and hasattr(trace['y'], 'tolist'):
trace['y'] = trace['y'].tolist()
makePlot(json.dumps(d['data']), json.dumps(d.get('layout', {})))
print("Plot created!")
import plotly.graph_objects as go
import plotly.express as px
go.Figure.show = lambda self: show(self)
`);
ready = true;
status('βœ… Ready!', 'green');
document.getElementById('output').style.display = 'block';
document.getElementById('text').textContent = 'Ready to plot!';
}
async function run(code) {
if (!ready) return 'Not ready';
document.getElementById('plots').innerHTML = '';
pyodide.runPython(`
import sys
from io import StringIO
old = sys.stdout
sys.stdout = cap = StringIO()
`);
pyodide.runPython(code);
const output = pyodide.runPython('sys.stdout = old; cap.getvalue()');
document.getElementById('text').textContent = output || 'Done';
return output || 'Success';
}
// Start
setTimeout(() => {
if (typeof loadPyodide !== 'undefined' && typeof Plotly !== 'undefined') {
init();
}
}, 1000);
window.run = run;
</script>
'''
return html
with gr.Blocks() as demo:
gr.Markdown("# πŸ“Š Simple Plotly")
interface = gr.HTML(create_interface())
with gr.Row():
code = gr.Textbox(
value="""# Test 1: Graph Objects
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(x=[1,2,3,4], y=[1,4,9,16], mode='markers+lines'))
fig.show()
# Test 2: Express
import plotly.express as px
import pandas as pd
df = pd.DataFrame({'x': [1,2,3,4], 'y': [1,4,9,16]})
fig = px.scatter(df, x='x', y='y')
fig.show()""",
lines=10,
label="Code"
)
result = gr.Textbox(label="Result", lines=2, interactive=False)
btn = gr.Button("▢️ Run")
btn.click(
fn=None,
inputs=[code],
outputs=[result],
js="(code) => window.run ? window.run(code) : 'Loading...'"
)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)