JG1310 commited on
Commit
22d7108
·
verified ·
1 Parent(s): ea722a5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -22
app.py CHANGED
@@ -1171,7 +1171,8 @@ def create_histogram(file_path: str, dataset_path: str, slice_str: str = "",
1171
 
1172
  def create_line_plot(file_path: str, dataset_path: str, slice_str: str = "",
1173
  title_override: str = "", xlabel_override: str = "", ylabel_override: str = "",
1174
- x_dataset_path: str = "", memory_limit_mb: float = None) -> Tuple[Dict[str, Any], Optional[str]]:
 
1175
  """
1176
  Create line plot for 1D data or time series.
1177
 
@@ -1183,6 +1184,7 @@ def create_line_plot(file_path: str, dataset_path: str, slice_str: str = "",
1183
  xlabel_override: Optional custom x-axis label
1184
  ylabel_override: Optional custom y-axis label
1185
  x_dataset_path: Optional path to X-axis data (if empty, uses indices)
 
1186
  memory_limit_mb: Memory limit in MB (default: tiered 100/500/2000)
1187
 
1188
  Returns:
@@ -1284,16 +1286,45 @@ def create_line_plot(file_path: str, dataset_path: str, slice_str: str = "",
1284
  # Create figure
1285
  fig = go.Figure()
1286
 
1287
- # Add line trace
1288
  fig.add_trace(go.Scatter(
1289
  x=x_data,
1290
  y=y_data,
1291
  mode='lines+markers',
1292
- name=dataset_path,
1293
- line=dict(color='steelblue', width=2),
1294
- marker=dict(size=4)
 
1295
  ))
1296
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1297
  # Set title and labels
1298
  title = title_override if title_override else f"Line Plot: {dataset_path}"
1299
  xlabel = xlabel_override if xlabel_override else (x_dataset_path if x_dataset_path else "Index")
@@ -1327,6 +1358,9 @@ def create_line_plot(file_path: str, dataset_path: str, slice_str: str = "",
1327
  "download_info": "Download the HTML file to view the interactive line plot in your browser"
1328
  }
1329
 
 
 
 
1330
  return result, html_path
1331
 
1332
  except Exception as e:
@@ -1483,8 +1517,8 @@ def create_heatmap(file_path: str, dataset_path: str, slice_str: str = "",
1483
 
1484
 
1485
  def create_scatter_plot(file_path: str, x_dataset_path: str, y_dataset_path: str,
1486
- slice_str: str = "", title_override: str = "",
1487
- xlabel_override: str = "", ylabel_override: str = "",
1488
  memory_limit_mb: float = None) -> Tuple[Dict[str, Any], Optional[str]]:
1489
  """
1490
  Create scatter plot comparing two variables.
@@ -1493,7 +1527,8 @@ def create_scatter_plot(file_path: str, x_dataset_path: str, y_dataset_path: str
1493
  file_path: Path to the HDF5/NetCDF file
1494
  x_dataset_path: Path to X-axis dataset/variable
1495
  y_dataset_path: Path to Y-axis dataset/variable
1496
- slice_str: Optional numpy-style slice notation
 
1497
  title_override: Optional custom title
1498
  xlabel_override: Optional custom x-axis label
1499
  ylabel_override: Optional custom y-axis label
@@ -1528,8 +1563,8 @@ def create_scatter_plot(file_path: str, x_dataset_path: str, y_dataset_path: str
1528
  x_var = f.variables[x_dataset_path]
1529
  y_var = f.variables[y_dataset_path]
1530
 
1531
- # Check memory safety for both
1532
- x_safety = check_memory_safety(x_var.shape, x_var.dtype, slice_str, memory_limit_mb)
1533
  if not x_safety["safe"]:
1534
  error_result = {
1535
  "error": f"X data: {x_safety['error']}",
@@ -1537,10 +1572,11 @@ def create_scatter_plot(file_path: str, x_dataset_path: str, y_dataset_path: str
1537
  "status": "failed"
1538
  }
1539
  if "suggested_slice" in x_safety:
1540
- error_result["suggested_slice"] = x_safety["suggested_slice"]
1541
  return error_result, None
1542
 
1543
- y_safety = check_memory_safety(y_var.shape, y_var.dtype, slice_str, memory_limit_mb)
 
1544
  if not y_safety["safe"]:
1545
  error_result = {
1546
  "error": f"Y data: {y_safety['error']}",
@@ -1548,16 +1584,21 @@ def create_scatter_plot(file_path: str, x_dataset_path: str, y_dataset_path: str
1548
  "status": "failed"
1549
  }
1550
  if "suggested_slice" in y_safety:
1551
- error_result["suggested_slice"] = y_safety["suggested_slice"]
1552
  return error_result, None
1553
 
1554
- # Read data
1555
- if slice_str and slice_str.strip():
1556
- idx = parse_slice(slice_str)
1557
- x_data = x_var[idx]
1558
- y_data = y_var[idx]
1559
  else:
1560
  x_data = x_var[:]
 
 
 
 
 
 
1561
  y_data = y_var[:]
1562
 
1563
  # Convert to numpy and flatten
@@ -1572,7 +1613,10 @@ def create_scatter_plot(file_path: str, x_dataset_path: str, y_dataset_path: str
1572
  # Check lengths match
1573
  if len(x_data) != len(y_data):
1574
  return {
1575
- "error": f"X and Y data length mismatch: {len(x_data)} vs {len(y_data)}",
 
 
 
1576
  "status": "failed"
1577
  }, None
1578
 
@@ -2137,6 +2181,13 @@ def build_mcp_tools():
2137
  value="",
2138
  info="Path to X-axis data (if empty, uses indices)"
2139
  ),
 
 
 
 
 
 
 
2140
  gr.Number(
2141
  label="Memory Limit (MB) - optional",
2142
  value=None,
@@ -2235,10 +2286,16 @@ def build_mcp_tools():
2235
  info="Path to Y-axis dataset/variable"
2236
  ),
2237
  gr.Textbox(
2238
- label="Slice (optional)",
2239
- placeholder="0:100, :, 5",
2240
  value="",
2241
- info="Numpy-style slice notation"
 
 
 
 
 
 
2242
  ),
2243
  gr.Textbox(
2244
  label="Title (optional)",
 
1171
 
1172
  def create_line_plot(file_path: str, dataset_path: str, slice_str: str = "",
1173
  title_override: str = "", xlabel_override: str = "", ylabel_override: str = "",
1174
+ x_dataset_path: str = "", moving_avg_window: int = 0,
1175
+ memory_limit_mb: float = None) -> Tuple[Dict[str, Any], Optional[str]]:
1176
  """
1177
  Create line plot for 1D data or time series.
1178
 
 
1184
  xlabel_override: Optional custom x-axis label
1185
  ylabel_override: Optional custom y-axis label
1186
  x_dataset_path: Optional path to X-axis data (if empty, uses indices)
1187
+ moving_avg_window: Window size for moving average (0 or 1 = no smoothing, 2-1000 = apply smoothing)
1188
  memory_limit_mb: Memory limit in MB (default: tiered 100/500/2000)
1189
 
1190
  Returns:
 
1286
  # Create figure
1287
  fig = go.Figure()
1288
 
1289
+ # Add raw data trace
1290
  fig.add_trace(go.Scatter(
1291
  x=x_data,
1292
  y=y_data,
1293
  mode='lines+markers',
1294
+ name='Raw Data',
1295
+ line=dict(color='steelblue', width=1),
1296
+ marker=dict(size=3),
1297
+ opacity=0.7
1298
  ))
1299
 
1300
+ # Add moving average if requested
1301
+ smoothed_info = None
1302
+ if moving_avg_window and moving_avg_window > 1:
1303
+ # Validate window size
1304
+ if moving_avg_window > len(y_data):
1305
+ smoothed_info = f"Moving average window ({moving_avg_window}) larger than data length ({len(y_data)}), skipping smoothing"
1306
+ else:
1307
+ # Calculate moving average using convolution
1308
+ window = np.ones(moving_avg_window) / moving_avg_window
1309
+ y_smooth = np.convolve(y_data, window, mode='valid')
1310
+
1311
+ # Adjust X data to match smoothed Y length
1312
+ # 'valid' mode reduces length by (window_size - 1)
1313
+ offset = (moving_avg_window - 1) // 2
1314
+ x_smooth = x_data[offset:offset + len(y_smooth)]
1315
+
1316
+ # Add smoothed trace
1317
+ fig.add_trace(go.Scatter(
1318
+ x=x_smooth,
1319
+ y=y_smooth,
1320
+ mode='lines',
1321
+ name=f'Moving Avg (n={moving_avg_window})',
1322
+ line=dict(color='red', width=2),
1323
+ opacity=0.9
1324
+ ))
1325
+
1326
+ smoothed_info = f"Applied moving average with window size {moving_avg_window}"
1327
+
1328
  # Set title and labels
1329
  title = title_override if title_override else f"Line Plot: {dataset_path}"
1330
  xlabel = xlabel_override if xlabel_override else (x_dataset_path if x_dataset_path else "Index")
 
1358
  "download_info": "Download the HTML file to view the interactive line plot in your browser"
1359
  }
1360
 
1361
+ if smoothed_info:
1362
+ result["smoothing"] = smoothed_info
1363
+
1364
  return result, html_path
1365
 
1366
  except Exception as e:
 
1517
 
1518
 
1519
  def create_scatter_plot(file_path: str, x_dataset_path: str, y_dataset_path: str,
1520
+ x_slice_str: str = "", y_slice_str: str = "",
1521
+ title_override: str = "", xlabel_override: str = "", ylabel_override: str = "",
1522
  memory_limit_mb: float = None) -> Tuple[Dict[str, Any], Optional[str]]:
1523
  """
1524
  Create scatter plot comparing two variables.
 
1527
  file_path: Path to the HDF5/NetCDF file
1528
  x_dataset_path: Path to X-axis dataset/variable
1529
  y_dataset_path: Path to Y-axis dataset/variable
1530
+ x_slice_str: Optional numpy-style slice for X data
1531
+ y_slice_str: Optional numpy-style slice for Y data
1532
  title_override: Optional custom title
1533
  xlabel_override: Optional custom x-axis label
1534
  ylabel_override: Optional custom y-axis label
 
1563
  x_var = f.variables[x_dataset_path]
1564
  y_var = f.variables[y_dataset_path]
1565
 
1566
+ # Check memory safety for X
1567
+ x_safety = check_memory_safety(x_var.shape, x_var.dtype, x_slice_str, memory_limit_mb)
1568
  if not x_safety["safe"]:
1569
  error_result = {
1570
  "error": f"X data: {x_safety['error']}",
 
1572
  "status": "failed"
1573
  }
1574
  if "suggested_slice" in x_safety:
1575
+ error_result["suggested_slice_x"] = x_safety["suggested_slice"]
1576
  return error_result, None
1577
 
1578
+ # Check memory safety for Y
1579
+ y_safety = check_memory_safety(y_var.shape, y_var.dtype, y_slice_str, memory_limit_mb)
1580
  if not y_safety["safe"]:
1581
  error_result = {
1582
  "error": f"Y data: {y_safety['error']}",
 
1584
  "status": "failed"
1585
  }
1586
  if "suggested_slice" in y_safety:
1587
+ error_result["suggested_slice_y"] = y_safety["suggested_slice"]
1588
  return error_result, None
1589
 
1590
+ # Read X data
1591
+ if x_slice_str and x_slice_str.strip():
1592
+ x_idx = parse_slice(x_slice_str)
1593
+ x_data = x_var[x_idx]
 
1594
  else:
1595
  x_data = x_var[:]
1596
+
1597
+ # Read Y data
1598
+ if y_slice_str and y_slice_str.strip():
1599
+ y_idx = parse_slice(y_slice_str)
1600
+ y_data = y_var[y_idx]
1601
+ else:
1602
  y_data = y_var[:]
1603
 
1604
  # Convert to numpy and flatten
 
1613
  # Check lengths match
1614
  if len(x_data) != len(y_data):
1615
  return {
1616
+ "error": f"X and Y data length mismatch after slicing: {len(x_data)} vs {len(y_data)}",
1617
+ "x_slice": x_slice_str if x_slice_str else "no slice",
1618
+ "y_slice": y_slice_str if y_slice_str else "no slice",
1619
+ "suggestion": "Adjust slices to produce equal-length arrays",
1620
  "status": "failed"
1621
  }, None
1622
 
 
2181
  value="",
2182
  info="Path to X-axis data (if empty, uses indices)"
2183
  ),
2184
+ gr.Number(
2185
+ label="Moving Average Window (optional)",
2186
+ value=0,
2187
+ minimum=0,
2188
+ maximum=1000,
2189
+ info="Window size for smoothing (0 or 1 = no smoothing, 2-1000 = apply moving average)"
2190
+ ),
2191
  gr.Number(
2192
  label="Memory Limit (MB) - optional",
2193
  value=None,
 
2286
  info="Path to Y-axis dataset/variable"
2287
  ),
2288
  gr.Textbox(
2289
+ label="X Slice (optional)",
2290
+ placeholder="0, :, :",
2291
  value="",
2292
+ info="Numpy-style slice for X data (can differ from Y slice)"
2293
+ ),
2294
+ gr.Textbox(
2295
+ label="Y Slice (optional)",
2296
+ placeholder="1, :, :",
2297
+ value="",
2298
+ info="Numpy-style slice for Y data (can differ from X slice)"
2299
  ),
2300
  gr.Textbox(
2301
  label="Title (optional)",