mic3333 commited on
Commit
7167a40
Β·
verified Β·
1 Parent(s): 6d82cbd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +92 -164
app.py CHANGED
@@ -1,12 +1,12 @@
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;">
@@ -37,61 +37,36 @@ def create_pyodide_interface():
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
  };
@@ -112,94 +87,68 @@ def create_pyodide_interface():
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_fixed(fig):
121
  try:
122
- print("=== CONVERTING NUMPY TO LISTS ===")
123
-
124
- # Get figure dict
125
  fig_dict = fig.to_dict()
126
 
127
- # Fix NumPy array serialization issue
128
  for trace in fig_dict.get('data', []):
129
- # Convert x data if it's a NumPy array
130
  if isinstance(trace.get('x'), dict) and 'bdata' in trace.get('x', {}):
131
- print("Converting x data from NumPy binary to list...")
132
- # Get the original data from the figure object
133
  for fig_trace in fig.data:
134
  if hasattr(fig_trace, 'x') and hasattr(fig_trace.x, 'tolist'):
135
  trace['x'] = fig_trace.x.tolist()
136
- print(f"X converted: {trace['x']}")
137
  break
138
 
139
- # Convert y data if it's a NumPy array
140
  if isinstance(trace.get('y'), dict) and 'bdata' in trace.get('y', {}):
141
- print("Converting y data from NumPy binary to list...")
142
  for fig_trace in fig.data:
143
  if hasattr(fig_trace, 'y') and hasattr(fig_trace.y, 'tolist'):
144
  trace['y'] = fig_trace.y.tolist()
145
- print(f"Y converted: {trace['y']}")
146
  break
147
 
148
- # Now the data should be proper lists
149
- print(f"Figure has {len(fig_dict.get('data', []))} traces")
150
- for i, trace in enumerate(fig_dict.get('data', [])):
151
- print(f"Trace {i}: x={trace.get('x')}, y={trace.get('y')}")
152
-
153
- # Convert to JSON
154
  fig_json = json.dumps(fig_dict)
155
-
156
- # Send to JavaScript
157
- success = renderPlotWithDebug(fig_json)
158
 
159
  if success:
160
- print("βœ… Plot with converted data rendered!")
161
  else:
162
- print("❌ Plot rendering still failed")
163
-
164
  return success
165
 
166
  except Exception as e:
167
  print(f"❌ Plot error: {e}")
168
- import traceback
169
- traceback.print_exc()
170
  return False
171
 
172
- # Setup Plotly with debugging
173
  try:
174
  import plotly.graph_objects as go
175
  import plotly.express as px
176
  import numpy as np
177
 
178
- # Test data creation
179
- print("Testing data creation...")
180
- test_x = [1, 2, 3, 4, 5]
181
- test_y = [1, 4, 9, 16, 25]
182
- print(f"Test data - x: {test_x}, y: {test_y}")
183
 
184
- # Patch show method
185
- original_show = go.Figure.show
186
- go.Figure.show = lambda self, *args, **kwargs: show_plot_debug(self)
187
-
188
- print("βœ… Plotly setup complete with debugging!")
189
 
190
  except Exception as e:
191
- print(f"❌ Plotly setup failed: {e}")
192
- import traceback
193
- traceback.print_exc()
194
 
195
- print("πŸŽ‰ Environment ready for testing!")
196
  `);
197
 
198
  ready = true;
199
- updateStatus('βœ… Ready with debug mode!', 'green');
200
 
201
  document.getElementById('output').style.display = 'block';
202
- document.getElementById('text-output').textContent = 'System ready! The debug info will help identify data issues.';
203
 
204
  } catch (error) {
205
  console.error('Init error:', error);
@@ -207,15 +156,13 @@ print("πŸŽ‰ Environment ready for testing!")
207
  }
208
  }
209
 
210
- async function executeUserCode(code) {
211
- if (!ready) {
212
- return 'Not ready. Wait for green status.';
213
- }
214
 
215
  try {
216
- updateStatus('▢️ Executing with debug...', 'blue');
217
 
218
- // Clear previous plots
219
  document.getElementById('plots').innerHTML = '';
220
 
221
  // Capture output
@@ -226,8 +173,8 @@ old_stdout = sys.stdout
226
  sys.stdout = capture = StringIO()
227
  `);
228
 
229
- // Execute code
230
- let result = pyodide.runPython(code);
231
 
232
  // Get output
233
  let output = pyodide.runPython(`
@@ -235,37 +182,31 @@ sys.stdout = old_stdout
235
  capture.getvalue()
236
  `);
237
 
238
- // Display
239
- document.getElementById('text-output').textContent = output || 'Executed successfully';
240
- updateStatus('βœ… Complete!', 'green');
241
 
242
  return output || 'Success';
243
 
