mic3333 commited on
Commit
86e4e85
Β·
verified Β·
1 Parent(s): dcae7f9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +196 -155
app.py CHANGED
@@ -1,22 +1,21 @@
1
  #!/usr/bin/env python3
2
  """
3
- Fixed Plotly + Pyodide Integration - No Syntax Errors
4
  """
5
 
6
  import gradio as gr
7
 
8
  def create_pyodide_interface():
9
- """Create a working Pyodide + Plotly interface with proper string escaping"""
10
 
11
- # Use proper string escaping to avoid syntax errors
12
  pyodide_html = '''
13
  <div id="pyodide-container" style="border: 1px solid #ddd; padding: 15px; border-radius: 5px; margin: 10px 0;">
14
  <div id="status" style="font-weight: bold; padding: 10px; background: #f0f0f0; border-radius: 3px;">
15
- πŸ”„ Initializing Pyodide + Plotly...
16
  </div>
17
  <div id="output" style="display:none; margin-top: 10px;">
18
  <h4>Results:</h4>
19
- <pre id="text-output" style="background: #f8f8f8; padding: 10px; border-radius: 3px; max-height: 200px; overflow-y: auto;"></pre>
20
  <div id="plots" style="margin-top: 15px;"></div>
21
  </div>
22
  </div>
@@ -38,49 +37,68 @@ def create_pyodide_interface():
38
  console.log('Status:', msg);
39
  }
40
 
41
- // Function to render Plotly from Python
42
- window.renderPlot = function(plotData, plotLayout) {
43
  try {
 
 
44
  plotId++;
45
  const containerId = 'plot-' + plotId;
46
  const plotsDiv = document.getElementById('plots');
47
 
48
- if (!plotsDiv) return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  // Create plot container
51
- const plotDiv = document.createElement('div');
52
- plotDiv.innerHTML = `
53
- <h5>πŸ“ˆ Plot ${plotId}</h5>
54
- <div id="${containerId}" style="width: 100%; height: 500px; border: 1px solid #ccc; margin: 10px 0;"></div>
 
 
55
  `;
56
- plotsDiv.appendChild(plotDiv);
57
 
58
- // Parse JSON if needed
59
- if (typeof plotData === 'string') plotData = JSON.parse(plotData);
60
- if (typeof plotLayout === 'string') plotLayout = JSON.parse(plotLayout);
 
61
 
62
- // Render with Plotly
63
- Plotly.newPlot(containerId, plotData, plotLayout, {responsive: true});
 
 
 
 
64
 
65
- console.log('Plot rendered:', containerId);
 
 
66
  return true;
67
 
68
  } catch (error) {
69
- console.error('Plot render error:', error);
 
70
  return false;
71
  }
72
  };
73
 
74
  async function initPyodide() {
75
  try {
76
- if (typeof loadPyodide === 'undefined') {
77
- throw new Error('Pyodide CDN failed to load');
78
- }
79
- if (typeof Plotly === 'undefined') {
80
- throw new Error('Plotly CDN failed to load');
81
- }
82
-
83
- updateStatus('πŸ”„ Loading Pyodide core...', 'blue');
84
  pyodide = await loadPyodide();
85
 
86
  updateStatus('πŸ“¦ Installing packages...', 'blue');
@@ -92,128 +110,145 @@ def create_pyodide_interface():
92
  await micropip.install('plotly')
93
  `);
94
 
95
- updateStatus('πŸ”§ Setting up Plotly integration...', 'blue');
96
 
97
- // Setup Python environment with PROPER string escaping
98
  pyodide.runPython(`
99
  import json
100
- from js import renderPlot
101
-
102
- # Global plot counter
103
- plot_count = 0
104
 
105
- def show_plot(fig):
106
- global plot_count
107
  try:
108
- # Convert figure to dict
 
 
109
  fig_dict = fig.to_dict()
 
 
 
 
 
 
 
 
110
 
111
- # Extract data and layout
112
- data = fig_dict.get('data', [])
113
- layout = fig_dict.get('layout', {})
114
 
115
- # Call JavaScript render function
116
- success = renderPlot(json.dumps(data), json.dumps(layout))
117
 
118
  if success:
119
- plot_count += 1
120
- print(f"Plot {plot_count} displayed successfully!")
121
- return True
122
  else:
123
- print("Plot rendering failed")
124
- return False
125
-
 
 
126
  except Exception as e:
127
- print(f"Plot error: {e}")
 
 
128
  return False
129
 
130
- # Patch Plotly
131
  try:
132
  import plotly.graph_objects as go
133
  import plotly.express as px
 
134
 
135
- # Replace show method
 
 
 
 
 
 
136
  original_show = go.Figure.show
137
- go.Figure.show = lambda self, *args, **kwargs: show_plot(self)
138
 
139
- print("Plotly patched successfully!")
140
 
141
- except ImportError as e:
142
- print(f"Plotly import failed: {e}")
 
 
143
 
144
- print("Environment setup complete!")
145
  `);
146
 
147
  ready = true;
148
- updateStatus('βœ… Plotly + Pyodide ready!', 'green');
149
 
150
  document.getElementById('output').style.display = 'block';
151
- document.getElementById('text-output').textContent = 'Ready! Try executing some Plotly code.';
152
 
153
  } catch (error) {
154
- console.error('Initialization failed:', error);
155
  updateStatus('❌ Failed: ' + error.message, 'red');
156
  }
157
  }
158
 
159
  async function executeUserCode(code) {
160
  if (!ready) {
161
- return 'System not ready. Please wait for green status.';
162
  }
163
 
164
  try {
165
- updateStatus('▢️ Running...', 'blue');
 
 
 
166
 
167
- // Capture stdout
168
  pyodide.runPython(`
169
  import sys
170
  from io import StringIO
171
  old_stdout = sys.stdout
172
- sys.stdout = output_capture = StringIO()
173
  `);
174
 
175
- // Execute user code
176
  let result = pyodide.runPython(code);
177
 
178
- // Get captured output
179
- let stdout = pyodide.runPython(`
180
  sys.stdout = old_stdout
181
- output_capture.getvalue()
182
  `);
183
 
184
- // Display output
185
- document.getElementById('text-output').textContent = stdout || 'Code executed successfully';
186
  updateStatus('βœ… Complete!', 'green');
187
 
188
- return stdout || 'Success';
189
 
190
  } catch (error) {
191
  const errorMsg = 'Error: ' + error.toString();
192
  document.getElementById('text-output').textContent = errorMsg;
193
- updateStatus('❌ Error occurred', 'red');
194
  return errorMsg;
195
  }
196
  }
197
 
198
- // Initialize when both CDNs are loaded
199
- function checkAndInit() {
200
  if (typeof loadPyodide !== 'undefined' && typeof Plotly !== 'undefined') {
201
- console.log('Both CDNs loaded, starting initialization');
202
  initPyodide();
203
  } else {
204
- console.log('Waiting for CDNs...');
205
- setTimeout(checkAndInit, 1000);
206
  }
207
  }
208
 
209
- // Start when DOM is ready
210
  if (document.readyState === 'loading') {
211
- document.addEventListener('DOMContentLoaded', checkAndInit);
212
  } else {
213
- checkAndInit();
214
  }
215
 
216
- // Make functions globally available
217
  window.executeUserCode = executeUserCode;
218
  window.checkReady = () => ready;
219
 
@@ -222,116 +257,122 @@ output_capture.getvalue()
222
 
223
  return pyodide_html
224
 
225
- # Create Gradio app
226
- with gr.Blocks(title="Fixed Plotly Pyodide") as demo:
227
- gr.Markdown("# πŸπŸ“ˆ Fixed Plotly + Pyodide")
228
- gr.Markdown("**No more syntax errors!** Interactive Plotly charts in browser.")
229
 
230
- # Pyodide interface
231
  pyodide_interface = gr.HTML(create_pyodide_interface())
232
 
233
  with gr.Row():
234
- with gr.Column(scale=2):
235
  code_input = gr.Textbox(
236
- value="""# Working Plotly Example
237
  import plotly.graph_objects as go
238
  import numpy as np
239
 
240
- print("Creating Plotly chart...")
 
 
 
 
241
 
242
- # Simple data
243
- x = np.array([1, 2, 3, 4, 5])
244
- y = x ** 2
245
 
246
- # Create figure
247
  fig = go.Figure()
 
 
248
  fig.add_trace(go.Scatter(
249
- x=x,
250
- y=y,
251
- mode='lines+markers',
252
- name='xΒ²',
253
- line=dict(color='blue', width=3),
254
- marker=dict(size=8, color='red')
 
 
 
 
 
 
 
255
  ))
256
 
 
257
  fig.update_layout(
258
- title='Interactive Quadratic Function',
259
- xaxis_title='X values',
260
- yaxis_title='Y values',
261
- template='plotly_white'
 
 
262
  )
263
 
264
- fig.show()
265
- print("Chart should appear above! βœ…")""",
266
- lines=18,
267
- label="Python Code"
268
  )
269
 
270
- execute_btn = gr.Button("πŸš€ Execute Code", variant="primary", size="lg")
271
 
272
- with gr.Column(scale=1):
273
  status_display = gr.Textbox(
274
- label="Execution Status",
275
  interactive=False,
276
- lines=3
277
  )
278
 
279
- check_btn = gr.Button("πŸ“Š Check Status")
280
-
281
- gr.Markdown("""
282
- ### πŸ“‹ Quick Tests:
283
- 1. **Wait for green status**
284
- 2. **Run the default example**
285
- 3. **Look for interactive chart**
286
- 4. **Check browser console** if issues
287
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
 
289
- # Button handlers with simple JS
290
  execute_btn.click(
291
  fn=None,
292
  inputs=[code_input],
293
  outputs=[status_display],
294
- js="""
295
- function(code) {
296
- try {
297
- if (window.executeUserCode) {
298
- return window.executeUserCode(code);
299
- } else {
300
- return 'Execute function not available';
301
- }
302
- } catch (error) {
303
- return 'JS Error: ' + error.message;
304
- }
305
- }
306
- """
307
  )
308
 
309
  check_btn.click(
310
  fn=None,
311
  inputs=[],
312
  outputs=[status_display],
313
- js="""
314
- function() {
315
- try {
316
- if (window.checkReady) {
317
- return window.checkReady() ? 'βœ… System Ready' : '⏳ Still Loading';
318
- } else {
319
- return '❌ Check function not available';
320
- }
321
- } catch (error) {
322
- return 'Status Error: ' + error.message;
323
- }
324
- }
325
- """
326
  )
327
 
328
  if __name__ == "__main__":
329
- print("πŸš€ Starting Fixed Plotly + Pyodide Server...")
330
- print("πŸ“ Access at: http://localhost:7860")
331
-
332
- demo.launch(
333
- server_name="0.0.0.0",
334
- server_port=7860,
335
- share=False,
336
- debug=True
337
- )
 
1
  #!/usr/bin/env python3
2
  """
3
+ Plotly + Pyodide - Fixed Data Display Issue
4
  """
5
 
6
  import gradio as gr
7
 
8
  def create_pyodide_interface():
9
+ """Create interface with fixed Plotly data handling"""
10
 
 
11
  pyodide_html = '''
