dataanalysis / SPC_System /spc_engine.py
Ansaribinhyder's picture
Enhanced SPC Control
33d5431
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os
# --------- Load three datasets ----------
df_t1 = pd.read_excel("tester#1.xlsx")
df_t2 = pd.read_excel("tester#2.xlsx")
df_gold = pd.read_excel("Golden_Data.xlsx")
# --------- Get parameter list ----------
df_new = df_gold.head(3).dropna(axis=1, how="all")
df_param = df_new.drop(["T_TIME", "SITE_NUM"], axis=1)
parameters = list(df_param.columns)
# --------- Build master dictionary ----------
data = {
param: {
"Tester1": pd.to_numeric(df_t1[param].iloc[3:], errors="coerce").dropna().tolist(),
"Tester2": pd.to_numeric(df_t2[param].iloc[3:], errors="coerce").dropna().tolist(),
"Golden": pd.to_numeric(df_gold[param].iloc[3:], errors="coerce").dropna().tolist(),
"LimitL": df_new[param].iloc[1],
"LimitU": df_new[param].iloc[2],
"Unit": df_new[param].iloc[0]
}
for param in parameters
}
# --------- Plot comparison SPC ----------
os.makedirs("./charts_compare", exist_ok=True)
for param in parameters:
t1 = np.array(data[param]["Tester1"])
t2 = np.array(data[param]["Tester2"])
gold = np.array(data[param]["Golden"])
limit_l = data[param]["LimitL"]
limit_u = data[param]["LimitU"]
unit = data[param]["Unit"]
# Golden reference control band
mean = gold.mean()
t1_mean = t1.mean()
t2_mean = t2.mean()
std = gold.std(ddof=1)
UCL = mean + 3 * std
LCL = mean - 3 * std
# ---- Fix max length ----
max_len = max(len(t1), len(t2), len(gold))
xaxis = np.arange(1, max_len + 1)
# ---- Correlation ----
min_len_t1 = min(len(t1), len(gold))
min_len_t2 = min(len(t2), len(gold))
corr_t1 = np.corrcoef(t1[:min_len_t1], gold[:min_len_t1])[0,1]
corr_t2 = np.corrcoef(t2[:min_len_t2], gold[:min_len_t2])[0,1]
corr_t1_t2 = np.corrcoef(t1[:min_len_t1], t2[:min_len_t2])[0,1]
# ---- CPK (based on Golden dataset) ----
cpk = min((mean - limit_l) / (3 * std), (limit_u - mean) / (3 * std))
plt.figure(figsize=(10,6))
# --- Plot all datasets ---
plt.plot(range(1, len(t1)+1), t1, marker='o', label="Tester #1")
plt.plot(range(1, len(t2)+1), t2, marker='o', label="Tester #2")
plt.plot(range(1, len(gold)+1), gold, marker='o', label="Gold Reference", linewidth=3)
# --- SPC lines ---
plt.axhline(mean, linestyle='--', color='black', label=f"Mean (Gold)")
plt.axhline(UCL, linestyle='-.', color='red', label="UCL (Mean + 3σ)")
plt.axhline(LCL, linestyle='-.', color='red', label="LCL (Mean – 3σ)")
# --- Spec Limits ---
plt.axhline(limit_l, linestyle=':', color='orange', label="Lower Spec")
plt.axhline(limit_u, linestyle=':', color='orange', label="Upper Spec")
# ---- Fix X-axis ----
# plt.xticks(np.arange(1, max_len + 1, step=1))
# plt.xlim(1, max_len)
# ---- Fix X-axis with whole numbers + padding ----
max_len = max(len(t1), len(t2), len(gold))
plt.xticks(np.arange(1, max_len + 1, 1)) # whole numbers
plt.xlim(0, max_len + 1) # space before 1 and after last point
# ---- Add CPK + Correlation text box ----
textstr = (
f"Gold Mean = {mean:.4f}\n"
f"Std Dev = {std:.4f}\n"
f"CPK = {cpk:.4f}\n"
f"Corr T1–Gold = {corr_t1:.4f}\n"
f"Corr T2–Gold = {corr_t2:.4f}\n"
f"Corr T1-T2 = {corr_t1_t2:.4f}\n"
f"Tester#1 Mean = {t1_mean:.4f}\n"
f"Tester#2 Mean = {t2_mean:4f}\n"
)
plt.gca().text(
0.02, 0.98, textstr,
transform=plt.gca().transAxes,
fontsize=10,
verticalalignment='top',
bbox=dict(boxstyle="round,pad=0.4", facecolor="white", alpha=0.8)
)
# Labels
plt.title(f"SPC Comparison - {param} ({unit})")
plt.xlabel("Sample Index")
plt.ylabel(f"Value ({unit})")
plt.grid(True)
plt.legend()
plt.tight_layout()
# Save chart
plt.savefig(f"./charts_compare/SPC_compare_{param}.png", dpi=300)
plt.close()