244
  } catch (error) {
245
- const errorMsg = 'Error: ' + error.toString();
246
- document.getElementById('text-output').textContent = errorMsg;
247
  updateStatus('❌ Error', 'red');
248
- return errorMsg;
249
  }
250
  }
251
 
252
- // Wait for CDNs and init
253
- function waitForCDNs() {
254
  if (typeof loadPyodide !== 'undefined' && typeof Plotly !== 'undefined') {
255
- console.log('CDNs loaded, initializing...');
256
  initPyodide();
257
  } else {
258
- setTimeout(waitForCDNs, 1000);
259
  }
260
  }
261
 
262
- if (document.readyState === 'loading') {
263
- document.addEventListener('DOMContentLoaded', waitForCDNs);
264
- } else {
265
- waitForCDNs();
266
- }
267
 
268
- window.executeUserCode = executeUserCode;
269
  window.checkReady = () => ready;
270
 
271
  </script>
@@ -273,105 +214,91 @@ capture.getvalue()
273
 
274
  return pyodide_html
275
 
276
- # Gradio interface
277
  with gr.Blocks() as demo:
278
- gr.Markdown("# πŸ” Plotly Debug Version")
279
- gr.Markdown("**Diagnose why data points aren't showing**")
280
 
281
  pyodide_interface = gr.HTML(create_pyodide_interface())
282
 
283
  with gr.Row():
284
  with gr.Column():
285
  code_input = gr.Textbox(
286
- value="""# Debug Test - Simple Data
287
  import plotly.graph_objects as go
288
  import numpy as np
289
 
290
- print("Creating simple test plot...")
291
 
292
- # Explicit simple data
293
- x_data = [1, 2, 3, 4, 5]
294
- y_data = [2, 4, 6, 8, 10]
295
 
296
- print(f"X data: {x_data}")
297
- print(f"Y data: {y_data}")
298
 
299
- # Create figure step by step
300
  fig = go.Figure()
301
-
302
- # Add trace with explicit parameters
303
  fig.add_trace(go.Scatter(
304
- x=x_data,
305
- y=y_data,
306
  mode='markers+lines',
307
- name='Test Data',
308
- marker=dict(
309
- size=12,
310
- color='red',
311
- symbol='circle'
312
- ),
313
- line=dict(
314
- color='blue',
315
- width=3
316
- )
317
  ))
318
 
319
- # Explicit layout
320
  fig.update_layout(
321
- title='Debug Test Plot',
322
- xaxis=dict(title='X Values', range=[0, 6]),
323
- yaxis=dict(title='Y Values', range=[0, 12]),
324
- width=700,
325
- height=500,
326
- showlegend=True
327
  )
328
 
329
- print("Calling fig.show()...")
330
- fig.show()""",
331
- lines=20,
332
- label="Debug Test Code"
333
  )
334
 
335
- execute_btn = gr.Button("πŸ” Execute Debug", variant="primary")
336
 
337
  with gr.Column():
338
  status_display = gr.Textbox(
339
  label="Status",
340
  interactive=False,
341
- lines=4
342
  )
343
 
344
  check_btn = gr.Button("πŸ“Š Check")
345
 
346
- # Simple test examples
347
  gr.Markdown("""
348
- ### πŸ§ͺ Progressive Tests:
 
 
 
 
 
 
349
 
350
- **Test 1 - Minimal:**
351
  ```python
352
- import plotly.graph_objects as go
353
- fig = go.Figure()
354
- fig.add_trace(go.Scatter(x=[1,2,3], y=[1,2,3]))
 
355
  fig.show()
356
  ```
357
 
358
- **Test 2 - With NumPy:**
359
  ```python
360
  import plotly.graph_objects as go
361
  import numpy as np
362
- x = np.array([1,2,3,4,5])
363
- y = np.array([1,4,9,16,25])
364
- fig = go.Figure()
365
- fig.add_trace(go.Scatter(x=x, y=y, mode='markers'))
366
- fig.show()
367
- ```
368
 
369
- **Test 3 - Express:**
370
- ```python
371
- import plotly.express as px
372
- import pandas as pd
373
- df = pd.DataFrame({'x': [1,2,3], 'y': [1,4,9]})
374
- fig = px.scatter(df, x='x', y='y')
375
  fig.show()
376
  ```
377
  """)
@@ -380,7 +307,7 @@ fig.show()""",
380
  fn=None,
381
  inputs=[code_input],
382
  outputs=[status_display],
383
- js="(code) => window.executeUserCode ? window.executeUserCode(code) : 'Not ready'"
384
  )
385
 
386
  check_btn.click(
@@ -391,4 +318,5 @@ fig.show()""",
391
  )
392
 
393
  if __name__ == "__main__":
 
394
  demo.launch(server_name="0.0.0.0", server_port=7860, share=False)
 
1
  #!/usr/bin/env python3
