Ken-INOUE commited on
Commit
b7aa901
·
1 Parent(s): ed624a7

Enhance diagnosis function to return detailed results and update Gradio UI for improved output display

Browse files
Files changed (1) hide show
  1. app.py +56 -21
app.py CHANGED
@@ -2,6 +2,7 @@ import gradio as gr
2
  import pandas as pd
3
  import json
4
 
 
5
  def judge_status(value, ll, l, h, hh):
6
  if pd.notna(ll) and value < ll:
7
  return "LOW-LOW"
@@ -14,9 +15,10 @@ def judge_status(value, ll, l, h, hh):
14
  else:
15
  return "OK"
16
 
 
17
  def diagnose_app(csv_file, excel_file, process_name, datetime_str, window_minutes):
18
  if csv_file is None or excel_file is None:
19
- return "⚠ CSVとExcelファイルを両方アップロードしてください", None, None
20
 
21
  # CSV読み込み(3行ヘッダー)
22
  df = pd.read_csv(csv_file, header=[0, 1, 2])
@@ -36,18 +38,19 @@ def diagnose_app(csv_file, excel_file, process_name, datetime_str, window_minute
36
  try:
37
  target_time = pd.to_datetime(datetime_str)
38
  except Exception:
39
- return f"⚠ 入力した日時 {datetime_str} が無効です", None, None
40
 
41
  start_time = target_time - pd.Timedelta(minutes=window_minutes)
42
  end_time = target_time
43
  df_window = df[(df["timestamp"] >= start_time) & (df["timestamp"] <= end_time)]
44
  if df_window.empty:
45
- return "⚠ 指定した時間幅にデータがありません", None, None
46
 
47
  proc_thresholds = thresholds_df[thresholds_df["ProcessNo_ProcessName"] == process_name]
48
  if proc_thresholds.empty:
49
- return f"⚠ プロセス {process_name} の閾値が見つかりません", None, None
50
 
 
51
  all_results = []
52
  for _, row in df_window.iterrows():
53
  for _, thr in proc_thresholds.iterrows():
@@ -60,42 +63,72 @@ def diagnose_app(csv_file, excel_file, process_name, datetime_str, window_minute
60
  "ColumnID": thr["ColumnID"],
61
  "ItemName": thr["ItemName"],
62
  "値": value,
 
 
 
 
63
  "判定": status,
64
  "重要項目": bool(thr.get("Important", False)),
65
- "時刻": row["timestamp"]
66
  })
67
 
68
- total = len(all_results)
69
- if total == 0:
70
- return f"⚠ プロセス {process_name} の診断結果なし", None, None
71
 
 
 
72
  status_counts = pd.Series([r["判定"] for r in all_results]).value_counts().reindex(
73
  ["LOW-LOW", "LOW", "OK", "HIGH", "HIGH-HIGH"], fill_value=0
74
  )
75
  status_ratio = (status_counts / total * 100).round(1)
76
-
77
- result_df = pd.DataFrame({
78
- "状態": status_counts.index,
79
- "件数": status_counts.values,
80
- "割合(%)": status_ratio.values
81
- })
82
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  summary = (
84
  f"✅ {process_name} の診断完了({start_time} ~ {end_time})\n"
85
- + " / ".join([f"{s}:{r:.1f}%" for s, r in status_ratio.items()])
 
 
 
 
86
  )
87
 
88
  result_json = json.dumps(all_results, ensure_ascii=False, indent=2, default=str)
89
 
90
- return summary, result_df, result_json
91
 
92
  # --- Gradio UI ---
93
  with gr.Blocks() as demo:
94
  gr.Markdown("## 閾値診断アプリ")
95
 
96
  with gr.Row():
97
- csv_input = gr.File(label="CSVファイルをアップロード", type="filepath")
98
- excel_input = gr.File(label="閾値テーブルをアップロード", type="filepath")
99
 
100
  process_name = gr.Textbox(label="プロセス名", placeholder="例: E018-A012_除害RO")
101
  datetime_str = gr.Textbox(label="基準日時 (例: 2025/8/1 0:05)")
@@ -104,13 +137,15 @@ with gr.Blocks() as demo:
104
  run_btn = gr.Button("診断実行")
105
 
106
  summary_out = gr.Textbox(label="サマリー")
107
- table_out = gr.Dataframe(label="診断結果(集計表)")
 
 
108
  json_out = gr.JSON(label="JSON出力")
109
 
110
  run_btn.click(
111
  diagnose_app,
112
  inputs=[csv_input, excel_input, process_name, datetime_str, window_minutes],
113
- outputs=[summary_out, table_out, json_out]
114
  )
115
 
116
  if __name__ == "__main__":
 
2
  import pandas as pd
3
  import json
4
 
5
+ # --- 状態判定関数 ---
6
  def judge_status(value, ll, l, h, hh):
7
  if pd.notna(ll) and value < ll:
8
  return "LOW-LOW"
 
15
  else:
16
  return "OK"
17
 
18
+ # --- 診断関数 ---
19
  def diagnose_app(csv_file, excel_file, process_name, datetime_str, window_minutes):
20
  if csv_file is None or excel_file is None:
21
+ return "⚠ CSVとExcelを両方アップロードしてください", None, None, None, None
22
 
23
  # CSV読み込み(3行ヘッダー)
24
  df = pd.read_csv(csv_file, header=[0, 1, 2])
 
38
  try:
39
  target_time = pd.to_datetime(datetime_str)
40
  except Exception:
41
+ return f"⚠ 入力した日時 {datetime_str} が無効です", None, None, None, None
42
 