12
  <div id="pyodide-container" style="border: 1px solid #ddd; padding: 15px; border-radius: 5px; margin: 10px 0;">
13
  <div id="status" style="font-weight: bold; padding: 10px; background: #f0f0f0; border-radius: 3px;">
14
+ πŸ”„ Loading Pyodide + Plotly...
15
  </div>
16
  <div id="output" style="display:none; margin-top: 10px;">
17
  <h4>Results:</h4>
18
+ <pre id="text-output" style="background: #f8f8f8; padding: 10px; border-radius: 3px; max-height: 200px; overflow-y: auto; white-space: pre-wrap;"></pre>
19
  <div id="plots" style="margin-top: 15px;"></div>
20
  </div>
21
  </div>
 
37
  console.log('Status:', msg);
38
  }
39
 
40
+ // Enhanced plot renderer with data debugging
41
+ window.renderPlotWithDebug = function(figureJson) {
42
  try {
43
+ console.log('Received figure JSON:', figureJson.substring(0, 200) + '...');
44
+
45
  plotId++;
46
  const containerId = 'plot-' + plotId;
47
  const plotsDiv = document.getElementById('plots');
48
 
49
+ if (!plotsDiv) {
50
+ console.error('Plots container not found');
51
+ return false;
52
+ }
53
+
54
+ // Parse the figure
55
+ const figDict = JSON.parse(figureJson);
56
+ console.log('Parsed figure keys:', Object.keys(figDict));
57
+ console.log('Data array length:', figDict.data ? figDict.data.length : 'No data');
58
+
59
+ if (figDict.data && figDict.data.length > 0) {
60
+ console.log('First trace:', figDict.data[0]);
61
+ console.log('First trace x:', figDict.data[0].x);
62
+ console.log('First trace y:', figDict.data[0].y);
63
+ }
64
 
65
  // Create plot container
66
+ const plotWrapper = document.createElement('div');
67
+ plotWrapper.innerHTML = `
68
+ <div style="margin: 15px 0;">
69
+ <h5 style="margin: 10px 0;">πŸ“ˆ Plot ${plotId}</h5>
70
+ <div id="${containerId}" style="width: 100%; height: 500px; border: 1px solid #ccc; border-radius: 5px;"></div>
71
+ </div>
72
  `;
73
+ plotsDiv.appendChild(plotWrapper);
74
 
75
+ // Enhanced layout with better defaults
76
+ const layout = figDict.layout || {};
77
+ layout.margin = layout.margin || {l: 50, r: 50, t: 50, b: 50};
78
+ layout.autosize = true;
79
 
80
+ // Create plot with config
81
+ const config = {
82
+ responsive: true,
83
+ displayModeBar: true,
84
+ displaylogo: false
85
+ };
86
 
87
+ Plotly.newPlot(containerId, figDict.data, layout, config);
88
+
89
+ console.log('Plot created successfully with ID:', containerId);
90
  return true;
91
 
92
  } catch (error) {
93
+ console.error('Plot rendering error:', error);
94
+ console.error('Error details:', error.message);
95
  return false;
96
  }
97
  };