2
  """
3
+ Final Working Plotly + Pyodide - NumPy Array Fix
4
  """
5
 
6
  import gradio as gr
7
 
8
  def create_pyodide_interface():
9
+ """Create the final working interface"""
10
 
11
  pyodide_html = '''
12
  <div id="pyodide-container" style="border: 1px solid #ddd; padding: 15px; border-radius: 5px; margin: 10px 0;">
 
37
  console.log('Status:', msg);
38
  }
39
 
40
+ // Simple, reliable plot renderer
41
+ window.renderPlot = function(figureJson) {
42
  try {
 
 
43
  plotId++;
44
  const containerId = 'plot-' + plotId;
45
  const plotsDiv = document.getElementById('plots');
46
 
47
+ if (!plotsDiv) return false;
 
 
 
48
 
49
+ // Parse figure
50
  const figDict = JSON.parse(figureJson);
 
 
 
 
 
 
 
 
51
 
52
+ // Create container
53
  const plotWrapper = document.createElement('div');
54
  plotWrapper.innerHTML = `
55
  <div style="margin: 15px 0;">
56
+ <h5>πŸ“ˆ Plot ${plotId}</h5>
57
  <div id="${containerId}" style="width: 100%; height: 500px; border: 1px solid #ccc; border-radius: 5px;"></div>
58
  </div>
59
  `;
60
  plotsDiv.appendChild(plotWrapper);
61
 
62
+ // Render plot
63
+ Plotly.newPlot(containerId, figDict.data, figDict.layout, {responsive: true});
 
 
 
 
 
 
 
 
 
64
 
65
+ console.log('Plot rendered:', containerId);
 
 
66
  return true;
67
 
68
  } catch (error) {
69
+ console.error('Plot error:', error);
 
70
  return false;
71
  }
72
  };
 
87
 
88
  updateStatus('πŸ”§ Setting up integration...', 'blue');
89
 
 
90
  pyodide.runPython(`
91
  import json
92
+ from js import renderPlot
93
 
94
+ def show_plot(fig):
95
  try:
96
+ # Convert figure to dict
 
 
97
  fig_dict = fig.to_dict()
98
 
99
+ # Fix NumPy array serialization
100
  for trace in fig_dict.get('data', []):
101
+ # Convert x data from NumPy binary to list
102
  if isinstance(trace.get('x'), dict) and 'bdata' in trace.get('x', {}):
 
 
103
  for fig_trace in fig.data:
104
  if hasattr(fig_trace, 'x') and hasattr(fig_trace.x, 'tolist'):
105
  trace['x'] = fig_trace.x.tolist()
 
106
  break
107
 
108
+ # Convert y data from NumPy binary to list
109
  if isinstance(trace.get('y'), dict) and 'bdata' in trace.get('y', {}):
 
110
  for fig_trace in fig.data:
111
  if hasattr(fig_trace, 'y') and hasattr(fig_trace.y, 'tolist'):
112
  trace['y'] = fig_trace.y.tolist()
 
113
  break
114
 
115
+ # Convert to JSON and render
 
 
 
 
 
116
  fig_json = json.dumps(fig_dict)
117
+ success = renderPlot(fig_json)
 
 
118
 
119
  if success:
120
+ print("βœ… Plot displayed successfully!")
121
  else:
122
+ print("❌ Plot rendering failed")
123
+
124
  return success
125
 
126
  except Exception as e:
127
  print(f"❌ Plot error: {e}")
 
 
128
  return False
129
 
130
+ # Setup Plotly
131
  try:
132
  import plotly.graph_objects as go
133
  import plotly.express as px
134
  import numpy as np
135
 
136
+ # Replace show method
137
+ go.Figure.show = lambda self, *args, **kwargs: show_plot(self)
 
 
 
138
 
139
+ print("βœ… Plotly ready with NumPy fix!")
 
 
 
 
140
 
141
  except Exception as e:
142
+ print(f"❌ Setup failed: {e}")
 
 
143
 
144
+ print("πŸŽ‰ Environment ready!")
145
  `);
146
 
147
  ready = true;
148
+ updateStatus('βœ… Ready!', 'green');
149
 
150
  document.getElementById('output').style.display = 'block';
151
+ document.getElementById('text-output').textContent = 'Ready! NumPy arrays will be automatically converted.';
152
 
153
  } catch (error) {
154
  console.error('Init error:', error);
 
156
  }
157
  }
158
 
159
+ async function executeCode(code) {
160
+ if (!ready) return 'Not ready';
 
 
161
 
162
  try {
163
+ updateStatus('▢️ Running...', 'blue');
164
 
165
+ // Clear plots
166
  document.getElementById('plots').innerHTML = '';
167
 
168
  // Capture output
 
173
  sys.stdout = capture = StringIO()
174
  `);
175
 
176
+ // Execute
177
+ pyodide.runPython(code);
178
 
179
  // Get output
180
  let output = pyodide.runPython(`
 
182
  capture.getvalue()
183
  `);
184
 
185
+ document.getElementById('text-output').textContent = output || 'Success';
186
+ updateStatus('βœ… Done!', 'green');
 
187
 
188
  return output || 'Success';
189
 
190
  } catch (error) {
191
+ const err = 'Error: ' + error.toString();
192
+ document.getElementById('text-output').textContent = err;
193
  updateStatus('❌ Error', 'red');
194
+ return err;
195
  }
196
  }
197
 
198
+ // Initialize
199
+ function init() {
200
  if (typeof loadPyodide !== 'undefined' && typeof Plotly !== 'undefined') {
 
201
  initPyodide();
202
  } else {
203
+ setTimeout(init, 1000);
204
  }
205
  }
206
 
207
+ init();
 
 
 
 
208
 
209
+ window.executeCode = executeCode;
210
  window.checkReady = () => ready;
211
 
212
  </script>
 
214
 
215
  return pyodide_html
216
 
 
217
  with gr.Blocks() as demo:
218
+ gr.Markdown("# πŸŽ‰ Working Plotly + Pyodide")
219
+ gr.Markdown("**NumPy arrays automatically converted!** Data points will now display correctly.")
220
 
221
  pyodide_interface = gr.HTML(create_pyodide_interface())
222
 
223
  with gr.Row():
224
  with gr.Column():
225
  code_input = gr.Textbox(
226
+ value="""# This should now work perfectly!
227
  import plotly.graph_objects as go
228
  import numpy as np
229
 
230
+ print("Creating plot with NumPy arrays...")
231
 
232
+ # NumPy arrays (these will be auto-converted)
233
+ x = np.array([1, 2, 3, 4, 5])
234
+ y = np.array([1, 4, 9, 16, 25])
235
 
236
+ print(f"X: {x}")
237
+ print(f"Y: {y}")
238
 
239
+ # Create plot
240
  fig = go.Figure()
 
 
241
  fig.add_trace(go.Scatter(
242
+ x=x, # NumPy array - will be auto-converted
243
+ y=y, # NumPy array - will be auto-converted
244
  mode='markers+lines',
245
+ name='Quadratic',
246
+ marker=dict(size=10, color='red'),
247
+ line=dict(color='blue', width=2)
 
 
 
 
 
 
 
248
  ))
249
 
 
250
  fig.update_layout(
251
+ title='Working Plot with NumPy Arrays!',
252
+ xaxis_title='X Values',
253
+ yaxis_title='Y Values',
254
+ template='plotly_white'
 
 
255
  )
256
 
257
+ fig.show()
258
+ print("βœ… Plot complete - data points should be visible!")""",
259
+ lines=18,
260
+ label="Python Code"
261
  )
262
 
263
+ execute_btn = gr.Button("πŸš€ Execute", variant="primary")
264
 
265
  with gr.Column():
266
  status_display = gr.Textbox(
267
  label="Status",
268
  interactive=False,
269
+ lines=3
270
  )
271
 
272
  check_btn = gr.Button("πŸ“Š Check")
273
 
 
274
  gr.Markdown("""
275
+ ### βœ… **What's Fixed:**
276
+ - **NumPy arrays** automatically converted to JavaScript arrays
277
+ - **Data points** will now display correctly
278
+ - **Interactive features** (zoom, pan, hover) working
279
+ - **No manual .tolist()** conversion needed
280
+
281
+ ### πŸ§ͺ **Try These Examples:**
282
 
283
+ **Simple Test:**
284
  ```python
285
+ import plotly.express as px
286
+ import pandas as pd
287
+ df = pd.DataFrame({'x': [1,2,3,4], 'y': [1,4,9,16]})
288
+ fig = px.scatter(df, x='x', y='y', title='Simple Test')
289
  fig.show()
290
  ```
291
 
292
+ **3D Plot:**
293
  ```python
294
  import plotly.graph_objects as go
295
  import numpy as np
 
 
 
 
 
 
296
 
297
+ x = np.random.randn(100)
298
+ y = np.random.randn(100)
299
+ z = np.random.randn(100)
300
+
301
+ fig = go.Figure(data=go.Scatter3d(x=x, y=y, z=z, mode='markers'))
 
302
  fig.show()
303
  ```
304
  """)
 
307
  fn=None,
308
  inputs=[code_input],
309
  outputs=[status_display],
310
+ js="(code) => window.executeCode ? window.executeCode(code) : 'Not ready'"
311
  )
312
 
313
  check_btn.click(
 
318
  )
319
 
320
  if __name__ == "__main__":
321
+ print("πŸš€ Starting Final Working Plotly + Pyodide...")
322
  demo.launch(server_name="0.0.0.0", server_port=7860, share=False)