Spaces:
Sleeping
Sleeping
File size: 3,188 Bytes
de6f1e8 ccdbd61 60034d4 ccdbd61 010071f b8b8eab ccdbd61 010071f 60034d4 ccdbd61 60034d4 ccdbd61 b8b8eab ccdbd61 60034d4 ccdbd61 b8b8eab ccdbd61 60034d4 ccdbd61 60034d4 b8b8eab ccdbd61 60034d4 b04cfbb ccdbd61 60034d4 ccdbd61 60034d4 ccdbd61 60034d4 b8b8eab ccdbd61 b8b8eab ccdbd61 b8b8eab 60034d4 de6f1e8 60034d4 ccdbd61 60034d4 ccdbd61 60034d4 ccdbd61 de6f1e8 60034d4 ccdbd61 60034d4 ccdbd61 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# tools/plot_generator.py
# ------------------------------------------------------------
# Creates an interactive lineβandβmarker trend chart for any
# (date_col, value_col) pair and saves a hiβres PNG copy.
import os
import tempfile
from typing import Tuple, Union
import pandas as pd
import plotly.graph_objects as go
# Alias for typing β every helper returns a go.Figure
Plot = go.Figure
def plot_metric_tool(
file_path: str,
date_col: str,
value_col: str,
output_dir: str = "/tmp",
title: str | None = None,
line_width: int = 2,
marker_size: int = 6,
) -> Union[Tuple[Plot, str], str]:
"""
Build a (date, metric) trend chart.
Returns
-------
(fig, png_path) on success
error string on failure (string starts with 'β')
"""
# ββ 1. Load CSV or Excel ββββββββββββββββββββββββββββββββββ
ext = os.path.splitext(file_path)[1].lower()
try:
df = (
pd.read_excel(file_path)
if ext in (".xls", ".xlsx")
else pd.read_csv(file_path)
)
except Exception as exc:
return f"β Failed to load file: {exc}"
# ββ 2. Validate columns βββββββββββββββββββββββββββββββββββ
missing = [c for c in (date_col, value_col) if c not in df.columns]
if missing:
return f"β Missing column(s): {', '.join(missing)}"
# ββ 3. Parse & clean ββββββββββββββββββββββββββββββββββββββ
df[date_col] = pd.to_datetime(df[date_col], errors="coerce")
df[value_col] = pd.to_numeric(df[value_col], errors="coerce")
df = df.dropna(subset=[date_col, value_col])
if df.empty:
return f"β No valid data after cleaning '{date_col}' / '{value_col}'."
# Aggregate duplicate timestamps, sort by date
df = (
df[[date_col, value_col]]
.groupby(date_col, as_index=True)
.mean()
.sort_index()
)
# ββ 4. Build Plotly figure ββββββββββββββββββββββββββββββββ
fig = go.Figure(
go.Scatter(
x=df.index,
y=df[value_col],
mode="lines+markers",
line=dict(width=line_width),
marker=dict(size=marker_size),
name=value_col,
)
)
fig.update_layout(
title=title or f"{value_col} Trend",
xaxis_title=date_col,
yaxis_title=value_col,
template="plotly_dark",
hovermode="x unified",
)
# ββ 5. Save static PNG copy βββββββββββββββββββββββββββββββ
os.makedirs(output_dir, exist_ok=True)
tmp = tempfile.NamedTemporaryFile(
prefix="trend_", suffix=".png", dir=output_dir, delete=False
)
png_path = tmp.name
tmp.close()
try:
fig.write_image(png_path, scale=2)
except Exception as exc:
return f"β Failed saving image: {exc}"
return fig, png_path
|