Ansaribinhyder commited on
Commit
9b40395
·
1 Parent(s): 16e58e0

Updated UI and Excel Function

Browse files
Files changed (2) hide show
  1. app.py +72 -44
  2. templates/plot.html +81 -64
app.py CHANGED
@@ -3,26 +3,27 @@ import pandas as pd
3
  import matplotlib.pyplot as plt
4
  import numpy as np
5
  import io
 
6
 
7
  app = Flask(__name__)
8
 
9
- # Global data cache
10
  data_cache = {
11
- "df1": None, # Golden data
12
  "limits": {},
13
  "cols": [],
14
- "golden_loaded": False
 
15
  }
16
 
17
 
18
  def process_golden_file(golden_file):
19
- """Load and store Golden Excel data + limits."""
20
  limits_df1 = pd.read_excel(golden_file, nrows=4)
21
  df1 = pd.read_excel(golden_file)
22
  df1 = df1.drop([0, 1, 2, 3])
23
  df1 = df1.apply(pd.to_numeric, errors="coerce")
24
 
25
- # Extract limits
26
  limits_df1 = limits_df1.drop([0])
27
  ignore_cols = ["SITE_NUM", "PART_ID", "PASSFG", "SOFT_BIN", "T_TIME", "TEST_NUM"]
28
  cols_to_plot = [col for col in limits_df1.columns if "_" in col and col not in ignore_cols]
@@ -33,53 +34,73 @@ def process_golden_file(golden_file):
33
  for col in limits_df1.columns
34
  }
35
 
36
- # Store globally
37
- data_cache["df1"] = df1
38
- data_cache["limits"] = limits
39
- data_cache["cols"] = cols_to_plot
40
- data_cache["golden_loaded"] = True
 
41
 
42
 
43
  def process_test_file(test_file):
44
- """Load and return the Test Excel data."""
45
  df2 = pd.read_excel(test_file)
46
  df2 = df2.drop([0, 1, 2, 3])
47
  df2 = df2.apply(pd.to_numeric, errors="coerce")
48
  return df2
49
 
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  def generate_plot(df2, col):
52
- """Generate plot comparing Golden and Test for a specific column."""
53
  df1, limits = data_cache["df1"], data_cache["limits"]
54
 
55
  plt.figure(figsize=(6, 4))
56
-
57
- # Golden
58
  x1 = np.arange(1, len(df1[col]) + 1)
59
- y1 = pd.to_numeric(df1[col], errors="coerce").values
60
- plt.plot(x1, y1, marker="o", linestyle="-", color="blue", label="Golden")
61
 
62
- # Test
63
  if col in df2.columns:
64
  x2 = np.arange(1, len(df2[col]) + 1)
65
- y2 = pd.to_numeric(df2[col], errors="coerce").values
66
- plt.plot(x2, y2, marker="s", linestyle="--", color="red", label="Test")
67
 
68
- # Limits
69
  if col in limits:
70
  ll, ul = limits[col]["LL"], limits[col]["UL"]
71
- plt.axhline(ll, color="green", linestyle="--", linewidth=2, label="LL")
72
- plt.axhline(ul, color="orange", linestyle="--", linewidth=2, label="UL")
73
 
74
  plt.title(f"{col}")
75
  plt.xlabel("Part # (sequence)")
76
  plt.ylabel("Value")
77
- plt.grid(True, linestyle="--", alpha=0.7)
78
- plt.legend(fontsize="small")
79
  plt.tight_layout()
80
 
81
  buf = io.BytesIO()
82
- plt.savefig(buf, format="png", bbox_inches="tight")
83
  buf.seek(0)
84
  plt.close()
85
  return buf
@@ -87,52 +108,59 @@ def generate_plot(df2, col):
87
 
88
  @app.route("/", methods=["GET", "POST"])
89
  def index():
90
- """Handle golden upload (if not loaded) or test upload (if golden loaded)."""
91
  if request.method == "POST":
 
92
  if not data_cache["golden_loaded"]:
93
- # Upload Golden
94
  golden_file = request.files.get("golden_file")
95
  if not golden_file:
96
- return render_template("index.html", error="Please upload a Golden file first.")
97
  try:
98
  process_golden_file(golden_file)
99
- return render_template("index.html", message="Golden data loaded successfully! Now upload Test data.")
100
  except Exception as e:
