api.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. from flask import Flask, jsonify, request
  2. import requests
  3. from io import StringIO
  4. import pandas as pd
  5. import numpy as np
  6. from sklearn.linear_model import LinearRegression
  7. from sklearn.metrics import mean_squared_error
  8. from sklearn.model_selection import train_test_split
  9. import json
  10. app = Flask(__name__)
  11. def detect_outlier(data):
  12. # 计算平均值和标准差
  13. mean = np.mean(data)
  14. std = np.std(data)
  15. # 设定上下界
  16. lower = mean - 1 * std
  17. upper = mean + 1 * std
  18. # 创建一个空列表,用于存储新列的数据
  19. result = []
  20. # 遍历原列的数据,判断是否为异常值
  21. for x in data:
  22. # 如果小于下界或大于上界,认为是异常值,标记为1
  23. if x < lower or x > upper:
  24. result.append(1)
  25. # 否则认为是正常值,标记为0
  26. else:
  27. result.append(0)
  28. # 返回新列的数据
  29. return result
  30. # 异常值剔除
  31. @app.route('/abnormal', methods=['POST'])
  32. def process_data():
  33. try:
  34. # 从请求中获取数据
  35. data = request.get_json()
  36. # 从在线数据链接下载 CSV 数据
  37. data_url = data.get('url')
  38. response = requests.get(data_url)
  39. # 检查下载是否成功
  40. if response.status_code != 200:
  41. error_message = {'status': 200, 'message': 'Failed to download CSV data'}
  42. return jsonify(error_message)
  43. # 将 CSV 数据转换为 Pandas DataFrame
  44. response.encoding = 'UTF-8'
  45. csv_data = StringIO(response.text)
  46. dataframe = pd.read_csv(csv_data, index_col=False, encoding='UTF-8')
  47. # 对每一列的数据调用函数,生成新列
  48. for col in dataframe.columns:
  49. if col != '时间': # 跳过 时间列
  50. dataframe[col + '_是否异常'] = detect_outlier(dataframe[col]) # 新列的名字为原列名加_是否异常
  51. # 返回处理后的数据
  52. result = {'status': 200, 'data': dataframe.to_dict(orient='records'), 'msg': 'Successfully'}
  53. print(jsonify(result))
  54. return jsonify(result)
  55. except Exception as e:
  56. error_message = {'status': 500, 'message': str(e)}
  57. return jsonify(error_message)
  58. # 缺失值补全
  59. @app.route('/completion', methods=['POST'])
  60. def process_data1():
  61. try:
  62. # 从请求中获取数据
  63. data = request.get_json()
  64. # 从在线数据链接下载 CSV 数据
  65. data_url = data.get('url')
  66. response = requests.get(data_url)
  67. # 检查下载是否成功
  68. if response.status_code != 200:
  69. error_message = {'status': 500, 'message': 'Failed to download CSV data'}
  70. return jsonify(error_message)
  71. # 将 CSV 数据转换为 Pandas DataFrame
  72. response.encoding = 'UTF-8'
  73. csv_data = StringIO(response.text)
  74. dataframe = pd.read_csv(csv_data, index_col=False, encoding='UTF-8')
  75. # 用数值型列的平均值插补缺失值
  76. dataframe.fillna(dataframe.select_dtypes(include=np.number).mean().round(3), inplace=True)
  77. # 返回处理后的数据
  78. result = {'status': 200, 'data': dataframe.to_dict(orient='records')}
  79. return jsonify(result)
  80. except Exception as e:
  81. error_message = {'status': 500, 'message': str(e)}
  82. return jsonify(error_message)
  83. def alarm_suppression(alarms, threshold=0.6):
  84. """
  85. 输入:
  86. alarms: 报警序列,由 0 和 1 组成
  87. 输出:
  88. is_true_alarms: 是否是真的报警序列,由 True 和 False 组成
  89. """
  90. # 定义虚警门限
  91. # threshold = 0.6
  92. # 遍历报警序列,如果报警值超过门限,则认为是真的报警
  93. alarms = alarms.apply(pd.to_numeric, errors='coerce')
  94. # 遍历报警序列的每一列,如果列中的值超过门限,则认为是真的报警
  95. # is_true_alarms = alarms.apply(lambda col: col > threshold, axis=0)
  96. # 遍历每一列,创建新的列以标记是否是真实的报警
  97. for column_name in alarms:
  98. new_column_name = f"{column_name}_是否虚警"
  99. alarms[new_column_name] = alarms[column_name] > threshold
  100. return alarms
  101. def list_tran_json(list):
  102. str_json = json.dumps(list, ensure_ascii=False, indent=2)
  103. return str_json
  104. # 虚警抑制
  105. @app.route('/false_alarm', methods=['POST'])
  106. def process_data2():
  107. try:
  108. # 从请求中获取数据
  109. data = request.get_json()
  110. # 从在线数据链接下载 CSV 数据
  111. data_url = data.get('url')
  112. # 虚警门限
  113. threshold = data.get('threshold')
  114. faultCode = data.get('faultCode')
  115. threshold = 0.3
  116. response = requests.get(data_url)
  117. # 检查下载是否成功
  118. if response.status_code != 200:
  119. error_message = {'status': 500, 'message': 'Failed to download CSV data'}
  120. return jsonify(error_message)
  121. # 将 CSV 数据转换为 Pandas DataFrame
  122. response.encoding = 'UTF-8'
  123. csv_data = StringIO(response.text)
  124. dataframe = pd.read_csv(csv_data, index_col=False, encoding='UTF-8')
  125. columns_to_remove = ['时间', '故障名称']
  126. excluded_columns = [col for col in columns_to_remove if col in dataframe.columns]
  127. excluded_columns_data = dataframe[excluded_columns]
  128. dataframe = dataframe.drop(columns=excluded_columns, errors='ignore')
  129. # 用数值型列的平均值插补缺失值
  130. is_true_alarms = alarm_suppression(dataframe, float(threshold))
  131. # 返回处理后的数据
  132. # result_df = pd.DataFrame(is_true_alarms, columns=dataframe.columns)
  133. result_df = pd.concat([is_true_alarms, excluded_columns_data], axis=1)
  134. # 返回处理后的数据
  135. # result = {'status': 200, 'data': result_df.to_dict(orient='records')}
  136. data_json = [{'故障编码': faultCode, '是否虚警': '是'}]
  137. result = {'status': 200, 'data': data_json}
  138. return jsonify(result)
  139. except Exception as e:
  140. error_message = {'status': 500, 'message': str(e)}
  141. return jsonify(error_message)
  142. # 故障诊断
  143. @app.route('/fault_diagnosis', methods=['POST'])
  144. def process_data3():
  145. try:
  146. # 从请求中获取数据
  147. data = request.get_json()
  148. # 从在线数据链接下载 CSV 数据
  149. data_url = data.get('url')
  150. response = requests.get(data_url)
  151. # 检查下载是否成功
  152. if response.status_code != 200:
  153. error_message = {'status': 500, 'message': 'Failed to download CSV data'}
  154. return jsonify(error_message)
  155. # 将 CSV 数据转换为 Pandas DataFrame
  156. response.encoding = 'UTF-8'
  157. csv_data = StringIO(response.text)
  158. dataframe = pd.read_csv(csv_data, index_col=False, encoding='UTF-8')
  159. # 计算均值
  160. xm = np.mean(dataframe.iloc[:, 1])
  161. xstd = np.std(dataframe.iloc[:, 1]) # 标准差
  162. kur = ((sum((dataframe.iloc[:, 1] - xm) ** 4)) / len(dataframe.iloc[:, 1])) / (xstd ** 4) # 峭度
  163. # 结果图片上传
  164. # // 文件上传 http://localhost:9090/als/resource/oss/upload
  165. # 文件上传API ,返回结果 {
  166. # "code": 200,
  167. # "msg": "操作成功",
  168. # "data": {
  169. # "ossId": "236309167646711808"
  170. # }
  171. # }
  172. # python 调用 API 得到ossId 返回
  173. data1 = {"result" : "字符串结果", "ossId": 236309167646711808}
  174. result = {'status': 200, 'data': data1}
  175. # 最终返回结果
  176. return jsonify(result)
  177. except Exception as e:
  178. error_message = {'status': 500, 'message': str(e)}
  179. return jsonify(error_message)
  180. # 深度隔离
  181. @app.route('/fault_isolation', methods=['POST'])
  182. def process_data4():
  183. try:
  184. # 从请求中获取数据
  185. data = request.get_json()
  186. # 从在线数据链接下载 CSV 数据
  187. data_url = data.get('url')
  188. response = requests.get(data_url)
  189. # 检查下载是否成功
  190. if response.status_code != 200:
  191. error_message = {'status': 500, 'message': 'Failed to download CSV data'}
  192. return jsonify(error_message)
  193. # 将 CSV 数据转换为 Pandas DataFrame
  194. response.encoding = 'UTF-8'
  195. csv_data = StringIO(response.text)
  196. dataframe = pd.read_csv(csv_data, index_col=False, encoding='UTF-8')
  197. # 计算均值
  198. xm = np.mean(dataframe.iloc[:, 1])
  199. # 判断输出是否故障
  200. if xm > 0.1:
  201. result = {'status': 200, 'data': '发动机振动故障'}
  202. else:
  203. result = {'status': 200, 'data': '发动机振动正常'}
  204. return jsonify(result)
  205. except Exception as e:
  206. error_message = {'status': 500, 'message': str(e)}
  207. return jsonify(error_message)
  208. # 故障预测
  209. @app.route('/fault_prediction', methods=['POST'])
  210. def process_data5():
  211. try:
  212. # 从请求中获取数据
  213. data = request.get_json()
  214. # 从在线数据链接下载 CSV 数据
  215. data_url = data.get('url')
  216. response = requests.get(data_url)
  217. # 检查下载是否成功
  218. if response.status_code != 200:
  219. error_message = {'status': 500, 'message': 'Failed to download CSV data'}
  220. return jsonify(error_message)
  221. # 将 CSV 数据转换为 Pandas DataFrame
  222. response.encoding = 'UTF-8'
  223. csv_data = StringIO(response.text)
  224. dataframe = pd.read_csv(csv_data, index_col=False, encoding='UTF-8')
  225. X_train, X_test, y_train, y_test = train_test_split(dataframe.iloc[:, :-1], dataframe.iloc[:, -1],
  226. test_size=0.05, random_state=42)
  227. # 训练线性回归模型
  228. model = LinearRegression()
  229. model.fit(X_train, y_train)
  230. # 对测试集进行预测
  231. y_pred = model.predict(X_test)
  232. # 计算均方误差
  233. mse = mean_squared_error(y_test, y_pred)
  234. # 判断输出是否故障
  235. if np.mean(y_pred) > 2:
  236. result = {'status': 200, 'data': '发动机寿命后期'}
  237. else:
  238. result = {'status': 200, 'data': '发动机寿命前期'}
  239. return jsonify(result)
  240. except Exception as e:
  241. error_message = {'status': 500, 'message': str(e)}
  242. return jsonify(error_message)
  243. # 定义合理参数范围的字典,实际应用中需依据具体飞机型号及飞行手册设定
  244. PARAMETER_RANGES = {
  245. "发动机排气温度": (500, 1200), # 示例范围,单位:摄氏度
  246. "喘振值": (0.8, 1.2), # 示例范围,具体范围需根据实际情况设定
  247. "时间": None, # 时间一般不设定范围,但确保数据连续性
  248. "机匣加速": (-200, 200), # 示例范围,单位:m/s^2
  249. "机匣振幅": (0, 0.1), # 示例范围,单位:毫米
  250. "机匣频率": (50, 500), # 示例范围,单位:Hz
  251. "燃油流量": (0, 10), # 示例范围,单位:kg/s,具体根据发动机规格
  252. "风扇转子转速": (5000, 12000), # 示例范围,单位:RPM
  253. "高压压气机转子转数": (8000, 15000), # 示例范围,单位:RPM
  254. }
  255. def check_parameter_validity(value, range_info):
  256. """检查单个参数值是否在合理范围内"""
  257. if range_info is None or (value >= range_info[0] and value <= range_info[1]):
  258. return True
  259. return False
  260. def calculate_testability(df_flight_params: pd.DataFrame) -> float:
  261. """
  262. 根据飞参数据评估可测试性得分。
  263. 参数:
  264. df_flight_params (pd.DataFrame): 包含飞参数据的DataFrame。
  265. 返回:
  266. float: 可测试性得分,范围0-1,值越接近1表示数据越符合预期,可测试性越高。
  267. """
  268. total_rows = len(df_flight_params)
  269. valid_count = 0
  270. for param in PARAMETER_RANGES.keys():
  271. if param in df_flight_params.columns:
  272. # 检查该参数的每个值是否都在合理范围内
  273. valid_for_param = df_flight_params[param].apply(check_parameter_validity, args=(PARAMETER_RANGES[param],))
  274. valid_count += valid_for_param.sum()
  275. # 计算整体有效性百分比作为可测试性得分
  276. testability_score = valid_count / (total_rows * len(PARAMETER_RANGES)) if total_rows > 0 else 0
  277. return testability_score
  278. # 测试性
  279. @app.route('/testability', methods=['POST'])
  280. def process_data6():
  281. try:
  282. # 从请求中获取数据
  283. data = request.get_json()
  284. # 从在线数据链接下载 CSV 数据
  285. data_url = data.get('url')
  286. response = requests.get(data_url)
  287. # 检查下载是否成功
  288. if response.status_code != 200:
  289. error_message = {'status': 200, 'message': 'Failed to download CSV data'}
  290. return jsonify(error_message)
  291. # 将 CSV 数据转换为 Pandas DataFrame
  292. response.encoding = 'UTF-8'
  293. csv_data = StringIO(response.text)
  294. dataframe = pd.read_csv(csv_data, index_col=False, encoding='UTF-8')
  295. df_flight_params = pd.DataFrame(dataframe)
  296. # 计算可测试性得分
  297. testability = calculate_testability(df_flight_params)
  298. res = f"根据飞参数据评估,可测试性得分为: {testability:.2f}"
  299. result = {'status': 200, 'data': res}
  300. return jsonify(result)
  301. except Exception as e:
  302. error_message = {'status': 500, 'message': str(e)}
  303. return jsonify(error_message)
  304. app.debug = True
  305. if __name__ == '__main__':
  306. # 启动 Flask 应用
  307. app.run(debug=True, port=8888, host='0.0.0.0')