Ken-INOUE commited on
Commit
f1a3458
·
1 Parent(s): 6695822

initial commit

Browse files
Files changed (3) hide show
  1. app.py +132 -0
  2. requirements.txt +13 -0
  3. trend_result.json +202 -0
app.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app_trend.py
2
+ import os
3
+ import json
4
+ import pandas as pd
5
+ import numpy as np
6
+ from sklearn.linear_model import LinearRegression
7
+ import gradio as gr
8
+
9
+ # --- 傾向検出関数 ---
10
+ def detect_trends(process_name, datetime_str, window_minutes, csv_file, excel_file):
11
+ try:
12
+ # CSV読み込み(3行ヘッダー維持)
13
+ df = pd.read_csv(csv_file.name, header=[0, 1, 2])
14
+ timestamp_col = df.iloc[:, 0]
15
+ df = df.drop(df.columns[0], axis=1)
16
+ df.insert(0, "timestamp", timestamp_col)
17
+ df["timestamp"] = pd.to_datetime(df["timestamp"], errors="coerce")
18
+
19
+ # 閾値テーブル読み込み
20
+ thresholds_df = pd.read_excel(excel_file.name)
21
+ thresholds_df["Important"] = thresholds_df["Important"].astype(str).str.upper().map({"TRUE": True, "FALSE": False})
22
+ for col in ["LL", "L", "H", "HH"]:
23
+ if col in thresholds_df.columns:
24
+ thresholds_df[col] = pd.to_numeric(thresholds_df[col], errors="coerce")
25
+
26
+ # --- 診断対象期間 ---
27
+ target_time = pd.to_datetime(datetime_str)
28
+ start_time = target_time - pd.Timedelta(minutes=window_minutes)
29
+ end_time = target_time
30
+ df_window = df[(df["timestamp"] >= start_time) & (df["timestamp"] <= end_time)]
31
+
32
+ if df_window.empty:
33
+ return pd.DataFrame(), f"⚠ 指定時間幅にデータなし", "{}"
34
+
35
+ proc_thresholds = thresholds_df[(thresholds_df["ProcessNo_ProcessName"] == process_name) &
36
+ (thresholds_df["Important"] == True)]
37
+ if proc_thresholds.empty:
38
+ return pd.DataFrame(), f"⚠ プロセス {process_name} の重要項目なし", "{}"
39
+
40
+ results = []
41
+ for _, thr in proc_thresholds.iterrows():
42
+ col_tuple = (thr["ColumnID"], thr["ItemName"], thr["ProcessNo_ProcessName"])
43
+ if col_tuple not in df.columns:
44
+ continue
45
+
46
+ series = df_window[col_tuple].dropna()
47
+ if len(series) < 3:
48
+ continue
49
+
50
+ # 線形回帰
51
+ x = np.arange(len(series)).reshape(-1, 1)
52
+ y = series.values.reshape(-1, 1)
53
+ model = LinearRegression().fit(x, y)
54
+ slope = model.coef_[0][0]
55
+
56
+ last_val = series.iloc[-1]
57
+ l, ll, h, hh = thr.get("L"), thr.get("LL"), thr.get("H"), thr.get("HH")
58
+
59
+ status = "安定"
60
+ if slope < 0 and pd.notna(ll):
61
+ if last_val > ll:
62
+ status = "LL接近下降傾向"
63
+ elif last_val <= ll:
64
+ status = "LL逸脱下降傾向"
65
+ if slope > 0 and pd.notna(hh):
66
+ if last_val < hh:
67
+ status = "HH接近上昇傾向"
68
+ elif last_val >= hh:
69
+ status = "HH逸脱上昇傾向"
70
+
71
+ results.append({
72
+ "ItemName": thr["ItemName"],
73
+ "傾向": status,
74
+ "傾き": round(float(slope), 4),
75
+ "最終値": round(float(last_val), 3) if pd.notna(last_val) else None,
76
+ "LL": ll, "L": l, "H": h, "HH": hh
77
+ })
78
+
79
+ if not results:
80
+ return pd.DataFrame(), f"⚠ データ不足のため傾向検出不可", "{}"
81
+
82
+ result_df = pd.DataFrame(results)
83
+ result_json = json.dumps(results, ensure_ascii=False, indent=2)
84
+
85
+ # JSONファイル保存(ダウンロード用)
86
+ json_path = "trend_result.json"
87
+ with open(json_path, "w", encoding="utf-8") as f:
88
+ f.write(result_json)
89
+
90
+ summary = f"✅ {process_name} の傾向検出完了({start_time} ~ {end_time})"
91
+ return result_df, summary, json_path
92
+
93
+ except Exception as e:
94
+ return pd.DataFrame(), f"❌ エラー: {str(e)}", "{}"
95
+
96
+
97
+ # --- Gradio UI ---
98
+ def create_demo():
99
+ with gr.Blocks() as demo:
100
+ gr.Markdown("## 📈 傾向検出アプリ")
101
+
102
+ with gr.Row():
103
+ csv_input = gr.File(label="CSVファイルをアップロード", type="filepath")
104
+ excel_input = gr.File(label="閾値テーブルExcelをアップロード", type="filepath")
105
+
106
+ process_name = gr.Textbox(label="プロセス名 (例: E018-A012_除害RO)")
107
+ datetime_input = gr.Textbox(label="基準日時 (例: 2025/8/1 0:05)")
108
+ window_minutes = gr.Number(label="さかのぼる時間幅 (分)", value=60)
109
+
110
+ run_btn = gr.Button("傾向検出を実行")
111
+
112
+ result_table = gr.Dataframe(label="傾向検出結果", interactive=False)
113
+ summary_out = gr.Textbox(label="サマリー")
114
+ json_file = gr.File(label="結果JSONダウンロード", interactive=False)
115
+
116
+ run_btn.click(
117
+ detect_trends,
118
+ inputs=[process_name, datetime_input, window_minutes, csv_input, excel_input],
119
+ outputs=[result_table, summary_out, json_file]
120
+ )
121
+
122
+ return demo
123
+
124
+
125
+ # --- 起動設定 ---
126
+ if __name__ == "__main__":
127
+ demo = create_demo()
128
+ if os.getenv("USE_MCP") == "1":
129
+ demo.launch(server_name="0.0.0.0", mcp_server=True, ssr_mode=False)
130
+ else:
131
+ demo.launch(server_name="0.0.0.0", share=False, ssr_mode=False)
132
+
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
trend_result.json ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "ItemName": "除害RO_A処理水_導電率",
4
+ "傾向": "HH接近上昇傾向",
5
+ "傾き": 0.0024,
6
+ "最終値": 5.577,
7
+ "LL": 6.738,
8
+ "L": 7.062,
9
+ "H": 7.65,
10
+ "HH": 7.988
11
+ },
12
+ {
13
+ "ItemName": "除害RO_B処理水_導電率",
14
+ "傾向": "HH接近上昇傾向",
15
+ "傾き": 0.0953,
16
+ "最終値": 27.245,
17
+ "LL": 9.45,
18
+ "L": 19.888,
19
+ "H": 39.938,
20
+ "HH": 41.225
21
+ },
22
+ {
23
+ "ItemName": "除害RO_C処理水_導電率",
24
+ "傾向": "HH接近上昇傾向",
25
+ "傾き": 0.0055,
26
+ "最終値": 0.0,
27
+ "LL": 6.388,
28
+ "L": 7.088,
29
+ "H": 7.962,
30
+ "HH": 9.275
31
+ },
32
+ {
33
+ "ItemName": "除害RO_D処理水_導電率",
34
+ "傾向": "HH接近上昇傾向",
35
+ "傾き": 0.0277,
36
+ "最終値": 11.999,
37
+ "LL": 9.4,
38
+ "L": 49.888,
39
+ "H": 49.9,
40
+ "HH": 49.9
41
+ },
42
+ {
43
+ "ItemName": "除害RO_E処理水_導電率",
44
+ "傾向": "LL接近下降傾向",
45
+ "傾き": -0.0172,
46
+ "最終値": 11.747,
47
+ "LL": 6.612,
48
+ "L": 7.225,
49
+ "H": 8.612,
50
+ "HH": 9.638
51
+ },
52
+ {
53
+ "ItemName": "除害RO_F処理水_導電率",
54
+ "傾向": "HH接近上昇傾向",
55
+ "傾き": 0.003,
56
+ "最終値": 2.882,
57
+ "LL": 8.062,
58
+ "L": 8.988,
59
+ "H": 10.15,
60
+ "HH": 10.588
61
+ },
62
+ {
63
+ "ItemName": "除害RO_G処理水_導電率",
64
+ "傾向": "HH逸脱上昇傾向",
65
+ "傾き": 0.0444,
66
+ "最終値": 19.593,
67
+ "LL": 6.212,
68
+ "L": 7.3,
69
+ "H": 8.862,
70
+ "HH": 12.562
71
+ },
72
+ {
73
+ "ItemName": "除害RO_H処理水_導電率",
74
+ "傾向": "LL接近下降傾向",
75
+ "傾き": -0.012,
76
+ "最終値": 8.729,
77
+ "LL": 7.075,
78
+ "L": 8.025,
79
+ "H": 8.988,
80
+ "HH": 9.438
81
+ },
82
+ {
83
+ "ItemName": "除害RO_I処理水_導電率",
84
+ "傾向": "HH接近上昇傾向",
85
+ "傾き": 0.0043,
86
+ "最終値": 7.273,
87
+ "LL": 6.388,
88
+ "L": 6.75,
89
+ "H": 7.538,
90
+ "HH": 7.9
91
+ },
92
+ {
93
+ "ItemName": "除害RO_J処理水_導電率",
94
+ "傾向": "LL接近下降傾向",
95
+ "傾き": -0.0109,
96
+ "最終値": 9.212,
97
+ "LL": 8.362,
98
+ "L": 8.612,
99
+ "H": 9.075,
100
+ "HH": 9.438
101
+ },
102
+ {
103
+ "ItemName": "除害RO_K処理水_導電率",
104
+ "傾向": "LL接近下降傾向",
105
+ "傾き": -0.0296,
106
+ "最終値": 46.721,
107
+ "LL": 23.625,
108
+ "L": 38.525,
109
+ "H": 49.925,
110
+ "HH": 49.938
111
+ },
112
+ {
113
+ "ItemName": "除害RO_L処理水_導電率",
114
+ "傾向": "LL接近下降傾向",
115
+ "傾き": -0.0069,
116
+ "最終値": 8.673,
117
+ "LL": 8.35,
118
+ "L": 8.762,
119
+ "H": 10.125,
120
+ "HH": 10.588
121
+ },
122
+ {
123
+ "ItemName": "除害RO_M処理水_導電率",
124
+ "傾向": "HH逸脱上昇傾向",
125
+ "傾き": 0.0034,
126
+ "最終値": 7.614,
127
+ "LL": 5.575,
128
+ "L": 5.738,
129
+ "H": 6.35,
130
+ "HH": 7.125
131
+ },
132
+ {
133
+ "ItemName": "除害RO_N処理水_導電率",
134
+ "傾向": "HH逸脱上昇傾向",
135
+ "傾き": 0.0292,
136
+ "最終値": 15.671,
137
+ "LL": 5.662,
138
+ "L": 6.25,
139
+ "H": 7.1,
140
+ "HH": 7.59
141
+ },
142
+ {
143
+ "ItemName": "除害RO_O処理水_導電率",
144
+ "傾向": "HH接近上昇傾向",
145
+ "傾き": 0.0001,
146
+ "最終値": 49.93,
147
+ "LL": 49.925,
148
+ "L": 49.925,
149
+ "H": 49.938,
150
+ "HH": 49.95
151
+ },
152
+ {
153
+ "ItemName": "除害RO_処理水_流量1",
154
+ "傾向": "HH接近上昇傾向",
155
+ "傾き": 0.2861,
156
+ "最終値": 199.512,
157
+ "LL": 210.9,
158
+ "L": 214.05,
159
+ "H": 218.7,
160
+ "HH": 298.05
161
+ },
162
+ {
163
+ "ItemName": "除害RO_処理水_流量2",
164
+ "傾向": "HH接近上昇傾向",
165
+ "傾き": 0.0919,
166
+ "最終値": 290.703,
167
+ "LL": 217.35,
168
+ "L": 280.5,
169
+ "H": 289.65,
170
+ "HH": 349.35
171
+ },
172
+ {
173
+ "ItemName": "除害RO 処理水 流量3",
174
+ "傾向": "LL接近下降傾向",
175
+ "傾き": -0.2295,
176
+ "最終値": 147.618,
177
+ "LL": 64.95,
178
+ "L": 143.025,
179
+ "H": 150.075,
180
+ "HH": 153.0
181
+ },
182
+ {
183
+ "ItemName": "除害RO_処理水_TOC1",
184
+ "傾向": "LL接近下降傾向",
185
+ "傾き": -0.0559,
186
+ "最終値": 44.986,
187
+ "LL": 39.75,
188
+ "L": 48.0,
189
+ "H": 63.25,
190
+ "HH": 82.0
191
+ },
192
+ {
193
+ "ItemName": "除害RO_処理水_TOC2",
194
+ "傾向": "HH接近上昇傾向",
195
+ "傾き": 0.0686,
196
+ "最終値": 46.997,
197
+ "LL": 37.5,
198
+ "L": 43.5,
199
+ "H": 56.0,
200
+ "HH": 74.75
201
+ }
202
+ ]