101
  return render_template("index.html", error=f"Error loading Golden file: {e}")
 
 
102
  else:
103
- # Upload Test
104
  test_file = request.files.get("test_file")
105
  if not test_file:
106
- return render_template("index.html", error="Please upload a Test file.")
107
  try:
108
  df2 = process_test_file(test_file)
109
- cols = data_cache["cols"]
110
- preview_cols = cols[:3] if len(cols) >= 3 else cols
111
- # Store test temporarily in memory (for this view only)
112
  data_cache["df2_temp"] = df2
113
- return render_template("plot.html", cols=cols, preview_cols=preview_cols)
 
 
 
 
 
114
  except Exception as e:
115
- return render_template("index.html", error=f"Error loading Test file: {e}")
116
 
117
  return render_template("index.html", golden_loaded=data_cache["golden_loaded"])
118
 
119
 
120
  @app.route("/plot_image/<col>")
121
  def plot_image(col):
122
- """Generate plot image for selected column."""
123
  df2 = data_cache.get("df2_temp")
124
  if df2 is None:
125
- return "No Test data uploaded yet."
126
- try:
127
- buf = generate_plot(df2, col)
128
- return send_file(buf, mimetype="image/png")
129
- except Exception as e:
130
- return f"Error generating plot: {str(e)}"
 
 
 
 
 
 
131
 
132
 
133
  @app.route("/reset_golden")
134
  def reset_golden():
135
- """Clear the Golden file from memory."""
136
  data_cache.update({"df1": None, "limits": {}, "cols": [], "golden_loaded": False})
137
  return redirect(url_for("index"))
138
 
 
3
  import matplotlib.pyplot as plt
4
  import numpy as np
5
  import io
6
+ import os
7
 
8
  app = Flask(__name__)
9
 
10
+ # Cache
11
  data_cache = {
12
+ "df1": None,
13
  "limits": {},
14
  "cols": [],
15
+ "golden_loaded": False,
16
+ "comparison_file": None
17
  }
18
 
19
 
20
  def process_golden_file(golden_file):
21
+ """Load Golden data and extract limits."""
22
  limits_df1 = pd.read_excel(golden_file, nrows=4)
23
  df1 = pd.read_excel(golden_file)
24
  df1 = df1.drop([0, 1, 2, 3])
25
  df1 = df1.apply(pd.to_numeric, errors="coerce")
26
 
 
27
  limits_df1 = limits_df1.drop([0])
28
  ignore_cols = ["SITE_NUM", "PART_ID", "PASSFG", "SOFT_BIN", "T_TIME", "TEST_NUM"]
29
  cols_to_plot = [col for col in limits_df1.columns if "_" in col and col not in ignore_cols]
 
34
  for col in limits_df1.columns
35
  }
36
 
37
+ data_cache.update({
38
+ "df1": df1,
39
+ "limits": limits,
40
+ "cols": cols_to_plot,
41
+ "golden_loaded": True
42
+ })
43
 
44
 
45
  def process_test_file(test_file):
46
+ """Load Test data."""
47
  df2 = pd.read_excel(test_file)
48
  df2 = df2.drop([0, 1, 2, 3])
49
  df2 = df2.apply(pd.to_numeric, errors="coerce")
50
  return df2
51
 
52
 
53
+ def generate_comparison_excel(df2):
54
+ """Generate comparison Excel (mean, std, min, max for both)."""
55
+ df1 = data_cache["df1"]
56
+ common_cols = [c for c in df1.columns if c in df2.columns]
57
+
58
+ summary = []
59
+ for col in common_cols:
60
+ g_mean, t_mean = df1[col].mean(), df2[col].mean()
61
+ g_std, t_std = df1[col].std(), df2[col].std()
62
+ g_min, t_min = df1[col].min(), df2[col].min()
63
+ g_max, t_max = df1[col].max(), df2[col].max()
64
+
65
+ diff = t_mean - g_mean if pd.notna(t_mean) and pd.notna(g_mean) else np.nan
66
+ summary.append([col, g_mean, t_mean, diff, g_std, t_std, g_min, t_min, g_max, t_max])
67
+
68
+ comp_df = pd.DataFrame(summary, columns=[
69
+ "Parameter", "Golden_Mean", "Test_Mean", "Mean_Diff",
70
+ "Golden_Std", "Test_Std", "Golden_Min", "Test_Min", "Golden_Max", "Test_Max"
71
+ ])
72
+
73
+ path = "comparison_result.xlsx"
74
+ comp_df.to_excel(path, index=False)
75
+ data_cache["comparison_file"] = path
76
+
77
+
78
  def generate_plot(df2, col):
