MTeguri commited on
Commit
1634454
·
1 Parent(s): 1b15187

Update README.md: Correct title and emoji, adjust color scheme

Browse files
Files changed (4) hide show
  1. .gitignore +3 -0
  2. README.md +3 -3
  3. app.py +173 -0
  4. requirements.txt +4 -0
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ .venv/
2
+ *.un~
3
+ .env
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
- title: Operation Data Analysis2
3
- emoji: 🐨
4
  colorFrom: gray
5
- colorTo: red
6
  sdk: gradio
7
  sdk_version: 5.44.1
8
  app_file: app.py
 
1
  ---
2
+ title: Operation Data Analysis
3
+ emoji: 🦀
4
  colorFrom: gray
5
+ colorTo: gray
6
  sdk: gradio
7
  sdk_version: 5.44.1
8
  app_file: app.py
app.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dotenv import load_dotenv
2
+ load_dotenv()
3
+
4
+ import os
5
+ # 環境変数から取得
6
+ SUPABASE_URL = os.environ.get('SUPABASE_URL')
7
+
8
+ SUPABASE_KEY = os.environ.get('SUPABASE_KEY')
9
+
10
+ import supabase
11
+ table_threshold = "Threshold_data"
12
+ table_sensor = "Sensor_data"
13
+ table_troubleshooting = "Troubleshooting_collection"
14
+
15
+ # クライアントの初期化
16
+ supabase_client = supabase.create_client(SUPABASE_URL, SUPABASE_KEY)
17
+
18
+ # データ取得 (初回のみ実行)
19
+ threshold_data = supabase_client.table(table_threshold).select("*").execute()
20
+ sensor_data = supabase_client.table(table_sensor).select("*").execute()
21
+ troubleshooting_data = supabase_client.table(table_troubleshooting).select("*").execute()
22
+
23
+ import pandas as pd
24
+ # データフレームへの変換 (初回のみ実行)
25
+ threshold_df = pd.DataFrame(threshold_data.data)
26
+ sensor_df = pd.DataFrame(sensor_data.data)
27
+ troubleshooting_df = pd.DataFrame(troubleshooting_data.data)
28
+
29
+ # Convert 'datetime' column to datetime objects (初回のみ実行)
30
+ sensor_df['datetime'] = pd.to_datetime(sensor_df['datetime'])
31
+
32
+
33
+ # 閾値チェック関数の定義
34
+ def check_thresholds(sensor_df_filtered, threshold_df): # Renamed parameter to clarify it's the filtered data
35
+ alerts = []
36
+
37
+ # '下限'と'上限'カラムを数値型に変換。変換できない値はNaNとする。
38
+ threshold_df['下限'] = pd.to_numeric(threshold_df['下限'], errors='coerce')
39
+ threshold_df['上限'] = pd.to_numeric(threshold_df['上限'], errors='coerce')
40
+
41
+ for _, row in threshold_df.iterrows():
42
+ metric = row["指標名"]
43
+ min_val = row["下限"]
44
+ max_val = row["上限"]
45
+ data_no = row["No."] # Get the 'No.' from threshold_df
46
+
47
+ # センサーデータに指標が存在しない場合はスキップ
48
+ if metric not in sensor_df_filtered.columns: # Use filtered data
49
+ continue
50
+
51
+ # センサーデータの該当カラムを数値型に変換。変換できない値はNaNとする。
52
+ sensor_metric_data = pd.to_numeric(sensor_df_filtered[metric], errors='coerce') # Use filtered data
53
+
54
+
55
+ for index, value in sensor_metric_data.items():
56
+ # Use the index from sensor_metric_data to get the timestamp from the filtered sensor_df passed to the function
57
+ # Ensure the index exists in the filtered sensor_df
58
+ if index in sensor_df_filtered.index:
59
+ timestamp = sensor_df_filtered.loc[index, "datetime"] if "datetime" in sensor_df_filtered.columns else index
60
+ else:
61
+ # Handle cases where the index might not be in the filtered dataframe (shouldn't happen with .copy() and .items())
62
+ continue
63
+
64
+
65
+ # 下限チェック
66
+ if pd.notna(min_val) and pd.notna(value) and value < min_val:
67
+ alerts.append({
68
+ "timestamp": timestamp,
69
+ "metric": metric,
70
+ "value": value,
71
+ "status": f"下限値 {min_val} 未満",
72
+ "data no.": data_no # Add the 'data no.'
73
+ })
74
+
75
+ # 上限チェック
76
+ if pd.notna(max_val) and pd.notna(value) and value > max_val:
77
+ alerts.append({
78
+ "timestamp": timestamp,
79
+ "metric": metric,
80
+ "value": value,
81
+ "status": f"上限値 {max_val} 超過",
82
+ "data no.": data_no # Add the 'data no.'
83
+ })
84
+
85
+ return pd.DataFrame(alerts)
86
+
87
+ # Gradioインターフェースの構築
88
+ import gradio as gr
89
+ import pandas as pd
90
+ import supabase
91
+ import datetime # Import datetime here as it's used in run_troubleshooting
92
+
93
+ # Assuming the data loading and check_thresholds function from the previous cell are available
94
+
95
+ # トラブルシューティング実行関数の定義
96
+ def run_troubleshooting():
97
+ try:
98
+ # Get current time and calculate the time 24 hours ago
99
+ current_time = datetime.datetime.now(datetime.timezone.utc)
100
+ time_24_hours_ago = current_time - datetime.timedelta(hours=24)
101
+
102
+ # Filter sensor data for the last 24 hours
103
+ # Use the globally available sensor_df and filter it each time the function is called
104
+ global sensor_df
105
+ recent_sensor_df = sensor_df[sensor_df['datetime'] >= time_24_hours_ago].copy()
106
+
107
+ # Ensure other dataframes are accessible (they are loaded globally once)
108
+ global threshold_df
109
+ global troubleshooting_df
110
+
111
+
112
+ # しきい値チェックの実行
113
+ alerts_df = check_thresholds(recent_sensor_df, threshold_df) # Pass the filtered data
114
+
115
+ # タイムスタンプごとのユニークなデータ番号の数をカウント
116
+ grouped_alerts = alerts_df.groupby('timestamp')['data no.'].nunique()
117
+ # 複数のデータ番号を持つタイムスタンプを抽出
118
+ multiple_data_nos_timestamps = grouped_alerts[grouped_alerts > 1].index.tolist()
119
+
120
+ # 複数の��ータ番号を持つタイムスタンプに該当するアラートをフィルタリング
121
+ filtered_alerts_df = alerts_df[alerts_df['timestamp'].isin(multiple_data_nos_timestamps)]
122
+
123
+ # タイムスタンプごとにデータ番号をリスト化
124
+ data_nos_by_timestamp = filtered_alerts_df.groupby('timestamp')['data no.'].unique().apply(list)
125
+
126
+ # 結果リストの作成
127
+ result_list = []
128
+ for timestamp, data_nos in data_nos_by_timestamp.items():
129
+ data_nos_str = ', '.join(map(str, data_nos))
130
+ result_list.append({"timestamp": timestamp, "data_nos": data_nos_str})
131
+
132
+ # 結果データフレームの作成
133
+ result_df = pd.DataFrame(result_list)
134
+
135
+ # If no alerts, return "異常ありません"
136
+ if result_df.empty:
137
+ return "過去24時間 異常ありません"
138
+
139
+ # トラブルシューティングデータフレームの指標番号リストを整数リストに変換
140
+ troubleshooting_indicator_lists = troubleshooting_df['指標No.'].str.split(',').apply(lambda x: [int(i) for i in x])
141
+ # 結果データフレームのデータ番号リストを整数リストに変換
142
+ result_data_nos_lists = result_df['data_nos'].str.split(', ').apply(lambda x: [int(i) for i in x])
143
+
144
+ # 出力テキストの生成
145
+ output_text = ""
146
+ for i, result_nos in enumerate(result_data_nos_lists):
147
+ result_timestamp = result_df.loc[i, 'timestamp']
148
+ for j, troubleshooting_nos in enumerate(troubleshooting_indicator_lists):
149
+ # 結果のデータ番号がトラブルシューティングの指標番号のスーパーセットであるか確認
150
+ if set(troubleshooting_nos).issubset(set(result_nos)):
151
+ troubleshooting_situation = troubleshooting_df.loc[j, 'シチュエーション\n(対応が必要な状況)']
152
+ troubleshooting_action = troubleshooting_df.loc[j, 'sub goal到達のために必要な行動\n(解決策)']
153
+
154
+ output_text += f"Timestamp: {result_timestamp}\n"
155
+ output_text += f"Trouble: {troubleshooting_situation}\n"
156
+ output_text += f"Troubleshooting: {troubleshooting_action}\n"
157
+ output_text += "-" * 20 + "\n" # 区切り線
158
+
159
+ return output_text
160
+ except Exception as e:
161
+ return f"エラーが発生しました: {type(e).__name__} - {e}"
162
+
163
+ # Gradioインターフェースの設定
164
+ iface = gr.Interface(
165
+ fn=run_troubleshooting,
166
+ inputs=None, # No direct input needed as it uses existing dataframes
167
+ outputs="text",
168
+ title="Troubleshooting Information",
169
+ description="Displays troubleshooting information based on sensor and threshold data."
170
+ )
171
+
172
+ # Gradioインターフェースの起動
173
+ iface.launch(mcp_server=True)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio[mcp]
2
+ supabase
3
+ numpy
4
+ python-dotenv