libre-code / app.py
mic3333's picture
Update app.py
86e4e85 verified
raw
history blame
12.2 kB
#!/usr/bin/env python3
"""
Plotly + Pyodide - Fixed Data Display Issue
"""
import gradio as gr
def create_pyodide_interface():
"""Create interface with fixed Plotly data handling"""
pyodide_html = '''
<div id="pyodide-container" style="border: 1px solid #ddd; padding: 15px; border-radius: 5px; margin: 10px 0;">
<div id="status" style="font-weight: bold; padding: 10px; background: #f0f0f0; border-radius: 3px;">
πŸ”„ Loading Pyodide + Plotly...
</div>
<div id="output" style="display:none; margin-top: 10px;">
<h4>Results:</h4>
<pre id="text-output" style="background: #f8f8f8; padding: 10px; border-radius: 3px; max-height: 200px; overflow-y: auto; white-space: pre-wrap;"></pre>
<div id="plots" style="margin-top: 15px;"></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 = null;
let ready = false;
let plotId = 0;
function updateStatus(msg, color = 'black') {
const statusEl = document.getElementById('status');
if (statusEl) {
statusEl.innerHTML = msg;
statusEl.style.color = color;
}
console.log('Status:', msg);
}
// Enhanced plot renderer with data debugging
window.renderPlotWithDebug = function(figureJson) {
try {
console.log('Received figure JSON:', figureJson.substring(0, 200) + '...');
plotId++;
const containerId = 'plot-' + plotId;
const plotsDiv = document.getElementById('plots');
if (!plotsDiv) {
console.error('Plots container not found');
return false;
}
// Parse the figure
const figDict = JSON.parse(figureJson);
console.log('Parsed figure keys:', Object.keys(figDict));
console.log('Data array length:', figDict.data ? figDict.data.length : 'No data');
if (figDict.data && figDict.data.length > 0) {
console.log('First trace:', figDict.data[0]);
console.log('First trace x:', figDict.data[0].x);
console.log('First trace y:', figDict.data[0].y);
}
// Create plot container
const plotWrapper = document.createElement('div');
plotWrapper.innerHTML = `
<div style="margin: 15px 0;">
<h5 style="margin: 10px 0;">πŸ“ˆ Plot ${plotId}</h5>
<div id="${containerId}" style="width: 100%; height: 500px; border: 1px solid #ccc; border-radius: 5px;"></div>
</div>
`;
plotsDiv.appendChild(plotWrapper);
// Enhanced layout with better defaults
const layout = figDict.layout || {};
layout.margin = layout.margin || {l: 50, r: 50, t: 50, b: 50};
layout.autosize = true;
// Create plot with config
const config = {
responsive: true,
displayModeBar: true,
displaylogo: false
};
Plotly.newPlot(containerId, figDict.data, layout, config);
console.log('Plot created successfully with ID:', containerId);
return true;
} catch (error) {
console.error('Plot rendering error:', error);
console.error('Error details:', error.message);
return false;
}
};
async function initPyodide() {
try {
updateStatus('πŸ”„ Loading Pyodide...', 'blue');
pyodide = await loadPyodide();
updateStatus('πŸ“¦ Installing packages...', 'blue');
await pyodide.loadPackage(['numpy', 'pandas', 'micropip']);
updateStatus('πŸ“ˆ Installing Plotly...', 'blue');
await pyodide.runPythonAsync(`
import micropip
await micropip.install('plotly')
`);
updateStatus('πŸ”§ Setting up integration...', 'blue');
// Python setup with enhanced debugging
pyodide.runPython(`
import json
from js import renderPlotWithDebug
def show_plot_debug(fig):
try:
print("=== PLOT DEBUG INFO ===")
# Convert to dict and inspect
fig_dict = fig.to_dict()
print(f"Figure has {len(fig_dict.get('data', []))} traces")
# Debug each trace
for i, trace in enumerate(fig_dict.get('data', [])):
print(f"Trace {i}: type={trace.get('type', 'unknown')}")
print(f" x data: {trace.get('x', 'missing')}")
print(f" y data: {trace.get('y', 'missing')}")
print(f" mode: {trace.get('mode', 'default')}")
# Convert to JSON for JavaScript
fig_json = json.dumps(fig_dict)
print(f"JSON length: {len(fig_json)} characters")
# Send to JavaScript
success = renderPlotWithDebug(fig_json)
if success:
print("βœ… Plot rendered successfully!")
else:
print("❌ Plot rendering failed")
print("=== END DEBUG INFO ===")
return success
except Exception as e:
print(f"❌ Plot error: {e}")
import traceback
traceback.print_exc()
return False
# Setup Plotly with debugging
try:
import plotly.graph_objects as go
import plotly.express as px
import numpy as np
# Test data creation
print("Testing data creation...")
test_x = [1, 2, 3, 4, 5]
test_y = [1, 4, 9, 16, 25]
print(f"Test data - x: {test_x}, y: {test_y}")
# Patch show method
original_show = go.Figure.show
go.Figure.show = lambda self, *args, **kwargs: show_plot_debug(self)
print("βœ… Plotly setup complete with debugging!")
except Exception as e:
print(f"❌ Plotly setup failed: {e}")
import traceback
traceback.print_exc()
print("πŸŽ‰ Environment ready for testing!")
`);
ready = true;
updateStatus('βœ… Ready with debug mode!', 'green');
document.getElementById('output').style.display = 'block';
document.getElementById('text-output').textContent = 'System ready! The debug info will help identify data issues.';
} catch (error) {
console.error('Init error:', error);
updateStatus('❌ Failed: ' + error.message, 'red');
}
}
async function executeUserCode(code) {
if (!ready) {
return 'Not ready. Wait for green status.';
}
try {
updateStatus('▢️ Executing with debug...', 'blue');
// Clear previous plots
document.getElementById('plots').innerHTML = '';
// Capture output
pyodide.runPython(`
import sys
from io import StringIO
old_stdout = sys.stdout
sys.stdout = capture = StringIO()
`);
// Execute code
let result = pyodide.runPython(code);
// Get output
let output = pyodide.runPython(`
sys.stdout = old_stdout
capture.getvalue()
`);
// Display
document.getElementById('text-output').textContent = output || 'Executed successfully';
updateStatus('βœ… Complete!', 'green');
return output || 'Success';
} catch (error) {
const errorMsg = 'Error: ' + error.toString();
document.getElementById('text-output').textContent = errorMsg;
updateStatus('❌ Error', 'red');
return errorMsg;
}
}
// Wait for CDNs and init
function waitForCDNs() {
if (typeof loadPyodide !== 'undefined' && typeof Plotly !== 'undefined') {
console.log('CDNs loaded, initializing...');
initPyodide();
} else {
setTimeout(waitForCDNs, 1000);
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', waitForCDNs);
} else {
waitForCDNs();
}
window.executeUserCode = executeUserCode;
window.checkReady = () => ready;
</script>
'''
return pyodide_html
# Gradio interface
with gr.Blocks() as demo:
gr.Markdown("# πŸ” Plotly Debug Version")
gr.Markdown("**Diagnose why data points aren't showing**")
pyodide_interface = gr.HTML(create_pyodide_interface())
with gr.Row():
with gr.Column():
code_input = gr.Textbox(
value="""# Debug Test - Simple Data
import plotly.graph_objects as go
import numpy as np
print("Creating simple test plot...")
# Explicit simple data
x_data = [1, 2, 3, 4, 5]
y_data = [2, 4, 6, 8, 10]
print(f"X data: {x_data}")
print(f"Y data: {y_data}")
# Create figure step by step
fig = go.Figure()
# Add trace with explicit parameters
fig.add_trace(go.Scatter(
x=x_data,
y=y_data,
mode='markers+lines',
name='Test Data',
marker=dict(
size=12,
color='red',
symbol='circle'
),
line=dict(
color='blue',
width=3
)
))
# Explicit layout
fig.update_layout(
title='Debug Test Plot',
xaxis=dict(title='X Values', range=[0, 6]),
yaxis=dict(title='Y Values', range=[0, 12]),
width=700,
height=500,
showlegend=True
)
print("Calling fig.show()...")
fig.show()""",
lines=20,
label="Debug Test Code"
)
execute_btn = gr.Button("πŸ” Execute Debug", variant="primary")
with gr.Column():
status_display = gr.Textbox(
label="Status",
interactive=False,
lines=4
)
check_btn = gr.Button("πŸ“Š Check")
# Simple test examples
gr.Markdown("""
### πŸ§ͺ Progressive Tests:
**Test 1 - Minimal:**
```python
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(x=[1,2,3], y=[1,2,3]))
fig.show()
```
**Test 2 - With NumPy:**
```python
import plotly.graph_objects as go
import numpy as np
x = np.array([1,2,3,4,5])
y = np.array([1,4,9,16,25])
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=y, mode='markers'))
fig.show()
```
**Test 3 - Express:**
```python
import plotly.express as px
import pandas as pd
df = pd.DataFrame({'x': [1,2,3], 'y': [1,4,9]})
fig = px.scatter(df, x='x', y='y')
fig.show()
```
""")
execute_btn.click(
fn=None,
inputs=[code_input],
outputs=[status_display],
js="(code) => window.executeUserCode ? window.executeUserCode(code) : 'Not ready'"
)
check_btn.click(
fn=None,
inputs=[],
outputs=[status_display],
js="() => window.checkReady ? (window.checkReady() ? 'βœ… Ready' : '⏳ Loading') : '❌ Error'"
)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860, share=False)