79
+ """Generate and return a plot comparing Golden vs Test."""
80
  df1, limits = data_cache["df1"], data_cache["limits"]
81
 
82
  plt.figure(figsize=(6, 4))
 
 
83
  x1 = np.arange(1, len(df1[col]) + 1)
84
+ plt.plot(x1, df1[col], 'o-', label="Golden", color='blue')
 
85
 
 
86
  if col in df2.columns:
87
  x2 = np.arange(1, len(df2[col]) + 1)
88
+ plt.plot(x2, df2[col], 's--', label="Test", color='red')
 
89
 
 
90
  if col in limits:
91
  ll, ul = limits[col]["LL"], limits[col]["UL"]
92
+ plt.axhline(ll, color='green', linestyle='--', label='LL')
93
+ plt.axhline(ul, color='orange', linestyle='--', label='UL')
94
 
95
  plt.title(f"{col}")
96
  plt.xlabel("Part # (sequence)")
97
  plt.ylabel("Value")
98
+ plt.legend(fontsize='small')
99
+ plt.grid(True, linestyle='--', alpha=0.7)
100
  plt.tight_layout()
101
 
102
  buf = io.BytesIO()
103
+ plt.savefig(buf, format='png', bbox_inches='tight')
104
  buf.seek(0)
105
  plt.close()
106
  return buf
 
108
 
109
  @app.route("/", methods=["GET", "POST"])
110
  def index():
 
111
  if request.method == "POST":
112
+ # Upload Golden first
113
  if not data_cache["golden_loaded"]:
 
114
  golden_file = request.files.get("golden_file")
115
  if not golden_file:
116
+ return render_template("index.html", error="Please upload Golden file.")
117
  try:
118
  process_golden_file(golden_file)
119
+ return render_template("index.html", message="Golden data loaded successfully!")
120
  except Exception as e:
121
  return render_template("index.html", error=f"Error loading Golden file: {e}")
122
+
123
+ # Upload Test data next
124
  else:
 
125
  test_file = request.files.get("test_file")
126
  if not test_file:
127
+ return render_template("index.html", error="Please upload Test data.")
128
  try:
129
  df2 = process_test_file(test_file)
 
 
 
130
  data_cache["df2_temp"] = df2
131
+ generate_comparison_excel(df2)
132
+ return render_template(
133
+ "plot.html",
134
+ cols=data_cache["cols"],
135
+ file_ready=True
136
+ )
137
  except Exception as e:
138
+ return render_template("index.html", error=f"Error processing Test file: {e}")
139
 
140
  return render_template("index.html", golden_loaded=data_cache["golden_loaded"])
141
 
142
 
143
  @app.route("/plot_image/<col>")
144
  def plot_image(col):
 
145
  df2 = data_cache.get("df2_temp")
146
  if df2 is None:
147
+ return "No Test data loaded."
148
+ buf = generate_plot(df2, col)
149
+ return send_file(buf, mimetype="image/png")
150
+
151
+
152
+ @app.route("/download_comparison")
153
+ def download_comparison():
154
+ """Download comparison Excel file."""
155
+ path = data_cache.get("comparison_file")
156
+ if path and os.path.exists(path):
157
+ return send_file(path, as_attachment=True)
158
+ return "No comparison file available."
159
 
160
 
161
  @app.route("/reset_golden")
162
  def reset_golden():
163
+ """Reset golden data."""
164
  data_cache.update({"df1": None, "limits": {}, "cols": [], "golden_loaded": False})
165
  return redirect(url_for("index"))
166
 
templates/plot.html CHANGED
@@ -1,70 +1,87 @@
1
  <!DOCTYPE html>
2
- <html lang="en">
3
  <head>
