Xmia 1 月之前
父节点
当前提交
9d0de9b361
共有 2 个文件被更改,包括 66 次插入159 次删除
  1. 61 157
      Temp_Diag.PY
  2. 5 2
      api_tempdiag.py

+ 61 - 157
Temp_Diag.PY

@@ -55,8 +55,8 @@ class MSET_Temp:
         """
         table_name = f"{self.windCode}_minute"
         engine = create_engine(
-            # "mysql+pymysql://root:admin123456@106.120.102.238:10336/energy_data_prod"
-            "mysql+pymysql://root:admin123456@192.168.50.235:30306/energy_data_prod"
+            "mysql+pymysql://root:admin123456@106.120.102.238:10336/energy_data_prod"
+            # "mysql+pymysql://root:admin123456@192.168.50.235:30306/energy_data_prod"
         )
 
         # 准备 wind_turbine_number 列表的 SQL 片段:('WT1','WT2',...)
@@ -203,199 +203,103 @@ class MSET_Temp:
 
     def check_threshold(self) -> pd.DataFrame:
         """
-        阈值分析(阈值固定 0.99)。返回长格式 DataFrame,列:
-          ["time_stamp", "temp_channel", "SPRT_score", "status"]
-        status = "危险" if SPRT_score > 0.99 else "正常"。
+        阈值分析(阈值 0.99),长格式:
+        返回所有存在通道的数据,缺失的通道自动跳过。
         """
         THRESHOLD = 0.99
-
-        # 1) 按风机编号 + 时间范围查询原始数据
-        df_concat = self._get_data_by_filter()
-        if df_concat.empty:
+        df = self._get_data_by_filter()
+        if df.empty:
             return pd.DataFrame(columns=["time_stamp", "temp_channel", "SPRT_score", "status"])
 
-        # 2) 筛选存在的温度列
+        # 四个通道英文名
         temp_cols_all = [
             'main_bearing_temperature',
             'gearbox_oil_temperature',
             'generatordrive_end_bearing_temperature',
             'generatornon_drive_end_bearing_temperature'
         ]
-        temp_cols = [c for c in temp_cols_all if c in df_concat.columns]
+        # 只保留存在的列
+        temp_cols = [c for c in temp_cols_all if c in df.columns]
         if not temp_cols:
             return pd.DataFrame(columns=["time_stamp", "temp_channel", "SPRT_score", "status"])
 
-        # 3) 转数值 & 删除 NaN
-        df_concat[temp_cols] = df_concat[temp_cols].apply(pd.to_numeric, errors='coerce')
-        df_concat = df_concat.dropna(subset=temp_cols + ['time_stamp'])
-        if df_concat.empty:
-            return pd.DataFrame(columns=["time_stamp", "temp_channel", "SPRT_score", "status"])
-
-        # 4) time_stamp 转 datetime
-        df_concat['time_stamp'] = pd.to_datetime(df_concat['time_stamp'])
-        x_date = df_concat['time_stamp']
-
-        # 5) 抽取温度列到 NumPy 数组
-        arr = df_concat[temp_cols].values  # shape = [总记录数, 通道数]
-        m, n = arr.shape
-        half = m // 2
-
-        all_flags: list[list[float]] = []
-        for i in range(n):
-            channel = arr[:, i]
-            train = channel[:half].reshape(-1, 1)
-            test  = channel[half:].reshape(-1, 1)
-
-            # 用训练集构造 D/L 矩阵
-            if self.genDLMatrix(train, dataSize4D=60, dataSize4L=5) != 0:
-                # 如果训练集样本不足,直接返回空表
-                return pd.DataFrame(columns=["time_stamp", "temp_channel", "SPRT_score", "status"])
-
-            feature_w = np.array([1.0])
-            flags = self.calcSPRT(test, feature_w, decisionGroup=1)
-            all_flags.append(flags)
-
-        # 6) 合并为宽表,再 melt 成长表
-        flags_arr = np.array(all_flags)  # shape = [通道数, 测试样本数]
-        num_test = flags_arr.shape[1]
-        ts = x_date.iloc[half : half + num_test].reset_index(drop=True)
-
-        wide = pd.DataFrame({"time_stamp": ts})
-        for idx, col in enumerate(temp_cols):
-            wide[col] = flags_arr[idx, :]
-
-        df_long = wide.melt(
-            id_vars=["time_stamp"],
-            value_vars=temp_cols,
-            var_name="temp_channel",
-            value_name="SPRT_score"
-        )
-        # 把 time_stamp 从 datetime 转成字符串,格式 "YYYY-MM-DD HH:MM:SS" 
-        df_long['time_stamp'] = pd.to_datetime(df_long['time_stamp']).dt.strftime("%Y-%m-%d %H:%M:%S")
-
-        # 7) 添加状态列:SPRT_score > 0.99 → “危险”,否则 “正常”
-        df_long['status'] = df_long['SPRT_score'].apply(
-            lambda x: "危险" if x > THRESHOLD else "正常"
-        )
-
-        # 8) 将 temp_channel 列的英文名称改为中文
-        temp_channel_mapping = {
+        # 转数值 & 时间
+        df[temp_cols] = df[temp_cols].apply(pd.to_numeric, errors='coerce')
+        df['time_stamp'] = pd.to_datetime(df['time_stamp'], errors='coerce')
+        records = []
+        # 英文→中文映射
+        cn_map = {
             'main_bearing_temperature': '主轴承温度',
             'gearbox_oil_temperature': '齿轮箱油温',
             'generatordrive_end_bearing_temperature': '发电机驱动端轴承温度',
             'generatornon_drive_end_bearing_temperature': '发电机非驱动端轴承温度'
         }
 
-        df_long['temp_channel'] = df_long['temp_channel'].map(temp_channel_mapping)
+        for col in temp_cols:
+            sub = df[['time_stamp', col]].dropna()
+            if sub.empty:
+                continue
+            arr = sub[col].values.reshape(-1,1)
+            ts  = sub['time_stamp'].dt.strftime("%Y-%m-%d %H:%M:%S").tolist()
+            half = len(arr) // 2
+            train = arr[:half]
+            test  = arr[half:]
+            # 不足则跳过该通道
+            if self.genDLMatrix(train, dataSize4D=60, dataSize4L=5) != 0:
+                continue
+
+            flags = self.calcSPRT(test, np.array([1.0]), decisionGroup=1)
+            for i, score in enumerate(flags):
+                records.append({
+                    "time_stamp": ts[half + i],
+                    "temp_channel": cn_map[col],
+                    "SPRT_score": score,
+                    "status": "危险" if score > THRESHOLD else "正常"
+                })
 
-        return df_long
-    
+        return pd.DataFrame(records, columns=["time_stamp", "temp_channel", "SPRT_score", "status"])
 
     def get_trend(self) -> dict:
         """
