Ken-INOUE commited on
Commit
b6dd650
·
1 Parent(s): 7bca111

Implement initial project structure and setup

Browse files
Files changed (2) hide show
  1. app.py +125 -0
  2. requirements.txt +13 -0
app.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import pandas as pd
4
+ import numpy as np
5
+ import json
6
+ from sklearn.linear_model import LinearRegression
7
+
8
+ # =========================================================
9
+ # データロード部分(共通)
10
+ # =========================================================
11
+ csv_path = r"sample.csv" # あなたのCSVパスに置き換え
12
+ excel_path = r"thresholds.xlsx" # あなたの閾値テーブルExcelパスに置き換え
13
+ lag_excel_path = r"lag_table.xlsx" # タイムラグ表Excelパスに置き換え
14
+
15
+ # CSV(3行ヘッダー)
16
+ df = pd.read_csv(csv_path, header=[0, 1, 2])
17
+ timestamp_col = df.iloc[:, 0]
18
+ df = df.drop(df.columns[0], axis=1)
19
+ df.insert(0, "timestamp", timestamp_col)
20
+ df["timestamp"] = pd.to_datetime(df["timestamp"], errors="coerce")
21
+
22
+ # 閾値テーブル
23
+ thresholds_df = pd.read_excel(excel_path)
24
+ thresholds_df["Important"] = thresholds_df["Important"].astype(str).str.upper().map({"TRUE": True, "FALSE": False})
25
+ for col in ["LL", "L", "H", "HH"]:
26
+ if col in thresholds_df.columns:
27
+ thresholds_df[col] = pd.to_numeric(thresholds_df[col], errors="coerce")
28
+
29
+ # タイムラグ表
30
+ lag_matrix = pd.read_excel(lag_excel_path, index_col=0)
31
+
32
+
33
+ # =========================================================
34
+ # 閾値診断関数
35
+ # =========================================================
36
+ def diagnose(process_name, datetime_str, window_minutes):
37
+ try:
38
+ target_time = pd.to_datetime(datetime_str)
39
+ except Exception:
40
+ return None, "⚠ 日時が不正です", None
41
+
42
+ start_time = target_time - pd.Timedelta(minutes=int(window_minutes))
43
+ df_window = df[(df["timestamp"] >= start_time) & (df["timestamp"] <= target_time)]
44
+ if df_window.empty:
45
+ return None, "⚠ データなし", None
46
+
47
+ proc_thresholds = thresholds_df[thresholds_df["ProcessNo_ProcessName"] == process_name]
48
+ results = []
49
+ for _, thr in proc_thresholds.iterrows():
50
+ col_tuple = (thr["ColumnID"], thr["ItemName"], thr["ProcessNo_ProcessName"])
51
+ if col_tuple not in df.columns:
52
+ continue
53
+ series = df_window[col_tuple].dropna()
54
+ if series.empty:
55
+ continue
56
+
57
+ value = series.iloc[-1]
58
+ status = "OK"
59
+ if pd.notna(thr["LL"]) and value < thr["LL"]:
60
+ status = "LOW-LOW"
61
+ elif pd.notna(thr["L"]) and value < thr["L"]:
62
+ status = "LOW"
63
+ elif pd.notna(thr["HH"]) and value > thr["HH"]:
64
+ status = "HIGH-HIGH"
65
+ elif pd.notna(thr["H"]) and value > thr["H"]:
66
+ status = "HIGH"
67
+
68
+ results.append({
69
+ "ItemName": thr["ItemName"],
70
+ "値": value,
71
+ "判定": status,
72
+ "重要項目": bool(thr.get("Important", False))
73
+ })
74
+
75
+ result_df = pd.DataFrame(results)
76
+ result_json = json.dumps(results, ensure_ascii=False, indent=2, default=lambda x: x.item() if hasattr(x, "item") else x)
77
+ summary = f"✅ {process_name} の診断完了({start_time}~{target_time})"
78
+ return result_df, summary, result_json
79
+
80
+
81
+ # =========================================================
82
+ # Gradio UI 構築
83
+ # =========================================================
84
+ with gr.Blocks() as demo:
85
+ gr.Markdown("## 水処理データ解析アプリ")
86
+
87
+ with gr.Tab("閾値診断アプリ"):
88
+ process_in = gr.Textbox(label="プロセス名", value="E018-A012_除害RO")
89
+ datetime_in = gr.Textbox(label="基準日時 (例: 2025/8/1 0:05)", value="2025/8/1 0:05")
90
+ window_in = gr.Number(label="時間幅(分)", value=60)
91
+
92
+ run_btn = gr.Button("診断実行")
93
+ summary_out = gr.Textbox(label="サマリー")
94
+ table_out = gr.Dataframe(label="診断結果", interactive=False)
95
+ json_out = gr.Textbox(label="JSON出力")
96
+
97
+ def run_diagnose(process, dt, win):
98
+ df_out, summary, js = diagnose(process, dt, win)
99
+ return summary, df_out, js
100
+
101
+ run_btn.click(
102
+ fn=run_diagnose,
103
+ inputs=[process_in, datetime_in, window_in],
104
+ outputs=[summary_out, table_out, json_out]
105
+ )
106
+
107
+
108
+ # =========================================================
109
+ # 実行部分
110
+ # =========================================================
111
+ if __name__ == "__main__":
112
+ if os.getenv("USE_MCP", "0") == "1":
113
+ # Hugging Face 用: MCP + UI
114
+ demo.launch(
115
+ mcp_server=True,
116
+ server_name="0.0.0.0",
117
+ share=False
118
+ )
119
+ else:
120
+ # ローカル用: UI のみ
121
+ demo.launch(
122
+ server_name="0.0.0.0",
123
+ share=False,
124
+ ssr_mode=False
125
+ )
requirements.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Webアプリ/UI
2
+ gradio>=4.44.0
3
+
4
+ # データ処理
5
+ pandas>=2.2.0
6
+ numpy>=1.26.0
7
+ openpyxl>=3.1.2
8
+
9
+ # 機械学習(回帰や予兆解析で利用)
10
+ scikit-learn>=1.5.0
11
+
12
+ # 可視化(将来グラフ表示を追加する可能性を考慮)
13
+ matplotlib>=3.8.0