4
- <meta charset="UTF-8">
5
- <title>IPM Data Plots</title>
6
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
7
- <style>
8
- body {
9
- background: #f6f8fa;
10
- font-family: "Segoe UI", Arial, sans-serif;
11
- padding: 30px;
12
- }
13
- h2 {
14
- text-align: center;
15
- margin-bottom: 30px;
16
- }
17
- img {
18
- max-width: 90%;
19
- border-radius: 10px;
20
- box-shadow: 0 3px 12px rgba(0,0,0,0.1);
21
- margin: 20px auto;
22
- display: block;
23
- }
24
- .dropdown-container {
25
- text-align: center;
26
- margin-top: 20px;
27
- }
28
- select {
29
- width: 60%;
30
- padding: 10px;
31
- border-radius: 6px;
32
- border: 1px solid #ccc;
33
- }
34
- .card {
35
- border: none;
36
- border-radius: 12px;
37
- box-shadow: 0 3px 12px rgba(0,0,0,0.08);
38
- background: #fff;
39
- padding: 20px;
40
- margin-bottom: 25px;
41
- }
42
- .preview-title {
43
- font-weight: 600;
44
- margin-top: 10px;
45
- }
46
- </style>
47
- <script>
48
- function showPlot() {
49
- const col = document.getElementById("col-select").value;
50
- document.getElementById("dynamic-plot").src = "/plot_image/" + encodeURIComponent(col);
51
- }
52
- </script>
 
 
 
 
 
 
 
 
53
  </head>
54
  <body>
55
- <div class="container">
56
- <h2>📈 Golden vs Test Comparison</h2>
57
 
58
- <div class="card">
59
- <h4>Preview (First few plots)</h4>
60
- {% for c in preview_cols %}
61
- <div class="preview-title">{{ c }}</div>
62
- <img src="/plot_image/{{ c }}" alt="{{ c }}">
63
- {% endfor %}
64
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
- <div class="card">
67
- <h4>Select Another Column to View</h4>
68
- <div class="dropdown-container">
69
- <select id="col-select" onchange="showPlot()">
70
- <option
 
1
  <!DOCTYPE html>
2
+ <html>
3
  <head>
4
+ <title>IPM Comparison</title>
5
+ <style>
6
+ body {
7
+ font-family: 'Segoe UI', sans-serif;
8
+ background: #f7f9fc;
9
+ text-align: center;
10
+ padding: 30px;
11
+ }
12
+ h2 {
13
+ color: #1e88e5;
14
+ }
15
+ select {
16
+ padding: 10px;
17
+ margin: 20px;
18
+ border-radius: 6px;
19
+ border: 1px solid #aaa;
20
+ font-size: 16px;
21
+ }
22
+ img {
23
+ max-width: 90%;
24
+ border: 1px solid #ddd;
25
+ border-radius: 8px;
26
+ margin-top: 20px;
27
+ }
28
+ a {
29
+ display: inline-block;
30
+ background-color: #43a047;
31
+ color: white;
32
+ padding: 10px 20px;
33
+ text-decoration: none;
34
+ border-radius: 6px;
35
+ margin-top: 15px;
36
+ transition: background 0.3s ease;
37
+ }
38
+ a:hover {
39
+ background-color: #2e7d32;
40
+ }
41
+ button {
42
+ background-color: #e53935;
43
+ color: white;
44
+ border: none;
45
+ padding: 10px 20px;
46
+ border-radius: 6px;
47
+ margin-top: 20px;
48
+ cursor: pointer;
49
+ }
50
+ button:hover {
51
+ background-color: #c62828;
52
+ }
53
+ </style>
54
+
55
+ <script>
56
+ function showPlot() {
57
+ const col = document.getElementById("col-select").value;
58
+ document.getElementById("plot-img").src = "/plot_image/" + encodeURIComponent(col);
59
+ }
60
+ </script>
61
  </head>
62
  <body>
 
 
63
 
64
+ <h2>📊 Golden vs Test Data Comparison</h2>
65
+
66
+ {% if file_ready %}
67
+ <a href="/download_comparison">⬇️ Download Comparison Excel</a>
68
+ {% endif %}
69
+
70
+ <h3>Select Parameter to Plot:</h3>
71
+ <select id="col-select" onchange="showPlot()">
72
+ <option disabled selected>Select a column</option>
73
+ {% for c in cols %}
74
+ <option value="{{ c }}">{{ c }}</option>
75
+ {% endfor %}
76
+ </select>
77
+
78
+ <br>
79
+ <img id="plot-img" src="" alt="Plot will appear here">
80
+
81
+ <br>
82
+ <form action="/reset_golden">
83
+ <button>Reset Golden Data</button>
84
+ </form>
85
 
86
+ </body>
87
+ </html>