-        趋势分析(SPRT_score)
+        趋势分析:对每个通道单独计算,缺失或训练不足时输出空结构。
         """
-        # 1) 按风机编号 + 时间范围查询原始数据
         df = self._get_data_by_filter()
-        # 如果没有任何数据,则四通道均为空
-        if df.empty:
-            return {
-                "data": {
-                    "main_bearing": {},
-                    "gearbox_oil": {},
-                    "generator_drive_end": {},
-                    "generator_nondrive_end": {}
-                },
-                "code": 200,
-                "message": "success"
-            }
-
-        # 2) 筛选存在的温度列
-        temp_cols_all = [
-            'main_bearing_temperature',
-            'gearbox_oil_temperature',
-            'generatordrive_end_bearing_temperature',
-            'generatornon_drive_end_bearing_temperature'
-        ]
-        temp_cols = [c for c in temp_cols_all if c in df.columns]
-        if not temp_cols:
-            return {
-                "data": {
-                    "main_bearing": {},
-                    "gearbox_oil": {},
-                    "generator_drive_end": {},
-                    "generator_nondrive_end": {}
-                },
-                "code": 200,
-                "message": "success"
-            }
-
-        # 3) 转数值 & 删除 NaN
-        df[temp_cols] = df[temp_cols].apply(pd.to_numeric, errors='coerce')
-        df = df.dropna(subset=temp_cols + ['time_stamp'])
-        if df.empty:
-            return {
-                "data": {
-                    "main_bearing": {},
-                    "gearbox_oil": {},
-                    "generator_drive_end": {},
-                    "generator_nondrive_end": {}
-                },
-                "code": 200,
-                "message": "success"
-            }
-
-        # 4) time_stamp 转 datetime 并排序
-        df['time_stamp'] = pd.to_datetime(df['time_stamp'])
-        df = df.sort_values('time_stamp').reset_index(drop=True)
-
-        # 5) 准备后半段时间戳列表
-        all_timestamps = df['time_stamp'].dt.strftime("%Y-%m-%d %H:%M:%S").tolist()
-        half = len(all_timestamps) // 2
-        trend_timestamps = all_timestamps[half:]
-
-        # 6) 计算每个通道的 SPRT_score
-        # 中文映射(如果需要保留中文名称可在这儿用,但输出不用)
-        # temp_channel_mapping = { ... }
-
-        # 初始化四通道输出结构,默认空对象
-        result_data = {
-            "main_bearing": {},
-            "gearbox_oil": {},
-            "generator_drive_end": {},
-            "generator_nondrive_end": {}
-        }
-        # key 映射:DataFrame 列名 -> 输出字段名
+        # 英文→输出字段名
         key_map = {
             'main_bearing_temperature': 'main_bearing',
             'gearbox_oil_temperature': 'gearbox_oil',
             'generatordrive_end_bearing_temperature': 'generator_drive_end',
             'generatornon_drive_end_bearing_temperature': 'generator_nondrive_end'
         }
+        # 预置结果
+        result = {v: {} for v in key_map.values()}
 
-        for col in temp_cols:
-            series = df[col].values
-            train = series[:half].reshape(-1, 1)
-            test  = series[half:].reshape(-1, 1)
-
-            # 生成 DL 矩阵并计算 SPRT
+        if df.empty:
+            return {"data": result, "code": 200, "message": "success"}
+
+        df['time_stamp'] = pd.to_datetime(df['time_stamp'], errors='coerce')
+        for col, out_key in key_map.items():
+            if col not in df.columns:
+                continue
+            sub = df[['time_stamp', col]].dropna()
+            if sub.empty:
+                continue
+            vals = pd.to_numeric(sub[col], errors='coerce').values
+            ts_list = sub['time_stamp'].dt.strftime("%Y-%m-%d %H:%M:%S").tolist()
+            half = len(vals) // 2
+            train = vals[:half].reshape(-1,1)
+            test  = vals[half:].reshape(-1,1)
+            # 训练不足时输出空列表
             if self.genDLMatrix(train, dataSize4D=60, dataSize4L=5) != 0:
-                flags = [None] * len(test)
+                flags = []
             else:
                 flags = self.calcSPRT(test, np.array([1.0]), decisionGroup=1)
-
-            # 填充对应 key
-            key = key_map[col]
-            result_data[key] = {
-                "timestamps": trend_timestamps,
+            result[out_key] = {
+                "timestamps": ts_list[half:],
                 "values": flags
             }
 
-        return {
-            "data": result_data,
-            "code": 200,
-            "message": "success"
-        }
+        return {"data": result, "code": 200, "message": "success"}
 
 
     # def get_trend(self) -> dict:

+ 5 - 2
api_tempdiag.py

@@ -57,6 +57,7 @@ async def route_threshold(input_data: TemperatureThresholdInput):
             },
             ...
           ]
+          "totalSize": 741
         },
         "code": 200,
         "message": "success"
@@ -70,7 +71,8 @@ async def route_threshold(input_data: TemperatureThresholdInput):
             endTime=input_data.endTime
         )
         records = analyzer.check_threshold().to_dict(orient="records")
-
+        
+        total = len(records)
         start = (input_data.pageNo - 1) * input_data.pageSize
         end   = start + input_data.pageSize
         paginated = records[start:end]
@@ -78,7 +80,8 @@ async def route_threshold(input_data: TemperatureThresholdInput):
         return {
             "data": {
                 "type": "temperature_threshold",
-                "records": paginated
+                "records": paginated,
+                "totalSize": total
             },
             "code": 200,
             "message": "success"