43
  start_time = target_time - pd.Timedelta(minutes=window_minutes)
44
  end_time = target_time
45
  df_window = df[(df["timestamp"] >= start_time) & (df["timestamp"] <= end_time)]
46
  if df_window.empty:
47
+ return "⚠ 指定時間幅にデータなし", None, None, None, None
48
 
49
  proc_thresholds = thresholds_df[thresholds_df["ProcessNo_ProcessName"] == process_name]
50
  if proc_thresholds.empty:
51
+ return f"⚠ プロセス {process_name} の閾値が見つかりません", None, None, None, None
52
 
53
+ # 全結果リスト
54
  all_results = []
55
  for _, row in df_window.iterrows():
56
  for _, thr in proc_thresholds.iterrows():
 
63
  "ColumnID": thr["ColumnID"],
64
  "ItemName": thr["ItemName"],
65
  "値": value,
66
+ "LL": thr.get("LL"),
67
+ "L": thr.get("L"),
68
+ "H": thr.get("H"),
69
+ "HH": thr.get("HH"),
70
  "判定": status,
71
  "重要項目": bool(thr.get("Important", False)),
72
+ "時刻": str(row["timestamp"])
73
  })
74
 
75
+ if not all_results:
76
+ return f"⚠ 診断結果なし", None, None, None, None
 
77
 
78
+ # --- 全項目集計 ---
79
+ total = len(all_results)
80
  status_counts = pd.Series([r["判定"] for r in all_results]).value_counts().reindex(
81
  ["LOW-LOW", "LOW", "OK", "HIGH", "HIGH-HIGH"], fill_value=0
82
  )
83
  status_ratio = (status_counts / total * 100).round(1)
84
+ result_df_all = pd.DataFrame({"状態": status_counts.index, "件数": status_counts.values, "割合(%)": status_ratio.values})
85
+
86
+ # --- 重要項目全体 ---
87
+ important_results = [r for r in all_results if r["重要項目"]]
88
+ if important_results:
89
+ total_imp = len(important_results)
90
+ status_counts_imp = pd.Series([r["判定"] for r in important_results]).value_counts().reindex(
91
+ ["LOW-LOW", "LOW", "OK", "HIGH", "HIGH-HIGH"], fill_value=0
92
+ )
93
+ status_ratio_imp = (status_counts_imp / total_imp * 100).round(1)
94
+ result_df_imp = pd.DataFrame({"状態": status_counts_imp.index, "件数": status_counts_imp.values, "割合(%)": status_ratio_imp.values})
95
+ else:
96
+ result_df_imp = pd.DataFrame(columns=["状態", "件数", "割合(%)"])
97
+
98
+ # --- 重要項目ごと ---
99
+ result_per_item = []
100
+ for item in {r["ItemName"] for r in important_results}:
101
+ item_results = [r for r in important_results if r["ItemName"] == item]
102
+ total_item = len(item_results)
103
+ status_counts_item = pd.Series([r["判定"] for r in item_results]).value_counts().reindex(
104
+ ["LOW-LOW", "LOW", "OK", "HIGH", "HIGH-HIGH"], fill_value=0
105
+ )
106
+ status_ratio_item = (status_counts_item / total_item * 100).round(1)
107
+ for s, c, r in zip(status_counts_item.index, status_counts_item.values, status_ratio_item.values):
108
+ result_per_item.append({"ItemName": item, "状態": s, "件数": c, "割合(%)": r})
109
+ result_df_imp_items = pd.DataFrame(result_per_item)
110
+
111
+ # --- サマリー ---
112
  summary = (
113
  f"✅ {process_name} の診断完了({start_time} ~ {end_time})\n"
114
+ + "[全項目] " + " / ".join([f"{s}:{r:.1f}%" for s, r in status_ratio.items()]) + "\n"
115
+ + "[重要項目全体] " + (
116
+ " / ".join([f"{s}:{r:.1f}%" for s, r in status_ratio_imp.items()])
117
+ if not result_df_imp.empty else "対象データなし"
118
+ )
119
  )
120
 
121
  result_json = json.dumps(all_results, ensure_ascii=False, indent=2, default=str)
122
 
123
+ return summary, result_df_all, result_df_imp, result_df_imp_items, result_json
124
 
125
  # --- Gradio UI ---
126
  with gr.Blocks() as demo:
127
  gr.Markdown("## 閾値診断アプリ")
128
 
129
  with gr.Row():
130
+ csv_input = gr.File(label="CSVファイル", type="filepath")
131
+ excel_input = gr.File(label="閾値テーブル", type="filepath")
132
 
133
  process_name = gr.Textbox(label="プロセス名", placeholder="例: E018-A012_除害RO")
134
  datetime_str = gr.Textbox(label="基準日時 (例: 2025/8/1 0:05)")
 
137
  run_btn = gr.Button("診断実行")
138
 
139
  summary_out = gr.Textbox(label="サマリー")
140
+ table_all_out = gr.Dataframe(label="全項目の状態集計結果")
141
+ table_imp_out = gr.Dataframe(label="重要項目全体の状態集計結果")
142
+ table_imp_items_out = gr.Dataframe(label="重要項目ごとの状態集計結果")
143
  json_out = gr.JSON(label="JSON出力")
144
 
145
  run_btn.click(
146
  diagnose_app,
147
  inputs=[csv_input, excel_input, process_name, datetime_str, window_minutes],
148
+ outputs=[summary_out, table_all_out, table_imp_out, table_imp_items_out, json_out]
149
  )
150
 
151
  if __name__ == "__main__":