Spaces:
Sleeping
Sleeping
| #!/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) |