Skip to content

Commit 95103d6

Browse files
authored
Reproducibility capsule - init, exp 1 plots, v1, not yet final (#5)
* figure comparison experiment 1 * figure comparison experiment 1 - v1 * figure comparison experiment 1 - v2 * exp 1 cpu utilization, latency, with mock data - v1 * exp 1 cpu utilization, latency, with mock data - v1.1
1 parent f37ae43 commit 95103d6

File tree

8 files changed

+1054
-0
lines changed

8 files changed

+1054
-0
lines changed
30.2 MB
Binary file not shown.
89.8 KB
Binary file not shown.
1.2 MB
Binary file not shown.

reproducibility_capsule/exp_1/exp_1_cpu_latency/exp_1_cpu_latency.ipynb

Lines changed: 641 additions & 0 deletions
Large diffs are not rendered by default.
Binary file not shown.

reproducibility_capsule/exp_1/exp_1_power_draw/exp1_plot_power_draw.ipynb

Lines changed: 266 additions & 0 deletions
Large diffs are not rendered by default.
Binary file not shown.
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import pandas as pd
2+
import numpy as np
3+
import matplotlib.pyplot as plt
4+
from matplotlib.ticker import FuncFormatter
5+
import os
6+
7+
# --- 1. CONFIGURATION & STYLE ---
8+
COLOR_PALETTE = [
9+
"#0072B2", "#E69F00", "#009E73", "#D55E00", "#CC79A7", "#F0E442", "#8B4513",
10+
"#56B4E9", "#F0A3FF", "#FFB400", "#00BFFF", "#90EE90", "#FF6347", "#8A2BE2",
11+
"#CD5C5C", "#4682B4", "#FFDEAD", "#32CD32", "#D3D3D3", "#999999"
12+
]
13+
METRIC = "power_draw"
14+
15+
16+
def load_and_process_data():
17+
"""Loads parquet files and aligns timestamps."""
18+
print("Loading data...")
19+
20+
# Check if data exists (Warning only)
21+
if not os.path.exists("../data/footprinter.parquet"):
22+
print("Warning: ../data/footprinter.parquet not found.")
23+
24+
# Load Data
25+
fp = pd.read_parquet("../data/footprinter.parquet").groupby("timestamp")[METRIC].sum()
26+
odt = pd.read_parquet("../data/opendt.parquet").groupby("timestamp")[METRIC].sum()
27+
rw = pd.read_parquet("../data/real_world.parquet").groupby("timestamp")[METRIC].sum()
28+
29+
# --- Processing ---
30+
print("Processing and aligning data...")
31+
32+
def average_every_n(series, n):
33+
return series.groupby(np.arange(len(series)) // n).mean()
34+
35+
# Average to 5-min intervals
36+
# OpenDT (2.5m) -> 2 samples = 5 min
37+
# Others (30s) -> 10 samples = 5 min
38+
odt = average_every_n(odt, 2)
39+
fp = average_every_n(fp, 10)
40+
rw = average_every_n(rw, 10)
41+
42+
# Sync lengths (trim to shortest)
43+
min_len = min(len(odt), len(fp), len(rw))
44+
odt = odt.iloc[:min_len]
45+
fp = fp.iloc[:min_len]
46+
rw = rw.iloc[:min_len]
47+
48+
# Force Start Time to 2022-10-06 22:00:00
49+
start_time = pd.Timestamp("2022-10-06 22:00:00")
50+
# Fixed deprecation warning: used '5min' instead of '5T'
51+
timestamps = pd.date_range(start=start_time, periods=min_len, freq="5min")
52+
53+
# Apply clean timestamps
54+
odt.index = timestamps
55+
fp.index = timestamps
56+
rw.index = timestamps
57+
58+
return fp, odt, rw, timestamps, min_len
59+
60+
61+
def calculate_mape(ground_truth, simulation):
62+
"""Calculates Mean Absolute Percentage Error (MAPE)."""
63+
R = ground_truth.values
64+
S = simulation.values
65+
return np.mean(np.abs((R - S) / R)) * 100
66+
67+
68+
def generate_experiment_pdf(x, fp, odt, rw, timestamps, min_len):
69+
"""Generates the final publication plot."""
70+
print("Generating final experiment PDF...")
71+
72+
# Setup Figure (12, 5 size)
73+
plt.figure(figsize=(12, 5))
74+
plt.grid(True)
75+
76+
# Plot Lines (Thick lines: lw=3)
77+
plt.plot(x, rw.values / 1000, label="Ground Truth", color=COLOR_PALETTE[0], lw=3)
78+
plt.plot(x, fp.values / 1000, label="FootPrinter", color=COLOR_PALETTE[1], lw=3)
79+
plt.plot(x, odt.values / 1000, label="OpenDT", color=COLOR_PALETTE[2], lw=3)
80+
81+
ax = plt.gca()
82+
83+
# --- Formatting X-Axis (Fixed Dates) ---
84+
target_dates = ["2022-10-08", "2022-10-10", "2022-10-12", "2022-10-14"]
85+
tick_dates = pd.to_datetime(target_dates)
86+
87+
tick_positions = []
88+
tick_labels = []
89+
90+
for d in tick_dates:
91+
seconds_diff = (d - timestamps[0]).total_seconds()
92+
# 300 seconds = 5 minutes
93+
idx = int(seconds_diff / 300)
94+
95+
tick_positions.append(idx)
96+
tick_labels.append(d.strftime("%d/%m"))
97+
98+
ax.set_xticks(tick_positions)
99+
# INCREASED FONT SIZE (was 14)
100+
ax.set_xticklabels(tick_labels, fontsize=20)
101+
102+
# Extend limit slightly to show last tick
103+
max_tick = max(tick_positions)
104+
if ax.get_xlim()[1] < max_tick:
105+
ax.set_xlim(right=max_tick + (min_len * 0.02))
106+
107+
# --- Formatting Y-Axis ---
108+
y_formatter = FuncFormatter(lambda val, _: f"{int(val):,}")
109+
ax.yaxis.set_major_formatter(y_formatter)
110+
# INCREASED FONT SIZE (was 14)
111+
ax.tick_params(axis='y', labelsize=20)
112+
113+
# Labels (INCREASED FONT SIZE)
114+
plt.ylabel("Power Draw [kW]", fontsize=22, labelpad=10)
115+
plt.xlabel("Time [day/month]", fontsize=22, labelpad=10)
116+
plt.ylim(bottom=0)
117+
118+
# Legend
119+
# FIXED: Cleaned 'loc' and ensured it matches bbox placement
120+
plt.legend(fontsize=18, loc="upper center", bbox_to_anchor=(0.5, 1.22), ncol=3, framealpha=1)
121+
122+
plt.tight_layout()
123+
124+
# Save
125+
plt.savefig("exp1_plot_power_draw.pdf", format="pdf", bbox_inches="tight")
126+
print("Plot saved as 'exp1_plot_power_draw.pdf'")
127+
# plt.show() # Uncomment if running in interactive mode/notebook
128+
plt.close()
129+
130+
131+
def main():
132+
# 1. Load Data
133+
fp, odt, rw, timestamps, min_len = load_and_process_data()
134+
x = np.arange(min_len)
135+
136+
# 2. Calculate Stats
137+
mape_fp = calculate_mape(rw, fp)
138+
mape_odt = calculate_mape(rw, odt)
139+
print(f"Stats Calculated (Not plotted) - FP: {mape_fp:.2f}%, ODT: {mape_odt:.2f}%")
140+
141+
# 3. Generate Plot
142+
generate_experiment_pdf(x, fp, odt, rw, timestamps, min_len)
143+
print("Done!")
144+
145+
146+
if __name__ == "__main__":
147+
main()

0 commit comments

Comments
 (0)