mgbam commited on
Commit
60034d4
Β·
verified Β·
1 Parent(s): eec9db3

Update tools/plot_generator.py

Browse files
Files changed (1) hide show
  1. tools/plot_generator.py +81 -18
tools/plot_generator.py CHANGED
@@ -1,28 +1,91 @@
 
 
1
  import pandas as pd
2
  import plotly.graph_objects as go
3
 
4
- def plot_metric_tool(file_path: str, date_col: str, value_col: str):
 
 
 
 
 
 
 
 
 
5
  """
6
- Generic interactive line chart for any numeric metric.
7
- Returns a Plotly Figure or error message string.
 
 
 
8
  """
9
- df = pd.read_csv(file_path)
 
 
 
 
 
 
 
 
10
 
11
- if date_col not in df.columns or value_col not in df.columns:
12
- return f"❌ '{date_col}' or '{value_col}' column missing."
 
 
13
 
14
- df[date_col] = pd.to_datetime(df[date_col], errors="coerce")
15
- if df[date_col].isna().all():
16
- return f"❌ '{date_col}' could not be parsed as dates."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
 
18
  fig = go.Figure(
19
- go.Scatter(
20
- x=df[date_col],
21
- y=df[value_col],
22
- mode="lines+markers",
23
- line=dict(width=2),
24
- )
 
 
 
 
25
  )
26
- fig.update_layout(title=f"{value_col} Trend", template="plotly_dark")
27
- fig.write_image("metric_plot.png")
28
- return fig
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import tempfile
3
  import pandas as pd
4
  import plotly.graph_objects as go
5
 
6
+
7
+ def plot_metric_tool(
8
+ file_path: str,
9
+ date_col: str,
10
+ value_col: str,
11
+ output_dir: str = "/tmp",
12
+ title: str = None,
13
+ line_width: int = 2,
14
+ marker_size: int = 6
15
+ ):
16
  """
17
+ Load CSV or Excel file, parse a time series metric, and return an interactive Plotly Figure.
18
+ Also saves a high-resolution PNG to a temp directory for static embedding.
19
+
20
+ Returns:
21
+ fig (go.Figure) or error string starting with '❌'.
22
  """
23
+ # 0) Load data
24
+ ext = os.path.splitext(file_path)[1].lower()
25
+ try:
26
+ if ext in ('.xls', '.xlsx'):
27
+ df = pd.read_excel(file_path)
28
+ else:
29
+ df = pd.read_csv(file_path)
30
+ except Exception as exc:
31
+ return f"❌ Failed to load file: {exc}"
32
 
33
+ # 1) Validate columns
34
+ missing = [c for c in (date_col, value_col) if c not in df.columns]
35
+ if missing:
36
+ return f"❌ Missing column(s): {', '.join(missing)}"
37
 
38
+ # 2) Parse date and ensure numeric values
39
+ try:
40
+ df[date_col] = pd.to_datetime(df[date_col], errors='coerce')
41
+ except Exception:
42
+ return f"❌ Could not parse '{date_col}' as dates."
43
+ df[value_col] = pd.to_numeric(df[value_col], errors='coerce')
44
+ df = df.dropna(subset=[date_col, value_col])
45
+ if df.empty:
46
+ return f"❌ No valid data after cleaning '{date_col}'/'{value_col}'"
47
+
48
+ # 3) Sort and aggregate duplicates
49
+ df = (
50
+ df[[date_col, value_col]]
51
+ .groupby(date_col, as_index=True)
52
+ .mean()
53
+ .sort_index()
54
+ )
55
 
56
+ # 4) Create Plotly figure
57
  fig = go.Figure(
58
+ data=[
59
+ go.Scatter(
60
+ x=df.index,
61
+ y=df[value_col],
62
+ mode='lines+markers',
63
+ line=dict(width=line_width),
64
+ marker=dict(size=marker_size),
65
+ name=value_col
66
+ )
67
+ ]
68
  )
69
+ plot_title = title or f"{value_col} Trend"
70
+ fig.update_layout(
71
+ title=plot_title,
72
+ xaxis_title=date_col,
73
+ yaxis_title=value_col,
74
+ template='plotly_dark',
75
+ hovermode='x unified'
76
+ )
77
+
78
+ # 5) Save static PNG
79
+ os.makedirs(output_dir, exist_ok=True)
80
+ tmpfile = tempfile.NamedTemporaryFile(
81
+ suffix='.png', prefix='trend_', dir=output_dir, delete=False
82
+ )
83
+ img_path = tmpfile.name
84
+ tmpfile.close()
85
+ try:
86
+ fig.write_image(img_path, scale=2)
87
+ except Exception as exc:
88
+ return f"❌ Failed saving image: {exc}"
89
+
90
+ # 6) Return figure and path for embedding
91
+ return fig, img_path