Modify plotting code to handle headerless csv
All checks were successful
Generate Power Graph / plot (push) Successful in 1m58s
All checks were successful
Generate Power Graph / plot (push) Successful in 1m58s
This commit is contained in:
parent
974d23a7d4
commit
086e415ad9
2 changed files with 73 additions and 72 deletions
|
|
@ -1,34 +1,39 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
plot_power.py
|
plot_power.py
|
||||||
Forgejo CI: visualize AMD TUF APU/GPU telemetry as a clear bar graph.
|
Forgejo CI: visualize AMD TUF APU/GPU telemetry as a clean bar graph.
|
||||||
|
Compatible with headerless CSV output from amd-monitor.sh
|
||||||
Author: MarkMental
|
Author: MarkMental
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
CSV_PATH = "power_log.csv"
|
CSV_PATH = "power_log.csv"
|
||||||
OUTPUT_FILE = "power_graph.png"
|
OUTPUT_FILE = "power_graph.png"
|
||||||
|
|
||||||
print(f"📊 Reading {CSV_PATH}...")
|
print(f"📊 Reading {CSV_PATH}...")
|
||||||
df = pd.read_csv(CSV_PATH)
|
|
||||||
|
|
||||||
# --- Normalize timestamp ---
|
# --- Load CSV without headers ---
|
||||||
|
df = pd.read_csv(
|
||||||
|
CSV_PATH,
|
||||||
|
names=["timestamp", "apu_w", "gpu_w", "total_w", "apu_temp", "gpu_temp"],
|
||||||
|
comment="#",
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- Convert timestamps ---
|
||||||
df["timestamp"] = pd.to_datetime(df["timestamp"], errors="coerce")
|
df["timestamp"] = pd.to_datetime(df["timestamp"], errors="coerce")
|
||||||
df["time_fmt"] = df["timestamp"].dt.strftime("%Y-%m-%d %H:%M:%S")
|
df["time_fmt"] = df["timestamp"].dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
# --- Downsample if extremely long (avoid thousands of bars) ---
|
# --- Downsample if too many entries ---
|
||||||
if len(df) > 200:
|
if len(df) > 200:
|
||||||
df = df.iloc[::max(1, len(df)//200), :]
|
df = df.iloc[::max(1, len(df)//200), :]
|
||||||
|
|
||||||
# --- Plot setup ---
|
# --- Plot ---
|
||||||
fig, ax1 = plt.subplots(figsize=(12, 6))
|
fig, ax1 = plt.subplots(figsize=(12, 6))
|
||||||
|
|
||||||
# Power bars
|
|
||||||
width = 0.3
|
|
||||||
x = range(len(df))
|
x = range(len(df))
|
||||||
|
width = 0.3
|
||||||
|
|
||||||
ax1.bar([i - width for i in x], df["apu_w"], width, label="APU Power (W)", color="#ff9933")
|
ax1.bar([i - width for i in x], df["apu_w"], width, label="APU Power (W)", color="#ff9933")
|
||||||
ax1.bar(x, df["gpu_w"], width, label="GPU Power (W)", color="#66cc66")
|
ax1.bar(x, df["gpu_w"], width, label="GPU Power (W)", color="#66cc66")
|
||||||
ax1.bar([i + width for i in x], df["total_w"], width, label="Total Power (W)", color="#3399ff")
|
ax1.bar([i + width for i in x], df["total_w"], width, label="Total Power (W)", color="#3399ff")
|
||||||
|
|
@ -39,8 +44,7 @@ ax1.set_title("AMD TUF Power & Temperature Log")
|
||||||
ax1.set_xticks(x[::max(1, len(x)//10)])
|
ax1.set_xticks(x[::max(1, len(x)//10)])
|
||||||
ax1.set_xticklabels(df["time_fmt"].iloc[::max(1, len(x)//10)], rotation=45, ha="right")
|
ax1.set_xticklabels(df["time_fmt"].iloc[::max(1, len(x)//10)], rotation=45, ha="right")
|
||||||
|
|
||||||
# --- Secondary axis for temperature ---
|
# --- Secondary axis for temperatures ---
|
||||||
if "apu_temp" in df.columns and "gpu_temp" in df.columns:
|
|
||||||
ax2 = ax1.twinx()
|
ax2 = ax1.twinx()
|
||||||
ax2.plot(x, df["apu_temp"], "--", color="red", linewidth=1.2, label="APU Temp (°C)")
|
ax2.plot(x, df["apu_temp"], "--", color="red", linewidth=1.2, label="APU Temp (°C)")
|
||||||
ax2.plot(x, df["gpu_temp"], "--", color="purple", linewidth=1.2, label="GPU Temp (°C)")
|
ax2.plot(x, df["gpu_temp"], "--", color="purple", linewidth=1.2, label="GPU Temp (°C)")
|
||||||
|
|
@ -48,16 +52,13 @@ if "apu_temp" in df.columns and "gpu_temp" in df.columns:
|
||||||
ax2.set_ylim(min(df[["apu_temp","gpu_temp"]].min())-5,
|
ax2.set_ylim(min(df[["apu_temp","gpu_temp"]].min())-5,
|
||||||
max(df[["apu_temp","gpu_temp"]].max())+5)
|
max(df[["apu_temp","gpu_temp"]].max())+5)
|
||||||
|
|
||||||
# Combine legends
|
# --- Combined legend ---
|
||||||
lines1, labels1 = ax1.get_legend_handles_labels()
|
lines1, labels1 = ax1.get_legend_handles_labels()
|
||||||
lines2, labels2 = ax2.get_legend_handles_labels()
|
lines2, labels2 = ax2.get_legend_handles_labels()
|
||||||
ax1.legend(lines1 + lines2, labels1 + labels2, loc="upper left")
|
ax1.legend(lines1 + lines2, labels1 + labels2, loc="upper left")
|
||||||
else:
|
|
||||||
ax1.legend(loc="upper left")
|
|
||||||
|
|
||||||
plt.grid(axis="y", alpha=0.3)
|
plt.grid(axis="y", alpha=0.3)
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.savefig(OUTPUT_FILE, dpi=150)
|
plt.savefig(OUTPUT_FILE, dpi=150)
|
||||||
print(f"✅ Saved clean bar graph: {OUTPUT_FILE}")
|
print(f"✅ Saved graph: {OUTPUT_FILE}")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,3 @@
|
||||||
2025-11-05T18:00:54-05:00,7.17,9.00,16.17,73.0,68.0
|
|
||||||
2025-11-05T18:00:55-05:00,60.01,9.00,69.01,73.0,68.0
|
|
||||||
2025-11-05T18:00:56-05:00,47.02,9.00,56.02,74.0,68.0
|
|
||||||
2025-11-05T18:00:57-05:00,18.03,9.00,27.03,73.0,68.0
|
|
||||||
2025-11-05T18:00:58-05:00,49.19,9.00,58.19,72.0,68.0
|
|
||||||
2025-11-05T18:00:59-05:00,30.06,9.00,39.06,72.0,68.0
|
|
||||||
2025-11-05T18:01:00-05:00,2.22,10.00,12.22,72.0,68.0
|
|
||||||
2025-11-05T18:01:01-05:00,17.20,9.00,26.20,73.0,68.0
|
|
||||||
2025-11-05T18:07:07-05:00,3.09,9.00,12.09,73.0,68.0
|
|
||||||
2025-11-05T18:07:08-05:00,36.18,9.00,45.18,73.0,68.0
|
|
||||||
2025-11-05T18:07:09-05:00,60.18,9.00,69.18,73.0,68.0
|
|
||||||
2025-11-05T18:07:10-05:00,7.18,9.00,16.18,72.0,68.0
|
|
||||||
2025-11-05T18:07:11-05:00,7.22,9.00,16.22,73.0,68.0
|
|
||||||
2025-11-05T18:07:12-05:00,56.04,9.00,65.04,73.0,68.0
|
|
||||||
2025-11-05T18:07:13-05:00,59.12,10.00,69.12,73.0,68.0
|
|
||||||
2025-11-05T18:07:14-05:00,63.22,9.00,72.22,73.0,68.0
|
|
||||||
2025-11-05T18:07:15-05:00,5.17,10.00,15.17,73.0,68.0
|
|
||||||
2025-11-05T18:07:16-05:00,61.18,9.00,70.18,73.0,68.0
|
|
||||||
2025-11-05T18:07:17-05:00,65.08,9.00,74.08,74.0,68.0
|
|
||||||
2025-11-05T18:07:18-05:00,5.05,9.00,14.05,72.0,68.0
|
|
||||||
2025-11-05T18:07:19-05:00,19.14,9.00,28.14,73.0,68.0
|
|
||||||
2025-11-05T18:07:20-05:00,3.11,9.00,12.11,72.0,68.0
|
|
||||||
2025-11-05T18:07:21-05:00,2.04,9.00,11.04,73.0,68.0
|
|
||||||
2025-11-05T18:07:22-05:00,45.16,9.00,54.16,73.0,68.0
|
|
||||||
2025-11-05T18:12:52-05:00,1.04,9.00,10.04,73.0,68.0
|
|
||||||
2025-11-05T18:12:53-05:00,29.07,9.00,38.07,73.0,68.0
|
|
||||||
2025-11-05T18:12:54-05:00,53.16,10.00,63.16,73.0,68.0
|
|
||||||
2025-11-05T18:12:55-05:00,54.05,9.00,63.05,72.0,68.0
|
|
||||||
2025-11-05T18:12:56-05:00,10.02,10.00,20.02,72.0,68.0
|
|
||||||
2025-11-05T18:12:57-05:00,2.12,10.00,12.12,73.0,68.0
|
|
||||||
2025-11-05T18:12:58-05:00,64.10,9.00,73.10,72.0,68.0
|
|
||||||
2025-11-05T18:12:59-05:00,61.06,12.00,73.06,71.0,68.0
|
|
||||||
2025-11-05T18:13:00-05:00,31.14,9.00,40.14,70.0,68.0
|
|
||||||
2025-11-05T18:13:01-05:00,37.16,11.00,48.16,71.0,68.0
|
|
||||||
2025-11-05T18:13:02-05:00,60.10,9.00,69.10,72.0,67.0
|
|
||||||
2025-11-05T18:13:03-05:00,57.22,9.00,66.22,71.0,67.0
|
|
||||||
2025-11-05T18:13:04-05:00,47.23,9.00,56.23,71.0,67.0
|
|
||||||
2025-11-05T18:13:05-05:00,9.12,9.00,18.12,72.0,67.0
|
|
||||||
2025-11-05T18:13:06-05:00,50.21,9.00,59.21,71.0,67.0
|
|
||||||
2025-11-05T18:13:07-05:00,60.05,9.00,69.05,72.0,67.0
|
|
||||||
2025-11-05T18:13:08-05:00,1.08,9.00,10.08,72.0,67.0
|
|
||||||
2025-11-05T18:13:09-05:00,56.01,9.00,65.01,71.0,67.0
|
|
||||||
2025-11-05T18:13:10-05:00,47.18,9.00,56.18,71.0,67.0
|
|
||||||
2025-11-05T18:13:11-05:00,50.17,9.00,59.17,72.0,67.0
|
|
||||||
2025-11-05T18:13:12-05:00,9.17,9.00,18.17,72.0,67.0
|
|
||||||
2025-11-05T18:13:13-05:00,49.08,9.00,58.08,72.0,67.0
|
|
||||||
2025-11-05T18:13:14-05:00,51.02,9.00,60.02,72.0,67.0
|
|
||||||
2025-11-05T18:13:15-05:00,33.17,9.00,42.17,72.0,67.0
|
2025-11-05T18:13:15-05:00,33.17,9.00,42.17,72.0,67.0
|
||||||
2025-11-05T18:13:16-05:00,50.22,9.00,59.22,72.0,67.0
|
2025-11-05T18:13:16-05:00,50.22,9.00,59.22,72.0,67.0
|
||||||
2025-11-05T18:13:17-05:00,9.20,10.00,19.20,72.0,68.0
|
2025-11-05T18:13:17-05:00,9.20,10.00,19.20,72.0,68.0
|
||||||
|
|
@ -498,3 +451,50 @@
|
||||||
2025-11-05T18:43:00-05:00,64.07,9.00,73.07,71.0,67.0
|
2025-11-05T18:43:00-05:00,64.07,9.00,73.07,71.0,67.0
|
||||||
2025-11-05T18:43:01-05:00,46.11,9.00,55.11,71.0,67.0
|
2025-11-05T18:43:01-05:00,46.11,9.00,55.11,71.0,67.0
|
||||||
2025-11-05T18:43:02-05:00,2.07,9.00,11.07,71.0,67.0
|
2025-11-05T18:43:02-05:00,2.07,9.00,11.07,71.0,67.0
|
||||||
|
2025-11-05T18:49:44-05:00,54.18,9.00,63.18,71.0,67.0
|
||||||
|
2025-11-05T18:49:45-05:00,55.05,9.00,64.05,71.0,67.0
|
||||||
|
2025-11-05T18:49:46-05:00,9.16,9.00,18.16,72.0,67.0
|
||||||
|
2025-11-05T18:49:47-05:00,52.06,9.00,61.06,72.0,67.0
|
||||||
|
2025-11-05T18:49:48-05:00,49.10,9.00,58.10,71.0,67.0
|
||||||
|
2025-11-05T18:49:49-05:00,55.23,9.00,64.23,72.0,67.0
|
||||||
|
2025-11-05T18:49:51-05:00,0.20,9.00,9.20,71.0,67.0
|
||||||
|
2025-11-05T18:49:52-05:00,52.24,9.00,61.24,75.0,67.0
|
||||||
|
2025-11-05T18:49:53-05:00,0.24,9.00,9.24,71.0,67.0
|
||||||
|
2025-11-05T18:49:54-05:00,47.06,9.00,56.06,72.0,67.0
|
||||||
|
2025-11-05T18:49:55-05:00,47.22,9.00,56.22,71.0,67.0
|
||||||
|
2025-11-05T18:49:56-05:00,47.19,9.00,56.19,71.0,67.0
|
||||||
|
2025-11-05T18:49:57-05:00,53.10,9.00,62.10,71.0,67.0
|
||||||
|
2025-11-05T18:49:58-05:00,61.01,9.00,70.01,72.0,67.0
|
||||||
|
2025-11-05T18:49:59-05:00,47.08,9.00,56.08,71.0,67.0
|
||||||
|
2025-11-05T18:50:00-05:00,3.17,9.00,12.17,71.0,67.0
|
||||||
|
2025-11-05T18:50:01-05:00,58.10,9.00,67.10,72.0,67.0
|
||||||
|
2025-11-05T18:50:02-05:00,61.08,9.00,70.08,72.0,67.0
|
||||||
|
2025-11-05T18:50:03-05:00,55.12,9.00,64.12,72.0,67.0
|
||||||
|
2025-11-05T18:50:04-05:00,56.02,9.00,65.02,71.0,67.0
|
||||||
|
2025-11-05T18:50:05-05:00,1.02,9.00,10.02,71.0,67.0
|
||||||
|
2025-11-05T18:50:06-05:00,64.18,9.00,73.18,71.0,67.0
|
||||||
|
2025-11-05T18:50:07-05:00,43.13,9.00,52.13,72.0,67.0
|
||||||
|
2025-11-05T18:50:08-05:00,64.11,9.00,73.11,71.0,67.0
|
||||||
|
2025-11-05T18:50:09-05:00,63.23,9.00,72.23,72.0,67.0
|
||||||
|
2025-11-05T18:50:10-05:00,14.25,9.00,23.25,74.0,67.0
|
||||||
|
2025-11-05T18:50:11-05:00,6.08,9.00,15.08,72.0,67.0
|
||||||
|
2025-11-05T18:50:12-05:00,48.07,9.00,57.07,71.0,67.0
|
||||||
|
2025-11-05T18:50:13-05:00,61.05,9.00,70.05,71.0,67.0
|
||||||
|
2025-11-05T18:50:14-05:00,58.02,9.00,67.02,72.0,67.0
|
||||||
|
2025-11-05T18:50:15-05:00,3.09,9.00,12.09,72.0,67.0
|
||||||
|
2025-11-05T18:50:16-05:00,58.22,9.00,67.22,72.0,67.0
|
||||||
|
2025-11-05T18:50:17-05:00,54.13,9.00,63.13,72.0,67.0
|
||||||
|
2025-11-05T18:50:18-05:00,61.11,9.00,70.11,72.0,67.0
|
||||||
|
2025-11-05T18:50:19-05:00,7.04,9.00,16.04,71.0,67.0
|
||||||
|
2025-11-05T18:50:20-05:00,61.22,9.00,70.22,71.0,67.0
|
||||||
|
2025-11-05T18:50:21-05:00,63.08,9.00,72.08,71.0,67.0
|
||||||
|
2025-11-05T18:50:22-05:00,9.03,9.00,18.03,72.0,67.0
|
||||||
|
2025-11-05T18:50:23-05:00,62.01,11.00,73.01,71.0,67.0
|
||||||
|
2025-11-05T18:50:24-05:00,4.10,9.00,13.10,70.0,67.0
|
||||||
|
2025-11-05T18:50:25-05:00,6.17,9.00,15.17,72.0,67.0
|
||||||
|
2025-11-05T18:50:26-05:00,6.09,9.00,15.09,71.0,67.0
|
||||||
|
2025-11-05T18:50:27-05:00,0.24,9.00,9.24,72.0,67.0
|
||||||
|
2025-11-05T18:50:28-05:00,53.23,9.00,62.23,71.0,67.0
|
||||||
|
2025-11-05T18:50:29-05:00,3.24,9.00,12.24,72.0,67.0
|
||||||
|
2025-11-05T18:50:30-05:00,55.12,9.00,64.12,71.0,67.0
|
||||||
|
2025-11-05T18:50:31-05:00,49.00,9.00,58.00,71.0,67.0
|
||||||
|
|
|
||||||
|
Loading…
Add table
Add a link
Reference in a new issue