98
 
99
  async function initPyodide() {
100
  try {
101
+ updateStatus('πŸ”„ Loading Pyodide...', 'blue');
 
 
 
 
 
 
 
102
  pyodide = await loadPyodide();
103
 
104
  updateStatus('πŸ“¦ Installing packages...', 'blue');
 
110
  await micropip.install('plotly')
111
  `);
112
 
113
+ updateStatus('πŸ”§ Setting up integration...', 'blue');
114
 
115
+ // Python setup with enhanced debugging
116
  pyodide.runPython(`
117
  import json
118
+ from js import renderPlotWithDebug
 
 
 
119
 
120
+ def show_plot_debug(fig):
 
121
  try:
122
+ print("=== PLOT DEBUG INFO ===")
123
+
124
+ # Convert to dict and inspect
125
  fig_dict = fig.to_dict()
126
+ print(f"Figure has {len(fig_dict.get('data', []))} traces")
127
+
128
+ # Debug each trace
129
+ for i, trace in enumerate(fig_dict.get('data', [])):
130
+ print(f"Trace {i}: type={trace.get('type', 'unknown')}")
131
+ print(f" x data: {trace.get('x', 'missing')}")
132
+ print(f" y data: {trace.get('y', 'missing')}")
133
+ print(f" mode: {trace.get('mode', 'default')}")
134
 
135
+ # Convert to JSON for JavaScript
136
+ fig_json = json.dumps(fig_dict)
137
+ print(f"JSON length: {len(fig_json)} characters")
138
 
139
+ # Send to JavaScript
140
+ success = renderPlotWithDebug(fig_json)
141
 
142
  if success:
143
+ print("βœ… Plot rendered successfully!")
 
 
144
  else:
145
+ print("❌ Plot rendering failed")
146
+
147
+ print("=== END DEBUG INFO ===")
148
+ return success
149
+
150
  except Exception as e:
151
+ print(f"❌ Plot error: {e}")
152
+ import traceback
153
+ traceback.print_exc()
154
  return False
155
 
156
+ # Setup Plotly with debugging
157
  try:
158
  import plotly.graph_objects as go
159
  import plotly.express as px
160
+ import numpy as np
161
 
162
+ # Test data creation
163
+ print("Testing data creation...")
164
+ test_x = [1, 2, 3, 4, 5]
165
+ test_y = [1, 4, 9, 16, 25]
166
+ print(f"Test data - x: {test_x}, y: {test_y}")
167
+
168
+ # Patch show method
169
  original_show = go.Figure.show
170
+ go.Figure.show = lambda self, *args, **kwargs: show_plot_debug(self)
171
 
172
+ print("βœ… Plotly setup complete with debugging!")
173
 
174
+ except Exception as e:
175
+ print(f"❌ Plotly setup failed: {e}")
176
+ import traceback
177
+ traceback.print_exc()
178
 
179
+ print("πŸŽ‰ Environment ready for testing!")
180
  `);
181
 
182
  ready = true;
183
+ updateStatus('βœ… Ready with debug mode!', 'green');
184
 
185
  document.getElementById('output').style.display = 'block';
186
+ document.getElementById('text-output').textContent = 'System ready! The debug info will help identify data issues.';
187
 
188
  } catch (error) {
189
+ console.error('Init error:', error);
190
  updateStatus('❌ Failed: ' + error.message, 'red');
191
  }
192
  }
193
 
194
  async function executeUserCode(code) {
195
  if (!ready) {
196
+ return 'Not ready. Wait for green status.';
197
  }
198
 
199
  try {
200
+ updateStatus('▢️ Executing with debug...', 'blue');
201
+
202
+ // Clear previous plots
203
+ document.getElementById('plots').innerHTML = '';
204
 
205
+ // Capture output
206
  pyodide.runPython(`
207
  import sys
208
  from io import StringIO
209
  old_stdout = sys.stdout
210
+ sys.stdout = capture = StringIO()
211
  `);
212
 
213
+ // Execute code
214
  let result = pyodide.runPython(code);
215
 
216
+ // Get output
217
+ let output = pyodide.runPython(`
218
  sys.stdout = old_stdout
219
+ capture.getvalue()
220
  `);
221
 
222
+ // Display
223
+ document.getElementById('text-output').textContent = output || 'Executed successfully';
224
  updateStatus('βœ… Complete!', 'green');
225
 
226
+ return output || 'Success';
227
 
228
  } catch (error) {
229
  const errorMsg = 'Error: ' + error.toString();
230
  document.getElementById('text-output').textContent = errorMsg;
231
+ updateStatus('❌ Error', 'red');
232
  return errorMsg;
233
  }
234
  }
235
 
236
+ // Wait for CDNs and init
237
+ function waitForCDNs() {
238
  if (typeof loadPyodide !== 'undefined' && typeof Plotly !== 'undefined') {
239
+ console.log('CDNs loaded, initializing...');
240
  initPyodide();
241
  } else {
242
+ setTimeout(waitForCDNs, 1000);
 
243
  }
244
  }
245
 
 
246
  if (document.readyState === 'loading') {
247
+ document.addEventListener('DOMContentLoaded', waitForCDNs);
248
  } else {
249
+ waitForCDNs();
250
  }
251
 
 
252
  window.executeUserCode = executeUserCode;
253
  window.checkReady = () => ready;
254
 
 
257
 
258
  return pyodide_html
259
 
260
+ # Gradio interface
261
+ with gr.Blocks() as demo:
262
+ gr.Markdown("# πŸ” Plotly Debug Version")
263
+ gr.Markdown("**Diagnose why data points aren't showing**")
264
 
 
265
  pyodide_interface = gr.HTML(create_pyodide_interface())
266
 
267
  with gr.Row():
268
+ with gr.Column():
269
  code_input = gr.Textbox(
270
+ value="""# Debug Test - Simple Data
271
  import plotly.graph_objects as go
272
  import numpy as np
273
 
274
+ print("Creating simple test plot...")
275
+
276
+ # Explicit simple data
277
+ x_data = [1, 2, 3, 4, 5]
278
+ y_data = [2, 4, 6, 8, 10]
279
 
280
+ print(f"X data: {x_data}")
281
+ print(f"Y data: {y_data}")
 
282
 
283
+ # Create figure step by step
284
  fig = go.Figure()
285
+
286
+ # Add trace with explicit parameters
287
  fig.add_trace(go.Scatter(
288
+ x=x_data,
289
+ y=y_data,
290
+ mode='markers+lines',
291
+ name='Test Data',
292
+ marker=dict(
293
+ size=12,
294
+ color='red',
295
+ symbol='circle'
296
+ ),
297
+ line=dict(
298
+ color='blue',
299
+ width=3
300
+ )
301
  ))
302
 
303
+ # Explicit layout
304
  fig.update_layout(
305
+ title='Debug Test Plot',
306
+ xaxis=dict(title='X Values', range=[0, 6]),
307
+ yaxis=dict(title='Y Values', range=[0, 12]),
308
+ width=700,
309
+ height=500,
310
+ showlegend=True
311
  )
312
 
313
+ print("Calling fig.show()...")
314
+ fig.show()""",
315
+ lines=20,
316
+ label="Debug Test Code"
317
  )
318
 
319
+ execute_btn = gr.Button("πŸ” Execute Debug", variant="primary")
320
 
321
+ with gr.Column():
322
  status_display = gr.Textbox(
323
+ label="Status",
324
  interactive=False,
325
+ lines=4
326
  )
327
 
328
+ check_btn = gr.Button("πŸ“Š Check")
329
+
330
+ # Simple test examples
331
+ gr.Markdown("""
332
+ ### πŸ§ͺ Progressive Tests:
333
+
334
+ **Test 1 - Minimal:**
335
+ ```python
336
+ import plotly.graph_objects as go
337
+ fig = go.Figure()
338
+ fig.add_trace(go.Scatter(x=[1,2,3], y=[1,2,3]))
339
+ fig.show()
340
+ ```
341
+
342
+ **Test 2 - With NumPy:**
343
+ ```python
344
+ import plotly.graph_objects as go
345
+ import numpy as np
346
+ x = np.array([1,2,3,4,5])
347
+ y = np.array([1,4,9,16,25])
348
+ fig = go.Figure()
349
+ fig.add_trace(go.Scatter(x=x, y=y, mode='markers'))
350
+ fig.show()
351
+ ```
352
+
353
+ **Test 3 - Express:**
354
+ ```python
355
+ import plotly.express as px
356
+ import pandas as pd
357
+ df = pd.DataFrame({'x': [1,2,3], 'y': [1,4,9]})
358
+ fig = px.scatter(df, x='x', y='y')
359
+ fig.show()
360
+ ```
361
+ """)
362
 
 
363
  execute_btn.click(
364
  fn=None,
365
  inputs=[code_input],
366
  outputs=[status_display],
367
+ js="(code) => window.executeUserCode ? window.executeUserCode(code) : 'Not ready'"
 
 
 
 
 
 
 
 
 
 
 
 
368
  )
369
 
370
  check_btn.click(
371
  fn=None,
372
  inputs=[],
373
  outputs=[status_display],
374
+ js="() => window.checkReady ? (window.checkReady() ? 'βœ… Ready' : '⏳ Loading') : '❌ Error'"
 
 
 
 
 
 
 
 
 
 
 
 
375
  )
376
 
377
  if __name__ == "__main__":
378
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=False)