import networkx import pandas import wntr import numpy as np import pandas as pd import math import copy import sys import networkx as nx import pymetis import influxdb_api from datetime import datetime import random import itertools import os from tjnetwork import * from api.project_backup import CopyProjectEx import simulation import globals import influxdb_api import concurrent.futures from datetime import datetime, timedelta, timezone import matplotlib.pyplot as plt def manually_get_burst_time_SCADA_pressure(name: str, manually_burst_time: str, scheme_Type: str, scheme_Name: str): """ 手动模拟爆管时,获取对应的SCADA数据 :param name: 数据库名称 :param manually_burst_time: 手动模拟爆管时间,格式为 '2024-11-24T17:30:00+08:00' :param scheme_Type: 方案类型 :param scheme_Name: 方案名称 :return: """ influxdb_api.query_corresponding_query_id_and_element_id(name=name) pressure_api_query_ids_list = list(globals.scheme_pressure_ids.keys()) # print(pressure_api_query_ids_list) # 用节点作为SCADA压力监测点名称 pressure_SCADA_IDs_list = [list(globals.scheme_pressure_ids.values())] # print(pressure_SCADA_IDs_list) # pressure_SCADA_IDs_list替换sensor_name # pressure_SCADA_IDs_list = list(pressure_SCADA_IDs_list) # normal_SCADA_pressure替换predicted_p normal_SCADA_pressure = influxdb_api.query_SCADA_data_by_device_ID_and_time( query_ids_list=pressure_api_query_ids_list, query_time=manually_burst_time ) # print(normal_SCADA_pressure) # 用 scheme_pressure_ids 中对应的value替换字典中的key,并且将原字典中的value转换为数字后乘以100 normal_SCADA_pressure = { globals.scheme_pressure_ids.get(k, k): (float(v) * 100 if v is not None else None) for k, v in normal_SCADA_pressure.items() } # print(normal_SCADA_pressure) normal_SCADA_pressure = pd.Series(normal_SCADA_pressure) # burst_SCADA_pressure替换leak_monitored burst_SCADA_pressure = influxdb_api.query_scheme_SCADA_data_by_device_ID_and_time( query_ids_list=pressure_SCADA_IDs_list, query_time=manually_burst_time, scheme_Type=scheme_Type, scheme_Name=scheme_Name ) # print(burst_SCADA_pressure) burst_SCADA_pressure = { globals.scheme_pressure_ids.get(k, k): (float(v) if v is not None else None) for k, v in burst_SCADA_pressure.items() } print(burst_SCADA_pressure) burst_SCADA_pressure = pd.Series(burst_SCADA_pressure) return burst_SCADA_pressure, pressure_SCADA_IDs_list, normal_SCADA_pressure # 2025/03/22 def manually_get_burst_flow(scheme_Type: str, scheme_Name: str, burst_start_time: str, bucket1: str="scheme_simulation_result", bucket2: str="SCADA_data") -> float: """ 进行手动模拟时,用(模拟得到的流量 - 前一时刻正常的SCADA流量)作为爆管流量 :param scheme_Type: 方案类型 :param scheme_Name: 方案名称 :param burst_start_time: 方案模拟开始时间,格式为 '2024-11-24T17:30:00+08:00'。 :param bucket1: 方案模拟数据存储的 bucket 名称。 :param bucket2: SCADA数据存储的 bucket 名称。 :return: 最后返回 m3/s为单位的的漏损水量 """ client = influxdb_api.get_new_client() if not client.ping(): print("{} -- Failed to connect to InfluxDB.".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) query_api = client.query_api() # 将北京时间转换为 UTC 时间 beijing_time = datetime.fromisoformat(burst_start_time) utc_time = beijing_time.astimezone(timezone.utc) utc_scheme_start_time = utc_time - timedelta(seconds=1) utc_scheme_stop_time = utc_time + timedelta(seconds=1) # 构建 Flux 查询语句 flux_query1 = f''' from(bucket: "{bucket1}") |> range(start: {utc_scheme_start_time.isoformat()}, stop: {utc_scheme_stop_time.isoformat()}) |> filter(fn: (r) => r["scheme_Type"] == "{scheme_Type}" and r["scheme_Name"] == "{scheme_Name}" and r["_measurement"] == "scheme_source_outflow") ''' table1 = query_api.query(flux_query1) result1 = [] for table in table1: for record in table.records: result1.append({ "device_ID": record["device_ID"], "value": float(record["_value"]) * 3.6 # L/s 转换为 m3/h }) # print(result1) scheme_sim_flow = sum(item['value'] for item in result1) # print(scheme_sim_flow) # 构建查询 SCADA 数据的 Flux 语句 flux_query2 = f''' from(bucket: "{bucket2}") |> range(start: {utc_scheme_start_time.isoformat()}, stop: {utc_scheme_stop_time.isoformat()}) |> filter(fn: (r) => r["_measurement"] == "source_outflow_realtime") ''' table2 = query_api.query(flux_query2) result2 = [] for table in table2: for record in table.records: result2.append({ "device_ID": record["device_ID"], "value": float(record["_value"]) }) # print(result2) scada_flow = sum(item['value'] for item in result2) # print(scada_flow) client.close() burst_flow = (scheme_sim_flow - scada_flow) / 3600 return burst_flow # 2025/03/25 def cal_if_detect(burst_SCADA_pressure: pd.Series, normal_SCADA_pressure: pd.Series, min_dpressure: float): """ 判断是否开始监测 :param burst_SCADA_pressure: 爆管时刻各压力表数值 :param normal_SCADA_pressure: 正常时刻各压力表数值 :param min_dpressure: 设定的压降值阈值,单位m :return: """ dpressure = normal_SCADA_pressure - burst_SCADA_pressure print(dpressure) # print(dpressure.loc['J06198']) max_dpressure = dpressure.max() max_dpressure_index = dpressure.idxmax() print(max_dpressure_index) print('max_dpressure', max_dpressure,type(max_dpressure)) print('min_dpressure', min_dpressure,type(min_dpressure)) if max_dpressure >= min_dpressure: if_detect = 1 tag = '压降在识别范围内,开始识别。' else: if_detect = 0 tag = '爆管造成的的压力下降小于设定值,故不展开识别。' print(tag) return if_detect, tag ## Simulation Module # load inp def load_inp(name: str, before_burst_time: str) -> wntr.network.WaterNetworkModel: """ 返回wntr类型的正常管网模型 :param name: 数据库名字 :param before_burst_time: 爆管发生前的时间,格式为'2024-11-25T09:00:00+08:00', 如果为手动模拟,则与爆管发生时间为同一个;如果为自动模拟则为前一个水力步长的时间 :return: """ new_name = f'before_burst_{name}' if have_project(new_name): if is_project_open(new_name): close_project(new_name) delete_project(new_name) CopyProjectEx()(name, new_name, ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table']) open_project(new_name) simulation.run_simulation(name=new_name, simulation_type='manually_temporary', modify_pattern_start_time=before_burst_time) if is_project_open(new_name): close_project(new_name) delete_project(new_name) inp_file = f'./db_inp/{new_name}.db.inp' wn = wntr.network.WaterNetworkModel(inp_file) return wn # load inp information def read_inf_inp(wn): all_node = wn.node_name_list node_elevation = wn.query_node_attribute('elevation') node_coordinates = wn.query_node_attribute('coordinates') all_pipe = wn.pipe_name_list # 改_wz__________________________________ n_pipe = [] for p in all_pipe: pipe = wn.get_link(p) if pipe.initial_status == 0: # 状态为'Closed' n_pipe.append(p) candidate_pipe_init = list(set(all_pipe) - set(n_pipe)) pipe_start_node = wn.query_link_attribute('start_node_name', link_type=wntr.network.model.Pipe) pipe_end_node = wn.query_link_attribute('end_node_name', link_type=wntr.network.model.Pipe) pipe_length = wn.query_link_attribute('length') pipe_diameter = wn.query_link_attribute('diameter') return all_node, node_elevation, node_coordinates, candidate_pipe_init, pipe_start_node, pipe_end_node, pipe_length, pipe_diameter def read_inf_inp_other(wn): all_link = wn.link_name_list pipe_start_node_all = wn.query_link_attribute('start_node_name') pipe_end_node_all = wn.query_link_attribute('end_node_name') return all_link, pipe_start_node_all, pipe_end_node_all # 用新的漏损管道替换原管道 def simple_add_leak(wn, leak_mag, leak_pipe): whole_inf = dict() leak_pipe_self = wn.get_link(leak_pipe) pipe_diameter = leak_pipe_self.diameter pipe_length = leak_pipe_self.length pipe_roughness = leak_pipe_self.roughness pipe_minor_loss = leak_pipe_self.minor_loss # pipe_status = leak_pipe_self.status # pipe_check_valve = leak_pipe_self.check_valve pipe_start_node = leak_pipe_self.start_node_name pipe_end_node = leak_pipe_self.end_node_name # close the pipe # leak_pipe_self.status = 'Closed' wn.remove_link(leak_pipe) # add the pipe add_pipe1 = leak_pipe + 'A' add_pipe2 = leak_pipe + 'B' add_node = leak_pipe + '_' start_n = wn.get_node(pipe_start_node) end_n = wn.get_node(pipe_end_node) if start_n.node_type == 'Reservoir': end_n_elevation = end_n.elevation start_n_elevation = end_n_elevation elif end_n.node_type == 'Reservoir': start_n_elevation = start_n.elevation end_n_elevation = start_n_elevation else: end_n_elevation = end_n.elevation start_n_elevation = start_n.elevation elevation_self = (start_n_elevation + end_n_elevation) / 2 coordinates_self = ( (start_n.coordinates[0] + end_n.coordinates[0]) / 2, (start_n.coordinates[1] + end_n.coordinates[1])) wn.add_junction(add_node, base_demand=0, elevation=elevation_self, coordinates=coordinates_self) leak_node = wn.get_node(add_node) wn.add_pipe(add_pipe1, start_node_name=pipe_start_node, end_node_name=add_node, length=pipe_length / 2, diameter=pipe_diameter, roughness=pipe_roughness, minor_loss=pipe_minor_loss) wn.add_pipe(add_pipe2, start_node_name=pipe_end_node, end_node_name=add_node, length=pipe_length / 2, diameter=pipe_diameter, roughness=pipe_roughness, minor_loss=pipe_minor_loss) # simulation leak_node.add_demand(base=leak_mag, pattern_name='add_leak') whole_inf['leak_node_name'] = add_node whole_inf['add_pipe1'] = add_pipe1 whole_inf['add_pipe2'] = add_pipe2 whole_inf['leak_pipe'] = leak_pipe whole_inf['pipe_start_node'] = pipe_start_node whole_inf['pipe_end_node'] = pipe_end_node whole_inf['pipe_length'] = pipe_length whole_inf['pipe_diameter'] = pipe_diameter whole_inf['pipe_roughness'] = pipe_roughness whole_inf['pipe_minor_loss'] = pipe_diameter return wn, whole_inf, add_pipe1 def simple_recover_wn(wn, whole_inf): leak_node = wn.get_node(whole_inf['leak_node_name']) del leak_node.demand_timeseries_list[-1] # update wn.remove_link(whole_inf['add_pipe1']) wn.remove_link(whole_inf['add_pipe2']) wn.remove_node(whole_inf['leak_node_name']) # open the pipe # leak_pipe_self.status = 'Open' wn.add_pipe(whole_inf['leak_pipe'], start_node_name=whole_inf['pipe_start_node'], end_node_name=whole_inf['pipe_end_node'], length=whole_inf['pipe_length'], diameter=whole_inf['pipe_diameter'], roughness=whole_inf['pipe_roughness'], minor_loss=whole_inf['pipe_minor_loss']) return wn # 模拟管道漏损(而非节点漏损) def leak_simulation_pipe_dd_multi_pf(wn, leak_mag, leak_pipe, sensor_name, sensor_f_name): wn.options.hydraulic.demand_model = 'DD' leak_pipe_self = wn.get_link(leak_pipe) pipe_diameter = leak_pipe_self.diameter pipe_length = leak_pipe_self.length pipe_roughness = leak_pipe_self.roughness pipe_minor_loss = leak_pipe_self.minor_loss # pipe_status = leak_pipe_self.status # pipe_check_valve = leak_pipe_self.check_valve pipe_start_node = leak_pipe_self.start_node_name pipe_end_node = leak_pipe_self.end_node_name wn.remove_link(leak_pipe) # add the pipe add_pipe1 = leak_pipe + 'A' add_pipe2 = leak_pipe + 'B' add_node = leak_pipe + '_' start_n = wn.get_node(pipe_start_node) end_n = wn.get_node(pipe_end_node) if start_n.node_type == 'Reservoir': end_n_elevation = end_n.elevation start_n_elevation = end_n_elevation elif end_n.node_type == 'Reservoir': start_n_elevation = start_n.elevation end_n_elevation = start_n_elevation else: end_n_elevation = end_n.elevation start_n_elevation = start_n.elevation elevation_self = (start_n_elevation + end_n_elevation) / 2 coordinates_self = ( (start_n.coordinates[0] + end_n.coordinates[0]) / 2, (start_n.coordinates[1] + end_n.coordinates[1])) wn.add_junction(add_node, base_demand=0, elevation=elevation_self, coordinates=coordinates_self) leak_node = wn.get_node(add_node) wn.add_pipe(add_pipe1, start_node_name=pipe_start_node, end_node_name=add_node, length=pipe_length / 2, diameter=pipe_diameter, roughness=pipe_roughness, minor_loss=pipe_minor_loss) wn.add_pipe(add_pipe2, start_node_name=pipe_end_node, end_node_name=add_node, length=pipe_length / 2, diameter=pipe_diameter, roughness=pipe_roughness, minor_loss=pipe_minor_loss) # simulation leak_node.add_demand(base=leak_mag, pattern_name='add_leak') sim = wntr.sim.EpanetSimulator(wn) results = sim.run_sim() del leak_node.demand_timeseries_list[-1] pressure_output_all = results.node['pressure'][sensor_name] pressure_output = pressure_output_all if leak_pipe in sensor_f_name: f_sensor_name = [add_pipe1 if i == leak_pipe else i for i in sensor_f_name] flow_output = results.link['flowrate'][f_sensor_name] flow_output.columns = sensor_f_name else: flow_output = results.link['flowrate'][sensor_f_name] # update wn.remove_link(add_pipe1) wn.remove_link(add_pipe2) wn.remove_node(add_node) # open the pipe # leak_pipe_self.status = 'Open' wn.add_pipe(leak_pipe, start_node_name=pipe_start_node, end_node_name=pipe_end_node, length=pipe_length, diameter=pipe_diameter, roughness=pipe_roughness, minor_loss=pipe_minor_loss) return wn, pressure_output, flow_output # def 2 normal simulation 正常工况下的水力模拟 def normal_simulation_pf(wn: wntr.network.WaterNetworkModel, pressure_SCADA_IDs_list: list[str], flow_SCADA_IDs_list: list[str]): """ 在正常(无漏损)状态下进行水力仿真,并返回监测点压力、流量、全局压力分布、最低压力点(top_sensor)以及总需水量。 :param wn: wntr类型的管网模型 :param pressure_SCADA_IDs_list: 监测的节点压力的ID构成的列表 :return: pressure, basic_p, top_sensor, sum_demand """ sim = wntr.sim.EpanetSimulator(wn) results = sim.run_sim() pressure_all = results.node['pressure'][pressure_SCADA_IDs_list] pressure = pressure_all.iloc[0] demand_all = results.node['demand'] demand = demand_all.iloc[0] sum_demand: float = cal_sum_demand(demand) flow_all = results.link['flowrate'][flow_SCADA_IDs_list] flow = flow_all.iloc[0] top_sensor: str = pressure.idxmin() basic_p = results.node['pressure'] basic_p = basic_p.iloc[0] return pressure, flow, basic_p, top_sensor, sum_demand def normal_simulation_multi_pf(wn: wntr.network.WaterNetworkModel, pressure_SCADA_IDs_list: list[str], flow_SCADA_IDs_list: list[str]): # inp_time = 0 sim = wntr.sim.EpanetSimulator(wn) results = sim.run_sim() pressure_all = results.node['pressure'][pressure_SCADA_IDs_list] pressure = pressure_all demand_all = results.node['demand'] demand = demand_all flow = results.link['flowrate'][flow_SCADA_IDs_list] sum_demand = pd.Series(dtype=object) for i in range(len(demand.index)): sum_demand[str(demand.index[i])] = cal_sum_demand(demand.iloc[i]) if type(pressure) == pd.core.series.Series: top_sensor = pressure.idxmin() else: mean_pressure = pressure.mean() top_sensor = mean_pressure.idxmin() basic_p = results.node['pressure'] return pressure, flow, basic_p, top_sensor, sum_demand # leak_pipe:模拟漏损管道 # 获取模拟漏损后的压力(流量)监测点处压力(流量) def simple_simulation_pf(wn, sensor_name, sensor_f_name, leak_pipe, add_pipe1): sim = wntr.sim.EpanetSimulator(wn) results = sim.run_sim() pressure_all = results.node['pressure'][sensor_name] if len(leak_pipe) > 0 and leak_pipe in sensor_f_name: f_sensor_name = [add_pipe1 if i == leak_pipe else i for i in sensor_f_name] flow_all = results.link['flowrate'][f_sensor_name] flow_all.columns = sensor_f_name else: flow_all = results.link['flowrate'][sensor_f_name] return pressure_all, flow_all def cal_sum_demand(demand): sum_demand = 0 for i in range(len(demand)): if demand.iloc[i] > 0: sum_demand += demand.iloc[i] return sum_demand def pick_center_pipe(node_x, node_y, candidate_pipe, pipe_start_node, pipe_end_node): data_set_t = pd.DataFrame(dtype=object) data_set_t['x'] = (node_x[pipe_start_node[candidate_pipe]].values + node_x[ pipe_start_node[candidate_pipe]].values) / 2 data_set_t['y'] = (node_y[pipe_end_node[candidate_pipe]].values + node_y[pipe_end_node[candidate_pipe]].values) / 2 data_set_t.index = list(candidate_pipe) mean_x = data_set_t['x'].mean() mean_y = data_set_t['y'].mean() data_set_t['d'] = abs(data_set_t['x'] - mean_x) + abs(data_set_t['y'] - mean_y) distance_t = data_set_t['d'].sort_values(ascending=True, inplace=False) '''if distance_t.index==[]: print(candidate_pipe) else:''' center_t = distance_t.index[0] return center_t def find_new_center_pipe(node_x, node_y, candidate_pipe, pipe_start_node, pipe_end_node, record_center): new_candidate_pipe = list(set(candidate_pipe) - set(record_center)) if new_candidate_pipe == []: new_candidate_pipe = candidate_pipe center_t = pick_center_pipe(node_x, node_y, new_candidate_pipe, pipe_start_node, pipe_end_node) return center_t # 根据计算的爆管相关节点求出相关的爆管管段 def cal_area_node_linked_pipe(nodeset, node_pipe_dic): pipeset = [] nodeset = list(nodeset) for i in range(len(nodeset)): temp_node = nodeset[i] pipe = node_pipe_dic[temp_node] pipeset = pipeset + pipe return pipeset # kmeans 聚类后的拓扑优化 # 构建整个图 def construct_graph(wn): length = wn.query_link_attribute('length') G = wn.get_graph(wn, link_weight=length) # 转为无向图 G0 = G.to_undirected() # A0 = np.array(nx.adjacency_graph(G0).todense()) return G0 # , A0 # cal metis grouping def metis_grouping_pipe_weight(G0, wn, all_node_iter, candidate_pipe_input, group_num, node_x, node_y, pipe_start_node_all, pipe_end_node_all, node_pipe_dic, all_node_series, couple_node_length): all_node_iter_series_new = all_node_series[all_node_iter] all_node_iter_series_new = all_node_iter_series_new.sort_values(ascending=True) all_node_iter_new = list(all_node_iter_series_new.index) G1 = G0.subgraph(all_node_iter_new) delimiter = ' ' adjacency_list = [] node_dict = {} c_new = 0 for each_node in all_node_iter_new: node_dict[each_node] = c_new c_new = c_new + 1 correspond_dic = {} count_node = 0 w = [] for line in generate_adjlist_with_all_edges(G1, delimiter): temp_node_name = line.split(sep=delimiter) w_temp = [] for i in range(len(temp_node_name) - 1): temp_name_1 = temp_node_name[0] + ',' + temp_node_name[i + 1] w_temp.append(couple_node_length[temp_name_1]) w.append(w_temp) n_t = [] for each_node in temp_node_name: n_t.append(node_dict[each_node]) correspond_dic[n_t[0]] = count_node count_node = count_node + 1 # del n_t[0] adjacency_list.append(n_t) adjacency_list_new = [[] * 1 for i in range(len(adjacency_list))] w_new = [[] * 1 for i in range(len(adjacency_list))] for i in range(len(adjacency_list)): adjacency_list_new[int(adjacency_list[i][0])] = adjacency_list[i] w_new[int(adjacency_list[i][0])] = w[i] for i in range(len(adjacency_list)): del adjacency_list_new[i][0] xadj = [0] w_f = [] final_adjacency_list = [] for i in range(len(adjacency_list_new)): final_adjacency_list = final_adjacency_list + adjacency_list_new[i] xadj.append(len(final_adjacency_list)) w_f = w_f + w_new[i] # (edgecuts, parts) = pymetis.part_graph(nparts=group_num, adjacency=adjacency_list_new) (edgecuts, parts) = pymetis.part_graph(nparts=group_num, adjncy=final_adjacency_list, xadj=xadj, eweights=w_f) # (edgecuts, parts) = pymetis.part_graph(nparts=group_num, adjacency=adjacency_list_new) candidate_group_list = [[] * 1 for i in range(group_num)] for i in range(len(all_node_iter_new)): candidate_group_list[parts[i]].append(all_node_iter_new[i]) '''parts_new = np.zeros(len(candidate_node_input), dtype=int) for i in range(len(candidate_group_list)): temp_group = candidate_group_list[i] for each_node in temp_group: parts_new[node_dict[each_node]] = i parts_new = list(parts_new)''' new_center = [] new_group = [] new_all_node = [] candidate_pipe_set = set(candidate_pipe_input) all_grouped_pipe = [] for i in range(group_num): # 构建子图 G_sub = G0.subgraph(candidate_group_list[i]) # 计算联通子图 sub_graphs = networkx.connected_components(G_sub) if networkx.number_connected_components(G_sub) == 1: # 求交集 nodeset = G_sub.nodes() pipeset_set = set(cal_area_node_linked_pipe(nodeset, node_pipe_dic)) candidate_pipe = list(pipeset_set.intersection(candidate_pipe_set)) # 判断集合是否保留 if len(candidate_pipe) > 0: # 保留 计算中心 center_t = pick_center_pipe(node_x, node_y, candidate_pipe, pipe_start_node_all, pipe_end_node_all) # 更新 new_center.append(center_t) new_group.append(candidate_pipe) new_all_node.append(nodeset) all_grouped_pipe = all_grouped_pipe + candidate_pipe else: for c in sub_graphs: G_temp = G0.subgraph(c) nodeset = G_temp.nodes() pipeset = cal_area_node_linked_pipe(nodeset, node_pipe_dic) pipeset_set = set(pipeset) # 求交集 candidate_pipe = list(pipeset_set.intersection(candidate_pipe_set)) # print(len(candidate_node)) # 判断集合是否保留 if len(candidate_pipe) > 0: # 保留 计算中心 center_t = pick_center_pipe(node_x, node_y, candidate_pipe, pipe_start_node_all, pipe_end_node_all) # 更新 new_center.append(center_t) new_group.append(candidate_pipe) new_all_node.append(nodeset) all_grouped_pipe = all_grouped_pipe + candidate_pipe record_center = [] c_g = 0 for each_group in new_group: if len(each_group) < 3: record_center.append(new_center[c_g]) c_g += 1 c_g = 0 for each_group in new_group: if len(each_group) >= 3: if new_center[c_g] in record_center: new_center[c_g] = find_new_center_pipe(node_x, node_y, each_group, pipe_start_node_all, pipe_end_node_all, record_center) record_center.append(new_center[c_g]) c_g += 1 visualize_metis_partition( G0, new_center, new_group, node_x, node_y, pipe_start_node_all, pipe_end_node_all ) return new_center, new_group, new_all_node def visualize_metis_partition( G, center_pipes, pipe_groups, node_x, node_y, pipe_start_node_all, pipe_end_node_all ): """ 可视化METIS分区结果(单图模式) 参数: G: 原始管网图(nx.Graph) center_pipes: 中心管道列表(list) pipe_groups: 分组管道列表(list of lists) node_x: 节点X坐标字典(dict) node_y: 节点Y坐标字典(dict) pipe_start_node_all: 管道起点字典(dict) pipe_end_node_all: 管道终点字典(dict) """ plt.figure(figsize=(9, 10)) # 生成颜色映射(自动扩展颜色数量) colors = plt.cm.tab20(np.linspace(0, 1, len(pipe_groups))) # --- 绘制背景管网(灰色半透明) --- for edge in G.edges(): start_node, end_node = edge plt.plot( [node_x[start_node], node_x[end_node]], [node_y[start_node], node_y[end_node]], color='lightgray', linewidth=0.5, alpha=0.3, zorder=1 # 确保背景在底层 ) # --- 绘制各分区管道(彩色)--- legend_handles = [] # 用于图例的句柄 for i, (group, center) in enumerate(zip(pipe_groups, center_pipes)): color = colors[i % len(colors)] # 循环使用颜色 # 绘制分组管道 for pipe in group: start = pipe_start_node_all[pipe] end = pipe_end_node_all[pipe] line = plt.plot( [node_x[start], node_x[end]], [node_y[start], node_y[end]], color=color, linewidth=2.5, alpha=0.8, zorder=2 ) # 只为每个分组的第一个管道添加图例句柄 if pipe == group[0]: legend_handles.append(line[0]) # 高亮中心管道(红色虚线) if center in pipe_start_node_all and center in pipe_end_node_all: start = pipe_start_node_all[center] end = pipe_end_node_all[center] plt.plot( [node_x[start], node_x[end]], [node_y[start], node_y[end]], color='red', linewidth=4, linestyle='--', dash_capstyle='round', zorder=3 # 确保中心管道在最顶层 ) # --- 添加图例和标注 --- # 分组图例 group_labels = [f'Group {i + 1}' for i in range(len(pipe_groups))] plt.legend( legend_handles, group_labels, loc='upper right', title="Partitions", fontsize=8, title_fontsize=10 ) # 中心管道标注(可选) for i, center in enumerate(center_pipes): if center in pipe_start_node_all: x = (node_x[pipe_start_node_all[center]] + node_x[pipe_end_node_all[center]]) / 2 y = (node_y[pipe_start_node_all[center]] + node_y[pipe_end_node_all[center]]) / 2 plt.text( x, y, f'C{i + 1}', color='red', fontsize=10, ha='center', va='center', bbox=dict(facecolor='white', alpha=0.8, edgecolor='none') ) # --- 图形美化 --- plt.title("Water Network Partitioning Overview", fontsize=14, pad=20) plt.xlabel("X Coordinate", fontsize=10) plt.ylabel("Y Coordinate", fontsize=10) plt.grid(True, alpha=0.2, linestyle=':') plt.tight_layout() # 显示图形 plt.show() # def generate_adjlist_with_all_edges(G, delimiter): for s, nbrs in G.adjacency(): line = str(s) + delimiter for t, data in nbrs.items(): line += str(t) + delimiter yield line[: -len(delimiter)] # # Similarity matching module def cal_similarity_simple_return_dd(similarity_mode, monitor_p, predict_p, normal_p, leak_p, monitor_p_all, predict_p_all, normal_p_all, leak_p_all, important_sensor, mean_dpressure, dpressure_std, dpressure_std_all, if_gy=0, cos_or_flow=1): # cos_or_flow 用于 CAF dpressure_s = normal_p - leak_p dpressure = predict_p - monitor_p act_dpressure = pd.Series(dtype=object) for i in range(len(leak_p.index)): if dpressure_std.iloc[i] > -200: # 0.001: if if_gy == 1: act_dpressure[leak_p.index[i]] = (leak_p.iloc[i] - monitor_p.iloc[i]) / dpressure_std.iloc[i] else: act_dpressure[leak_p.index[i]] = leak_p.iloc[i] - monitor_p.iloc[i] if similarity_mode == 'COS' or (similarity_mode == 'CAF' and cos_or_flow == 1): '''if leak_p.min()<0: none_flag = 1 similarity_cos = 0 similarity_dis = 0 else:''' none_flag = 0 sensor_for_cos = list(set(dpressure_s.index).intersection(set(act_dpressure.index))) '''if len(dpressure_s) ==0 or len(dpressure) ==0: jj=9 else:''' try: s1 = np.dot(np.transpose(dpressure_s.loc[sensor_for_cos]), dpressure.loc[sensor_for_cos]) s2 = np.linalg.norm(dpressure_s.loc[sensor_for_cos]) * np.linalg.norm(dpressure.loc[sensor_for_cos]) if s2 == 0: s2 = s2 + 0.0001 similarity_cos = s1 / s2 similarity_dis = 0 except Exception as e: print(dpressure_s) print(sensor_for_cos) print(act_dpressure) print(dpressure_std) print(dpressure) elif similarity_mode == 'DIS' or (similarity_mode == 'CAF' and cos_or_flow == 2): '''if leak_p.min()<0: none_flag = 1 else:''' none_flag = 0 important_sensor = list(set(important_sensor).intersection(set(act_dpressure.index))) part_dpressure = dpressure_s[important_sensor] - dpressure[important_sensor] similarity_pre_DIS = np.linalg.norm(part_dpressure) # similarity_pre_DIS_later = 1 / (1 + similarity_pre_DIS) similarity_dis = similarity_pre_DIS similarity_cos = 0 elif similarity_mode == 'CAD_new': act_dpressure = leak_p - monitor_p '''if leak_p.min() < 0: none_flag = 1 similarity_cos = 0 similarity_dis =0 else:''' none_flag = 0 # cos s1 = np.dot(np.transpose(dpressure_s), dpressure) s2 = np.linalg.norm(dpressure_s) * np.linalg.norm(dpressure) if s2 == 0: s2 = s2 + 0.0001 similarity_cos = s1 / s2 # DIS part_dpressure = act_dpressure.loc[important_sensor] similarity_pre_DIS = np.linalg.norm(part_dpressure) similarity_pre_DIS_later = 1 / (1 + similarity_pre_DIS) similarity_dis = similarity_pre_DIS elif similarity_mode == 'CAD_new_gy' or similarity_mode == 'CDF': # cos sensor_for_cos = list(set(dpressure_s.index).intersection(set(act_dpressure.index))) if len(sensor_for_cos) == 0 and len(dpressure_s) == 0: similarity_cos = 0 elif len(sensor_for_cos) == 0 and len(dpressure_s) > 0: sensor_for_cos = list(dpressure_s.index) none_flag = 0 s1 = np.dot(np.transpose(dpressure_s.loc[sensor_for_cos]), dpressure.loc[sensor_for_cos]) s2 = np.linalg.norm(dpressure_s.loc[sensor_for_cos]) * np.linalg.norm(dpressure.loc[sensor_for_cos]) if s2 == 0: s2 = s2 + 0.0001 similarity_cos = s1 / s2 else: none_flag = 0 s1 = np.dot(np.transpose(dpressure_s.loc[sensor_for_cos]), dpressure.loc[sensor_for_cos]) s2 = np.linalg.norm(dpressure_s.loc[sensor_for_cos]) * np.linalg.norm(dpressure.loc[sensor_for_cos]) if s2 == 0: s2 = s2 + 0.0001 similarity_cos = s1 / s2 # DIS important_sensor_new = list(set(important_sensor).intersection(set(act_dpressure.index))) if len(important_sensor_new) == 0: important_sensor_new = important_sensor act_dpressure = pd.Series(dtype=object) for i in range(len(leak_p_all.index)): # if dpressure_std.iloc [i] > -200: # 0.001: if if_gy == 1: act_dpressure[leak_p_all.index[i]] = (leak_p_all.iloc[i] - monitor_p_all.iloc[i]) / \ dpressure_std_all.iloc[i] else: act_dpressure[leak_p_all.index[i]] = leak_p_all.iloc[i] - monitor_p_all.iloc[i] # part_dpressure = act_dpressure.loc[important_sensor_new] part_dpressure = (dpressure.loc[important_sensor_new] - dpressure_s.loc[important_sensor_new]) similarity_pre_DIS = np.linalg.norm(part_dpressure) ## chang test # part_dpressure = dpressure_s.loc[important_sensor]-dpressure.loc[important_sensor] # similarity_pre_DIS = np.linalg.norm(part_dpressure) # similarity_pre_DIS_later = 1 / (1 + similarity_pre_DIS) similarity_dis = similarity_pre_DIS elif similarity_mode == 'OF': # cos similarity_cos = 0 none_flag = 0 # DIS important_sensor_new = list(set(important_sensor).intersection(set(act_dpressure.index))) if len(important_sensor_new) == 0: important_sensor_new = important_sensor act_dpressure = pd.Series(dtype=object) for i in range(len(leak_p_all.index)): # if dpressure_std.iloc [i] > -200: # 0.001: if if_gy == 1: act_dpressure[leak_p_all.index[i]] = (leak_p_all.iloc[i] - monitor_p_all.iloc[i]) / \ dpressure_std_all.iloc[i] else: act_dpressure[leak_p_all.index[i]] = leak_p_all.iloc[i] - monitor_p_all.iloc[i] # part_dpressure = act_dpressure.loc[important_sensor_new] part_dpressure = (dpressure.loc[important_sensor_new] - dpressure_s.loc[important_sensor_new]) similarity_pre_DIS = np.linalg.norm(part_dpressure) ## chang test # part_dpressure = dpressure_s.loc[important_sensor]-dpressure.loc[important_sensor] # similarity_pre_DIS = np.linalg.norm(part_dpressure) # similarity_pre_DIS_later = 1 / (1 + similarity_pre_DIS) similarity_dis = similarity_pre_DIS return similarity_cos, similarity_dis, none_flag def adjust(similarity_cos, similarity_dis, record_success_candidate, record_success_no_candidate): if len(record_success_no_candidate) > 0: for each in record_success_no_candidate: similarity_cos[each] = similarity_cos[record_success_candidate].min() * 0.9 similarity_dis[each] = similarity_dis[record_success_candidate].max() * 1.1 return similarity_cos, similarity_dis def cal_sq_all_multi(similarity_cos, similarity_dis, similarity_f, candidate_pipe, timestep_list_spc, if_flow, if_only_cos, if_only_flow, cos_h_input, dis_h_input, dis_f_h_input, if_compalsive, cos_sensor_num, flow_sensor_num): if if_only_flow == 1: similarity_f, h_f = cal_sq_single_array(similarity_f.values.reshape((-1, 1)), if_direct=2) sq_cos = 0 sq_dis = 0 sq_f = 1 similarity_all = similarity_f * sq_f output_similarity = similarity_all.reshape((-1, len(candidate_pipe))) output_similarity_pd = pd.DataFrame(output_similarity, index=timestep_list_spc, columns=candidate_pipe) else: if if_only_cos == 0: if if_flow == 1: # standerdize similarity_cos, h_cos = cal_sq_single_array(similarity_cos.values.reshape((-1, 1)), if_direct=1) similarity_dis, h_dis = cal_sq_single_array(similarity_dis.values.reshape((-1, 1)), if_direct=2) similarity_f, h_f = cal_sq_single_array(similarity_f.values.reshape((-1, 1)), if_direct=2) if if_compalsive == 1: sq_cos = cos_h_input sq_dis = dis_h_input sq_f = dis_f_h_input else: '''sq_cos = h_cos/(h_cos +h_dis +h_f ) sq_dis = h_dis/(h_cos +h_dis +h_f ) sq_f = h_f/(h_cos +h_dis +h_f )''' sq_cos, sq_dis, sq_f = add_weight_for_SQ(h_cos, h_dis, h_f, cos_sensor_num, flow_sensor_num) '''if cos_sensor_num == 2 and sq_cos>0.2: sq_cos = 0.2 sq_dis = 0.8*h_dis / (h_dis + h_f) sq_f = 0.8*h_f / (h_dis + h_f) if cos_sensor_num == 1 and sq_dis > 0.3: sq_cos = 0.1 sq_dis = 0.3 sq_f = 0.6''' sq_cos, sq_dis, sq_f = adjust_ratio('CDF', sq_cos, sq_dis, sq_f) if cos_sensor_num <= 1: sq_cos = 0 # similarity similarity_all = similarity_cos * sq_cos + similarity_dis * sq_dis + similarity_f * sq_f output_similarity = similarity_all.reshape((-1, len(candidate_pipe))) output_similarity_pd = pd.DataFrame(output_similarity, index=timestep_list_spc, columns=candidate_pipe) else: # standerdize similarity_cos, h_cos = cal_sq_single_array(similarity_cos.values.reshape((-1, 1)), if_direct=1) similarity_dis, h_dis = cal_sq_single_array(similarity_dis.values.reshape((-1, 1)), if_direct=2) if if_compalsive == 1: sq_cos = cos_h_input sq_dis = dis_h_input else: sq_cos = h_cos / (h_cos + h_dis) sq_dis = h_dis / (h_cos + h_dis) if cos_sensor_num == 2 and sq_cos > 0.5: sq_cos = 0.5 sq_dis = 0.5 sq_cos, sq_dis, sq_f = adjust_ratio('CAD_new_gy', sq_cos, sq_dis, 0) sq_f = 0 # similarity similarity_all = similarity_cos * sq_cos + similarity_dis * sq_dis output_similarity = similarity_all.reshape((-1, len(candidate_pipe))) output_similarity_pd = pd.DataFrame(output_similarity, index=timestep_list_spc, columns=candidate_pipe) elif if_only_cos == 1: if if_flow == 1: # standerdize similarity_cos, h_cos = cal_sq_single_array(similarity_cos.values.reshape((-1, 1)), if_direct=1) similarity_f, h_f = cal_sq_single_array(similarity_f.values.reshape((-1, 1)), if_direct=1) # if_direct=2 if if_compalsive == 1: sq_cos = cos_h_input sq_f = dis_f_h_input else: sq_cos = h_cos / (h_cos + h_f) sq_f = h_f / (h_cos + h_f) sq_cos, sq_dis, sq_f = adjust_ratio('CAF', sq_cos, 0, sq_f) sq_dis = 0 # similarity similarity_all = similarity_cos * sq_cos + similarity_f * sq_f output_similarity = similarity_all.reshape((-1, len(candidate_pipe))) output_similarity_pd = pd.DataFrame(output_similarity, index=timestep_list_spc, columns=candidate_pipe) else: sq_cos = cos_h_input sq_dis = dis_h_input sq_f = dis_f_h_input output_similarity_pd = similarity_cos else: sq_cos = cos_h_input sq_dis = dis_h_input sq_f = dis_f_h_input output_similarity_pd = 1 / (similarity_dis + 1) return output_similarity_pd, sq_cos, sq_dis, sq_f def add_weight_for_SQ(h_cos, h_dis, h_f, sensor_cos_num, sensor_f_num): h_f_new = h_f * sensor_f_num if sensor_cos_num <= 1: h_cos_new = 0 h_dis_new = h_dis * sensor_cos_num else: h_cos_new = h_cos * sensor_cos_num # / 2 h_dis_new = h_dis * sensor_cos_num # / 2 cos_sq = h_cos_new / (h_cos_new + h_dis_new + h_f_new) dis_sq = h_dis_new / (h_cos_new + h_dis_new + h_f_new) f_sq = h_f_new / (h_cos_new + h_dis_new + h_f_new) if sensor_cos_num == 2 and cos_sq > 0.2: cos_sq = 0.2 dis_sq = 0.8 * h_dis_new / (h_dis_new + h_f_new) f_sq = 0.8 * h_f_new / (h_dis_new + h_f_new) '''if sensor_cos_num == 1: if dis_sq / f_sq > sensor_cos_num/sensor_f_num: dis_sq = sensor_cos_num/sensor_f_num f_sq=1-dis_sq''' # if h_dis_new/h_f_new > sensor_cos_num/sensor_f_num return cos_sq, dis_sq, f_sq def cal_sq_single_array(similarity_pre, if_direct): if similarity_pre.max() - similarity_pre.min() == 0: similarity_pre = np.ones(similarity_pre.shape) else: if if_direct == 1: similarity_pre = 0.998 * (similarity_pre - similarity_pre.min()) / ( similarity_pre.max() - similarity_pre.min()) + 0.002 else: similarity_pre = 0.998 * (similarity_pre.max() - similarity_pre) / ( similarity_pre.max() - similarity_pre.min()) + 0.002 # calculate pij similarity_p = similarity_pre / similarity_pre.sum() # cal xinxishang similarity_lnp = np.zeros((len(similarity_pre), 1)) for j in range(len(similarity_p)): similarity_lnp[j] = -similarity_p[j] * math.log(similarity_p[j], math.e) h = 1 - 1 / math.log(len(similarity_pre), math.e) * similarity_lnp.sum() return similarity_pre, h def cal_similarity_all_multi_new_sq_improve_double_lzr(candidate_pipe, similarity_mode, pressure_leak, monitor_p, predict_p, normal_p, if_flow, if_only_cos, if_only_flow, flow_leak, monitor_f, predict_f, normal_f, timestep_list, Top_sensor_num, if_gy, effective_sensor, cos_h, dis_h, dis_f_h, if_compalsive, max_flow): similarity = pd.Series(dtype=float, index=candidate_pipe) important_p_sensor = cal_top_sensors(monitor_p, predict_p, Top_sensor_num) # important_f_sensor, basic_f = cal_top_f_sensor(normal_f) important_f_sensor = monitor_f.columns if len(important_p_sensor) > 0 or len(important_f_sensor) > 0: # if len(important_p_sensor) > 0 break_flag = 0 pressure_leak_new = pressure_leak.swaplevel() flow_leak_new = flow_leak.swaplevel() total_similarity_cos = pd.DataFrame(index=timestep_list, columns=candidate_pipe) total_similarity_dis = pd.DataFrame(index=timestep_list, columns=candidate_pipe) total_similarity_dis_f = pd.DataFrame(index=timestep_list, columns=candidate_pipe) total_similarity_cos_f = pd.DataFrame(index=timestep_list, columns=candidate_pipe) for timestep in timestep_list: # cal p_cos, p_dis, f_dis if if_only_flow != 1: pressure_leak_temp = pressure_leak_new.loc[timestep].loc[:, effective_sensor] monitor_p_temp = monitor_p.loc[timestep, effective_sensor] predict_p_temp = predict_p.loc[timestep, effective_sensor] normal_p_temp = normal_p.loc[timestep, effective_sensor] total_similarity_cos.loc[timestep, :], total_similarity_dis.loc[timestep, :] = cal_similarity_all_cos_dis( candidate_pipe, pressure_leak_temp, similarity_mode, monitor_p_temp, predict_p_temp, normal_p_temp, pressure_leak_new.loc[timestep].loc[:, monitor_p.columns], monitor_p.loc[timestep, :], predict_p.loc[timestep, :], normal_p.loc[timestep, :], important_p_sensor, if_gy, cos_or_flow=1) if if_flow == 1: if len(timestep_list) == 1: leak_f_temp = flow_leak_new.loc[timestep].loc[:, important_f_sensor] monitor_f_temp = monitor_f.loc[timestep, important_f_sensor] predict_f_temp = predict_f.loc[timestep, important_f_sensor] normal_f_temp = normal_f.loc[timestep, important_f_sensor] basic_normal_f_temp = abs(max_flow.loc[important_f_sensor]) leak_f_temp = leak_f_temp / basic_normal_f_temp monitor_f_temp = monitor_f_temp / basic_normal_f_temp predict_f_temp = predict_f_temp / basic_normal_f_temp normal_f_temp = normal_f_temp / basic_normal_f_temp else: basic_f = abs(max_flow.loc[important_f_sensor]) leak_f_temp = flow_leak_new.loc[timestep].loc[:, important_f_sensor] / basic_f monitor_f_temp = monitor_f.loc[timestep, important_f_sensor] / basic_f predict_f_temp = predict_f.loc[timestep, important_f_sensor] / basic_f normal_f_temp = normal_f.loc[timestep, important_f_sensor] / basic_f total_similarity_cos_f.loc[timestep, :], total_similarity_dis_f.loc[timestep, :] = cal_similarity_all_cos_dis(candidate_pipe, leak_f_temp, similarity_mode, monitor_f_temp, predict_f_temp, normal_f_temp, flow_leak_new.loc[ timestep].loc[:, monitor_f.columns], monitor_f.loc[timestep, :], predict_f.loc[timestep, :], normal_f.loc[timestep, :], important_f_sensor, if_gy, cos_or_flow=1) # cos_or_flow=2 else: total_similarity_cos_f = [] # dis similarity_all, cos_h, dis_h, dis_f_h = cal_sq_all_multi(total_similarity_cos, total_similarity_dis, total_similarity_cos_f, candidate_pipe, timestep_list, if_flow, if_only_cos, if_only_flow, cos_h, dis_h, dis_f_h, if_compalsive, len(important_p_sensor), len(important_f_sensor)) if len(timestep_list) == 1: similarity = similarity_all.iloc[0] elif len(timestep_list) > 3: for each_candidate in candidate_pipe: similarity[each_candidate] = remove_3_sigma(similarity_all.loc[:, each_candidate]) else: for each_candidate in candidate_pipe: similarity[each_candidate] = similarity_all.loc[:, each_candidate].mean() similarity = similarity.sort_values(ascending=False) else: break_flag = 1 similarity = 0 cos_h = 0 dis_h = 0 dis_f_h = 0 return similarity, cos_h, dis_h, dis_f_h, break_flag def cal_similarity_all_cos_dis(candidate_pipe, pressure_leak, similarity_mode, monitor_p, predict_p, normal_p, pressure_leak_all, monitor_p_all, predict_p_all, normal_p_all, important_sensor, if_gy, cos_or_flow): similarity_cos = pd.Series(dtype=float, index=candidate_pipe) similarity_dis = pd.Series(dtype=float, index=candidate_pipe) dpressure = normal_p - pressure_leak # 无用 ---------------------------------------------- mean_dpressure = dpressure.mean() monitor_new = pd.DataFrame(index=['monitor'], columns=monitor_p.index) monitor_new.iloc[0] = monitor_p add_m_leak_pressure = [pressure_leak, monitor_p] add_m_leak_pressure = pd.concat(add_m_leak_pressure) pressure_leak_std = np.std(add_m_leak_pressure, ddof=1) pressure_leak_std = pd.Series(pressure_leak_std, index=pressure_leak.columns) add_m_leak_pressure_all = [pressure_leak_all, monitor_p_all] add_m_leak_pressure_all = pd.concat(add_m_leak_pressure_all) pressure_leak_std_all = np.std(add_m_leak_pressure_all, ddof=1) pressure_leak_std_all = pd.Series(pressure_leak_std_all, index=pressure_leak.columns) # 无用 ---------------------------------------------- monitor_p_temp = monitor_p predict_p_temp = predict_p normal_p_temp = normal_p monitor_p_temp_all = monitor_p_all predict_p_temp_all = predict_p_all normal_p_temp_all = normal_p_all record_success_candidate = [] record_success_no_candidate = [] for i in range(len(candidate_pipe)): leak_p = pressure_leak.iloc[i, :] leak_p_all = pressure_leak_all.iloc[i, :] similarity_cos.iloc[i], similarity_dis.iloc[i], none_flag = cal_similarity_simple_return_dd( similarity_mode, monitor_p_temp, predict_p_temp, normal_p_temp, leak_p, monitor_p_temp_all, predict_p_temp_all, normal_p_temp_all, leak_p_all, important_sensor, mean_dpressure, pressure_leak_std, pressure_leak_std_all, if_gy, cos_or_flow) if none_flag == 0: record_success_candidate.append(candidate_pipe[i]) else: record_success_no_candidate.append(candidate_pipe[i]) similarity_cos, similarity_dis = adjust(similarity_cos, similarity_dis, record_success_candidate, record_success_no_candidate) return similarity_cos, similarity_dis def cal_top_f_sensor(normal_f): if type(normal_f) == pd.core.frame.DataFrame: mean_f = normal_f.mean() else: mean_f = normal_f output_sensor = [] output_normal_f = pd.Series(dtype=object) for i in range(len(mean_f.index)): if abs(mean_f.iloc[i]) > 0.01 / 3600: output_sensor.append(mean_f.index[i]) output_normal_f[mean_f.index[i]] = mean_f.iloc[i] return output_sensor, output_normal_f def cal_top_sensors(monitor_p, predict_p, Top_sensor_num): dpressure = abs(predict_p - monitor_p) if type(dpressure) == pd.core.frame.DataFrame: dpressure = dpressure.mean() dpressure_rank = dpressure.sort_values(ascending=False) return list(dpressure_rank.index[:Top_sensor_num]) def remove_3_sigma(similarity_t): all_sample = len(similarity_t.index) apart_sample = math.ceil(all_sample * 0.6) similarity = similarity_t.astype('float') mean_t = similarity.mean() std_t = similarity.std() new_similarity = similarity[(similarity <= mean_t + 3 * std_t) & (similarity >= mean_t - 3 * std_t)] mean_t_new = new_similarity.mean() return mean_t_new ## other functions # OF 1 def cal_pipe_coordinate(all_pipe, pipe_start_node, pipe_end_node, node_coordinates): pipe_num = len(all_pipe) pipe_coordinates = np.zeros([pipe_num, 2]) pipe_x = copy.deepcopy(pipe_start_node) pipe_y = copy.deepcopy(pipe_start_node) for i in range(pipe_num): temp_pipe = all_pipe[i] pipe_x[temp_pipe] = (node_coordinates[pipe_start_node[temp_pipe]][0] + node_coordinates[pipe_end_node[temp_pipe]][0]) / 2 pipe_y[temp_pipe] = (node_coordinates[pipe_start_node[temp_pipe]][1] + node_coordinates[pipe_end_node[temp_pipe]][1]) / 2 return pipe_x, pipe_y # OF 1+ def cal_node_coordinate(all_node, node_coordinates): node_x = copy.deepcopy(node_coordinates) node_y = copy.deepcopy(node_coordinates) for i in range(len(node_x)): temp_node = all_node[i] node_x[temp_node] = node_coordinates[temp_node][0] node_y[temp_node] = node_coordinates[temp_node][1] return node_x, node_y # OF 4 def cal_signature_pipe_multi_pf(wn, leak_mag, candidate_center, timestep_list, sensor_name, sensor_f_name): candidate_center_num = len(candidate_center) pressure_leak = pd.DataFrame(index=pd.MultiIndex.from_product([candidate_center, timestep_list]), columns=sensor_name) flow_leak = pd.DataFrame(index=pd.MultiIndex.from_product([candidate_center, timestep_list]), columns=sensor_f_name) pressure_leak = pressure_leak.sort_index() flow_leak = flow_leak.sort_index() for i in range(candidate_center_num): wn, pressure_output, flow_output = leak_simulation_pipe_dd_multi_pf(wn, leak_mag, candidate_center[i], sensor_name, sensor_f_name) # leak_or_not_list.append(leak_or_not) pressure_leak.loc[candidate_center[i]].loc[:, :] = pressure_output flow_leak.loc[candidate_center[i]].loc[:, :] = flow_output sys.stdout.write('\r' + '已经完成计算' + str(i + 1) + '个特征中心') return pressure_leak, flow_leak, candidate_center # OF 6 根据流量计算可能爆管的管段及最小爆管管径 def cal_possible_pipe(leak_flow, all_pipe, pipe_diameter): basic_pressure = 10 # 基础压力 discharge_coeff = 0.6 # 经验系数 break_area_ratio = 1 # 爆管面积比 0.5 1.25 break_area = leak_flow / (discharge_coeff * math.sqrt(2 * basic_pressure * 9.81)) # 爆管面积 m3/h '''break_area_diameter = math.sqrt(4 * break_area / math.pi) min_diameter = (math.ceil(1000 * break_area_diameter / break_area_ratio)) / 1000''' break_area_diameter = math.sqrt(4 * break_area / math.pi / break_area_ratio) # 爆管直径 min_diameter = (math.ceil(1000 * break_area_diameter)) / 1000 # 向上取整 new_all_pipe = pick_pipe(all_pipe, pipe_diameter, min_diameter) return new_all_pipe, min_diameter # Press the green button in the gutter to run the script. def extract_links(data, link_types, direction): return [ link for res_data in data.values() for link_type in link_types for link in res_data[link_type][direction] ] def add_noise_pd(data, noise_type, noise_para): output_data = copy.deepcopy(data) if type(output_data) == pd.core.frame.Series: if noise_type == 'uni': for x in output_data.index: noise = (np.random.random() - 0.5) * 2 output_data[x] = output_data[x] + noise * noise_para elif noise_type == 'gauss': noise = np.random.normal(loc=0, scale=noise_para, size=output_data.shape) output_data = output_data + noise elif type(output_data) == pd.core.frame.DataFrame: if noise_type == 'uni': noise = (np.random.random(size=output_data.shape) - 0.5) * 2 output_data = output_data + noise * noise_para elif noise_type == 'gauss': noise = np.random.normal(loc=0, scale=noise_para, size=output_data.shape) output_data = output_data + noise return output_data def add_noise_number(data, noise_type, noise_para): output_data = copy.deepcopy(data) if noise_type == 'uni': noise = (np.random.random() - 0.5) * 2 output_data = output_data + noise * noise_para elif noise_type == 'gauss': noise = random.gauss(0, noise_para) output_data = output_data + noise return output_data def add_noise_number_flow(data, noise_para_mean, noise_para_std1, noise_para_std2): output_data = copy.deepcopy(data) noise_flag1 = (np.random.random() - 0.5) if noise_flag1 < 0: noise = noise_para_mean - abs(np.random.normal(loc=0, scale=noise_para_std1)) else: noise = noise_para_mean + abs(np.random.normal(loc=0, scale=noise_para_std2)) noise_flag2 = (np.random.random() - 0.5) if noise_flag2 < 0: noise_f = noise * (-1) else: noise_f = noise output_data = output_data + noise_f return output_data def produce_noise_number(noise_type, noise_para): if noise_type == 'uni': noise = (np.random.random() - 0.5) * 2 noise = noise * noise_para elif noise_type == 'gauss': noise = random.gauss(0, noise_para) else: noise = 0 return noise def add_noise_percentage_pd(data, noise_type, noise_para): output_data = copy.deepcopy(data) if type(output_data) == pd.core.frame.Series: if noise_type == 'uni': for x in output_data.index: noise = (np.random.random() - 0.5) * 2 output_data[x] = output_data[x] * (1 + noise * noise_para / 100) elif noise_type == 'gauss': for x in output_data.index: noise = np.random.gauss(0, noise_para) output_data[x] = output_data[x] * (1 + noise / 100) # std_noise = noise.std() elif type(output_data) == pd.core.frame.DataFrame: if noise_type == 'uni': noise = (np.random.random(size=output_data.shape) - 0.5) * 2 output_data = output_data * (1 + noise * noise_para / 100) elif noise_type == 'gauss': noise = np.random.normal(loc=0, scale=noise_para, size=output_data.shape) output_data = output_data * (1 + noise / 100) # std_noise = noise.std().mean() return output_data def produce_pattern_value(wn, all_node): wn_o = copy.deepcopy(wn) # 改_wz_____________________________ sample_node = wn_o.get_node(all_node[0]) num_categories = len(sample_node.demand_timeseries_list) columns = [f'D{i}' for i in range(num_categories)] basic_demand_pd = pd.DataFrame(index=all_node, columns=columns) for each in all_node: node = wn_o.get_node(each) for i in range(num_categories): basic_demand_pd.loc[each, columns[i]] = node.demand_timeseries_list[i].base_value return basic_demand_pd # 添加噪声 def add_noise_in_wn_pf(wn, pipe_c_noise, timestep_list, pipe_coefficient, sensor_name, sensor_f_name, all_node, basic_demand_pd, noise_type, noise_para, leak_pipe, leak_flow): wn.options.time.duration = 0 pipe_roughness_change = add_noise_pd(pipe_coefficient, noise_type, pipe_c_noise) wn = change_para_of_wn(wn, pipe_roughness_change) record_pressure = pd.DataFrame(index=timestep_list, columns=sensor_name) record_flow = pd.DataFrame(index=timestep_list, columns=sensor_f_name) record_noise_all = pd.DataFrame(index=pd.MultiIndex.from_product([timestep_list, all_node]), columns=basic_demand_pd.columns) record_noise_all = record_noise_all.sort_index() # normal 获取添加噪声后的监测点数据 for i in range(len(timestep_list)): wn, record_noise = change_node_demand(wn, basic_demand_pd, all_node, noise_type, noise_para) record_noise_all.loc[timestep_list[i]].loc[:, :] = record_noise pressure_temp, flow_temp = simple_simulation_pf(wn, sensor_name, sensor_f_name, [], []) record_pressure.iloc[i, :] = pressure_temp record_flow.iloc[i, :] = flow_temp # leak_simulation 获取添加漏损后的监测点数据 record_pressure_leak = pd.DataFrame(index=timestep_list, columns=sensor_name) record_flow_leak = pd.DataFrame(index=timestep_list, columns=sensor_f_name) # 改_wz_________________________________________ # add leak wn, whole_inf, add_pipe1 = simple_add_leak(wn, leak_flow, leak_pipe) # simulation for i in range(len(timestep_list)): record_noise = record_noise_all.loc[timestep_list[i]] wn = change_node_demand_leak(wn, record_noise, all_node) pressure_temp, flow_temp = simple_simulation_pf(wn, sensor_name, sensor_f_name, leak_pipe, add_pipe1) record_pressure_leak.iloc[i, :] = pressure_temp record_flow_leak.iloc[i, :] = flow_temp # delete leak wn = simple_recover_wn(wn, whole_inf) return wn, record_pressure, record_flow, record_pressure_leak, record_flow_leak def change_node_demand(wn, basic_demand_pd, all_node, noise_type, noise_para): # 改_wz_____________________________________ record_noise = pd.DataFrame(index=all_node, columns=basic_demand_pd.columns) for each_node in all_node: node = wn.get_node(each_node) num_columns = len(basic_demand_pd.columns) # 处理前N-1列(如果有) for i in range(num_columns - 1): # 获取原始值并添加噪声 record_noise.loc[each_node].iloc[i] = (1 + produce_noise_number(noise_type, noise_para)) * \ basic_demand_pd.loc[each_node].iloc[i] node.demand_timeseries_list[i].base_value = record_noise.loc[each_node].iloc[i] # 处理最后一列(当列数>=1时) if num_columns >= 1: last_col = basic_demand_pd.columns[-1] original_last = basic_demand_pd.loc[each_node, last_col] record_noise.loc[each_node, last_col] = original_last node.demand_timeseries_list[-1].base_value = original_last return wn, record_noise def change_node_demand_leak(wn, record_noise, all_node): # 改_wz_____________________________ sample_node = wn.get_node(all_node[0]) num_categories = len(sample_node.demand_timeseries_list) for each in all_node: node = wn.get_node(each) for i in range(num_categories): node.demand_timeseries_list[i].base_value = record_noise.loc[each].iloc[i] return wn def cal_group_num(candidate_node_input, cal_group_num): candidate_node_num = len(candidate_node_input) if candidate_node_num > 100: group_num_input = cal_group_num # 30 else: group_num_input = 10 return group_num_input def area_output_num_ki_improve(candidate_center, candidate_group, similarity, new_all_node, top_group_ratio, top_pipe_num_max, top_pipe_num_min, cut_ratio): final_area = [] final_center = [] all_node_iter = [] if similarity.index.is_unique == False: total_center_num = len(list(set(similarity.index))) else: total_center_num = len(similarity.index) next_group_num = min(total_center_num, math.ceil(total_center_num / cut_ratio * top_group_ratio)) for i in range(next_group_num): top_center = similarity.index[i] top_center_index = find_list_repeat(candidate_center, top_center) for j in range(len(top_center_index)): final_area = final_area + candidate_group[top_center_index[j]] all_node_iter = all_node_iter + list(new_all_node[top_center_index[j]]) final_center.append(top_center) final_area = list(set(final_area)) if len(final_area) > top_pipe_num_max: if_end = 0 elif len(final_area) > top_pipe_num_min: if_end = 1 elif total_center_num == next_group_num: if_end = 1 else: if_end = 1 for i in np.arange(next_group_num, total_center_num, 1): before_list = copy.deepcopy(final_area) top_center = similarity.index[i] top_center_index = candidate_center.index(top_center) temp_group = final_area + candidate_group[top_center_index] temp_area = list(set(temp_group)) if len(temp_area) < top_pipe_num_min: final_center.append(top_center) all_node_iter = all_node_iter + list(new_all_node[top_center_index]) final_area = temp_area elif len(temp_area) < top_pipe_num_max: final_center.append(top_center) all_node_iter = all_node_iter + list(new_all_node[top_center_index]) final_area = temp_area break else: a = len(temp_area) - top_pipe_num_max b = top_pipe_num_min - len(before_list) if a >= b: final_area = before_list else: final_center.append(top_center) all_node_iter = all_node_iter + list(new_all_node[top_center_index]) final_area = temp_area break final_center = list(set(final_center)) all_node_iter = list(set(all_node_iter)) return final_area, final_center, all_node_iter, if_end def find_list_repeat(candidate_center, target): repeated_list = [] for index, nums in enumerate(candidate_center): if nums == target: repeated_list.append(index) return repeated_list def change_para_of_wn(wn, pipe_roughness_change): for pipe_name, pipe in wn.pipes(): pipe.roughness = pipe_roughness_change[pipe_name] return wn def cal_DtoTop1(G0, pipe_leak, located_pipe, pipe_start_node_all, pipe_end_node_all, pipe_length): if pipe_leak == located_pipe: result_DtoTop1 = 0 result_DtoTop1_num = 0 else: pipe_leak_start_node = pipe_start_node_all[pipe_leak] pipe_leak_end_node = pipe_end_node_all[pipe_leak] located_pipe_start_node = pipe_start_node_all[located_pipe] located_pipe_end_node = pipe_end_node_all[located_pipe] DtoTop1_series = pd.Series(dtype=object) DtoTop1_num_series = pd.Series(dtype=object) DtoTop1_series['ss'] = nx.shortest_path_length(G0, pipe_leak_start_node, located_pipe_start_node, weight='weight') DtoTop1_series['se'] = nx.shortest_path_length(G0, pipe_leak_start_node, located_pipe_end_node, weight='weight') DtoTop1_series['es'] = nx.shortest_path_length(G0, pipe_leak_end_node, located_pipe_start_node, weight='weight') DtoTop1_series['ee'] = nx.shortest_path_length(G0, pipe_leak_end_node, located_pipe_end_node, weight='weight') DtoTop1_num_series['ss'] = nx.shortest_path_length(G0, pipe_leak_start_node, located_pipe_start_node) DtoTop1_num_series['se'] = nx.shortest_path_length(G0, pipe_leak_start_node, located_pipe_end_node) DtoTop1_num_series['es'] = nx.shortest_path_length(G0, pipe_leak_end_node, located_pipe_start_node) DtoTop1_num_series['ee'] = nx.shortest_path_length(G0, pipe_leak_end_node, located_pipe_end_node) if DtoTop1_num_series.min() == 0: result_DtoTop1_num = 1 result_DtoTop1 = DtoTop1_series.max() / 2 else: result_DtoTop1_num = DtoTop1_num_series.min() + 1 DtoTop1_type = DtoTop1_series.argmin() result_DtoTop1 = DtoTop1_series[DtoTop1_type] + (pipe_length[pipe_leak] + pipe_length[located_pipe]) / 2 return result_DtoTop1, result_DtoTop1_num def cal_RR(located_pipe, similarity_sp): if located_pipe in similarity_sp.index: rank = similarity_sp.index.get_loc(located_pipe) RR = rank / len(similarity_sp.index) else: RR = 1.1 return RR def cal_cover(similarity, leak_pipe): if leak_pipe in list(similarity.index): cover = 1 else: cover = 0 return cover def cal_SD(located_pipe, real_pipe, pipe_x, pipe_y): dx = pipe_x[located_pipe] - pipe_x[real_pipe] dy = pipe_y[located_pipe] - pipe_y[real_pipe] SD = math.sqrt(dx * dx + dy * dy) return SD def update_similarity(leak_candidate_center, similarity, leak_center_dict): similarity_new = pd.Series(dtype=object) for each_center in leak_candidate_center: houxuan_center = leak_center_dict[each_center] if len(houxuan_center) > 1: temp_similarity = similarity[houxuan_center] similarity_new[each_center] = temp_similarity.max() else: if type(similarity[each_center]) == pd.core.series.Series: similarity_new[each_center] = similarity[each_center].mean() else: similarity_new[each_center] = similarity[each_center] similarity_new = similarity_new.sort_values(ascending=False) return similarity_new def extra_judge(similarity): mean_similarity = float(similarity.mean()) record_sensor = [] record_value = [] for i in range(len(similarity.index)): if similarity.iloc[i] >= mean_similarity: record_value.append(similarity.iloc[i]) record_sensor.append(similarity.index[i]) out_put_similarity = pd.Series(record_value, index=record_sensor, dtype=object) cut_ratio = len(out_put_similarity.index) / len(similarity.index) return cut_ratio, out_put_similarity def adjust_ratio(similarity_mode, cos_h, dis_h, dis_f_h, low_limit=0.1): if similarity_mode == 'CAF': if cos_h < low_limit: cos_h = low_limit dis_f_h = 1 - cos_h elif dis_f_h < low_limit: dis_f_h = low_limit cos_h = 1 - dis_f_h elif similarity_mode == 'CAD_new_gy': if dis_h < low_limit: dis_h = low_limit cos_h = 1 - dis_h elif cos_h < low_limit: cos_h = low_limit dis_h = 1 - cos_h elif similarity_mode == 'CDF': normal_index = [0, 1, 2] h_list = [cos_h, dis_h, dis_f_h] if cos_h < low_limit: h_list[0] = low_limit normal_index.remove(0) if dis_h < low_limit: h_list[1] = low_limit normal_index.remove(1) if dis_f_h < low_limit: h_list[2] = low_limit normal_index.remove(2) if len(normal_index) == 1: h_list[normal_index[0]] = h_list[normal_index[0]] - (sum(h_list) - 1) elif len(normal_index) == 2: sum_list = sum(h_list) multiper = 1 - (sum_list - 1) / (h_list[normal_index[0]] + h_list[normal_index[1]]) h_list[normal_index[0]] = h_list[normal_index[0]] * multiper h_list[normal_index[1]] = h_list[normal_index[1]] * multiper cos_h, dis_h, dis_f_h = h_list[0], h_list[1], h_list[2] return cos_h, dis_h, dis_f_h # DAND def DN_search_multi_simple_add_flow_count_new(wn, G0, all_node, node_x, node_y, pipe_start_node_all, pipe_end_node_all, couple_node_length, node_pipe_dic, all_node_series, top_group_ratio, top_pipe_num_max, top_pipe_num_min, candidate_pipe_input_initial, similarity_mode, pressure_monitor, pressure_predict, pressure_normal, pressure_leak_all, flow_monitor, flow_predict, flow_normal, flow_leak_all, timestep_list, max_flow, group_basic_num, Top_sensor_num, if_gy, pressure_threshold): """ 是一个较为复杂的迭代搜索函数,用于通过多次分组、仿真与相似性计算,最终定位出最可能发生漏损(或爆管)的管道。 函数内部依次调用前述的分组(metis_grouping_pipe_weight)、相似性计算(cal_similarity_all_multi_new_sq_improve_double_lzr) 以及候选区域更新(area_output_num_ki_improve)函数。 :param wn: 水网模型 :param G0: 网络图 :param all_node: 节点列表 :param node_x: 节点坐标映射(字典或 Series) :param node_y: 节点坐标映射(字典或 Series) :param pipe_start_node_all: 字典 :param pipe_end_node_all: 字典 :param couple_node_length: 字典 :param node_pipe_dic: 字典 :param all_node_series: pandas Series :param top_group_ratio: 数值 :param top_pipe_num_max: 数值 :param top_pipe_num_min: 数值 :param candidate_pipe_input_initial: 候选管道列表 :param similarity_mode: 字符串 :param pressure_monitor: 压力数 :param pressure_predict: 压力数 :param pressure_normal: 压力数 :param pressure_leak_all: 压力数 :param timestep_list: 时间步列表 :param max_flow: Series 或字典 :param group_basic_num: 数值 :param Top_sensor_num: 整数 :param if_gy: 标志(整型或布尔) :param pressure_threshold: 数值 :return: 最终候选管道(最高相似性对应的管道名称)、耗时(秒)、模拟次数、更新后的 wn、以及最终相似性排序的 pandas Series """ iter_count = 0 all_node_iter = copy.deepcopy(all_node) candidate_pipe_input = copy.deepcopy(candidate_pipe_input_initial) # 可能漏损管段 t1 = datetime.now() if_flow, if_only_cos, if_only_flow = decode_mode(similarity_mode) # 定位方法 # threshold if if_only_flow == 1: dpressure = (flow_predict - flow_monitor).mean() dpressure = np.abs(dpressure) effective_sensor = list(dpressure.index) else: dpressure = (pressure_predict - pressure_monitor).mean() dpressure = np.abs(dpressure) dpressure = dpressure[dpressure > pressure_threshold] effective_sensor = list(dpressure.index) simulation_times = 0 # 模拟次数 if len(dpressure) > 0: cos_h = 0 dis_h = 0 dis_f_h = 0 if_compalsive = 0 record_center_dataset = [] # iter while 1: final_area = [] final_center = [] group_num = cal_group_num(candidate_pipe_input, group_basic_num) # group 分组,得出候选漏损中心 candidate_center_list, candidate_group_list, new_all_node = metis_grouping_pipe_weight(G0, wn, all_node_iter, candidate_pipe_input, group_num, node_x, node_y, pipe_start_node_all, pipe_end_node_all, node_pipe_dic, all_node_series, couple_node_length) simulation_times = simulation_times + len(candidate_center_list) # pick_pressure_leak pressure_leak = pressure_leak_all.loc[candidate_center_list].loc[:, :] flow_leak = flow_leak_all.loc[candidate_center_list].loc[:, :] # pressure_leak_f= pressure_leak.swaplevel() # -------------------------------------------------------- add_center = [] leak_center_dict = dict() for i in range(len(candidate_center_list)): houxuan_center = [] for each_center in record_center_dataset: if each_center in candidate_group_list[i] and each_center != candidate_center_list[i]: houxuan_center.append(each_center) add_center = add_center + houxuan_center houxuan_center.append(candidate_center_list[i]) leak_center_dict[candidate_center_list[i]] = houxuan_center for each_center in candidate_center_list: if each_center not in record_center_dataset: record_center_dataset.append(each_center) # -------------------------------------------------------- # -------------------------------------------------------- if len(add_center) > 0: s3 = pressure_leak_all.loc[add_center] pressure_leak = pd.concat([pressure_leak, s3]) s4 = flow_leak_all.loc[add_center] flow_leak = pd.concat([flow_leak, s4]) # -------------------------------------------------------- # -------------------------------------------------------- # if len(candidate_pipe_input) < 1.2 * top_pipe_num_max / top_group_ratio: if_compalsive = 1 cos_h, dis_h, dis_f_h = adjust_ratio(similarity_mode, cos_h, dis_h, dis_f_h) candidate_center_list_sup = candidate_center_list + add_center similarity, cos_h, dis_h, dis_f_h, break_flag = cal_similarity_all_multi_new_sq_improve_double_lzr( candidate_center_list_sup, similarity_mode, pressure_leak, pressure_monitor, pressure_predict, pressure_normal, if_flow, if_only_cos, if_only_flow, flow_leak, flow_monitor, flow_predict, flow_normal, timestep_list, Top_sensor_num, if_gy, effective_sensor, cos_h, dis_h, dis_f_h, if_compalsive, max_flow) if break_flag == 1: break new_similarity = update_similarity(candidate_center_list, similarity, leak_center_dict) if len(candidate_pipe_input) > top_pipe_num_max / top_group_ratio: cut_ratio, new_similarity = extra_judge(new_similarity) else: cut_ratio = 1 final_area_t, final_center_t, all_node_new_1, if_end = area_output_num_ki_improve(candidate_center_list, candidate_group_list, new_similarity, new_all_node, top_group_ratio, top_pipe_num_max, top_pipe_num_min, cut_ratio) final_area = final_area + final_area_t final_center = final_center + final_center_t final_area = list(set(final_area)) final_center = list(set(final_center)) if if_end == 1: break elif len(candidate_pipe_input) == len(final_area): break else: candidate_pipe_input = final_area all_node_iter = all_node_new_1 iter_count += 1 sys.stdout.write( '\r' + '已经完成' + str(iter_count) + '次迭代计算' + '候选节点' + str(len(final_area)) + '个') if break_flag == 0: final_area_pipe = copy.deepcopy(final_area) simulation_times = simulation_times + len(final_area) pressure_leak_sp = pressure_leak_all.loc[final_area_pipe].loc[:, :] flow_leak_sp = flow_leak_all.loc[final_area_pipe].loc[:, :] similarity_sp, cos_h, dis_h, dis_f_h, break_flag = cal_similarity_all_multi_new_sq_improve_double_lzr( final_area_pipe, similarity_mode, pressure_leak_sp, pressure_monitor, pressure_predict, pressure_normal, if_flow, if_only_cos, if_only_flow, flow_leak_sp, flow_monitor, flow_predict, flow_normal, timestep_list, Top_sensor_num, if_gy, effective_sensor, cos_h, dis_h, dis_f_h, if_compalsive, max_flow) else: dpressure = (pressure_predict - pressure_monitor).mean() dpressure = np.abs(dpressure) simulation_times = simulation_times + len(dpressure.index) similarity_sp = pd.Series(dtype=object) for each_node in dpressure.index: pipe = node_pipe_dic[each_node][0] similarity_sp.loc[pipe] = dpressure.loc[each_node] similarity_sp = similarity_sp.sort_values(ascending=False) t2 = datetime.now() final_area_pipe = [] sys.stdout.write( '\r' + '已经完成' + str(iter_count + 1) + '次迭代计算' + '候选节点' + str(len(final_area_pipe)) + '个') t2 = datetime.now() dt = (t2 - t1).seconds else: dpressure = (pressure_predict - pressure_monitor).mean() dpressure = np.abs(dpressure) similarity_sp = pd.Series(dtype=object) for each_node in dpressure.index: pipe = node_pipe_dic[each_node][0] similarity_sp.loc[pipe] = dpressure.loc[each_node] similarity_sp = similarity_sp.sort_values(ascending=False) t2 = datetime.now() dt = (t2 - t1).seconds return similarity_sp.index[0], dt, simulation_times, wn, similarity_sp def decode_mode(similarity_mode): if similarity_mode == 'COS': if_flow = 0 if_only_cos = 1 if_only_flow = 0 elif similarity_mode == 'CAD_new_gy': if_flow = 0 if_only_cos = 0 if_only_flow = 0 elif similarity_mode == 'CDF': if_flow = 1 if_only_cos = 0 if_only_flow = 0 elif similarity_mode == 'CAF': if_flow = 1 if_only_cos = 1 if_only_flow = 0 elif similarity_mode == 'DIS': if_flow = 1 if_only_cos = 2 if_only_flow = 0 elif similarity_mode == 'OF': if_flow = 1 if_only_cos = 0 if_only_flow = 1 return if_flow, if_only_cos, if_only_flow # 根据爆管直径选择可能管段 def pick_pipe(all_pipes, pipe_diameter, limited_diameter): candidate_pipe = [] for each_pipe in all_pipes: if pipe_diameter[each_pipe] >= limited_diameter: candidate_pipe.append(each_pipe) return candidate_pipe #2025/6/7 def locate_burst(name: str, pressure_SCADA_ID_list: list[list[str]], burst_SCADA_pressure: pd.Series, normal_SCADA_pressure: pd.Series, flow_SCADA_ID_list: list[list[str]], burst_SCADA_flow: pd.Series, normal_SCADA_flow: pd.Series, burst_leakage: float, burst_happen_time: str, basic_pressure: float = 10.0): """ 漏损定位 :param name: 数据库名称 :param pressure_SCADA_ID_list: 压力SCADA点的名称列表 :param burst_SCADA_pressure: 爆管时真实压力 or 爆管方案模拟的到的压力 :param normal_SCADA_pressure: 爆管时间数据平滑得到的压力 or 正常情况下的压力 :param burst_leakage: 爆管漏损水量 :param burst_happen_time: 爆管发生时间,格式为'2024-11-25T09:00:00+08:00' :param basic_pressure: 水厂给整片管网的最小服务压力。根据《城镇供水服务》(GB/T 32063-2015),管网末梢最小服务压力应不低于 0.14 MPa(14米水柱), 《消防给水及消火栓系统技术规范》(GB 50974-2014)规定,火灾时管网压力应至少达到 0.10 MPa(10米水柱) :return: """ # candidate_type candidate_type = 'pipe' top_group_ratio = 0.4 top_pipe_num_max = 42 # 25 top_pipe_num_min = 34 # 35 # modified # similarity_mode_list = ['CDF_inflow','CDF_other','CAD_new_gy','CAF','COS'] method_rational = 0.5 # 保存路径 与 部分参数 修改 file_fold = './1mypaperdata_f/sensor_opt_validation/' # './sensor_opt/' Method_mode = 'DAND' Noise_level = 'N2' Leakage_level = 'L02' version = 'wz_0513' file_path = os.path.join(file_fold, f'{name}' + '_' + Method_mode + '_' + Noise_level + '_' + Leakage_level + '_' + version + '.xlsx') directory = os.path.dirname(file_path) if not os.path.exists(directory): os.makedirs(directory) writer = pd.ExcelWriter(file_path) # other basic_setting 可不修改 candidate_leak_ratio = [float(Leakage_level[1:]) / 10] node_d_noise_list = [0, 0.05, 0.1, 0.15] # /3.27 pipe_c_noise_list = [0, 5, 10, 15] # /3.27 noise_para_monitor_list = [0, 0.1, 0.2, 0.3] # noise_f_para_monitor_list = [0, 1, 2, 5] # % leak_flow_para_mean_list = [0, 0.0125, 0.0125, 0.0125] leak_flow_para_std1_list = [0, 0.0125 / 4, 0.0125 / 4, 0.0125 / 4] leak_flow_para_std2_list = [0, 0.0025 / 3, 0.0025 / 3, 0.0025 / 3] noise_level = int(Noise_level[1:]) ## other # driven_mode = 'DD' require_p = 100 * 1.42 # 20mh2o minimum_p = 0 # 0 if_plot = 0 # 加载原始管网模型及读取信息 # 调用 load_inp 构造水网模型(使用 wntr 模块),加载 正常工况的 INP 文件 wn_origin = load_inp(name=name, before_burst_time=burst_happen_time) # 由read_inf_inp 获取水网中所有节点、节点海拔、坐标、候选管道(初始状态为开)、管道起始和结束节点、长度和直径等信息 all_node, node_elevation, node_coordinates, candidate_pipe_init, pipe_start_node, pipe_end_node, pipe_length, pipe_diameter = read_inf_inp( wn_origin) candidate_pipe_input, min_diameter = cal_possible_pipe(burst_leakage, candidate_pipe_init, pipe_diameter) # 获取可能管段和最小爆管直径 node_x, node_y = cal_node_coordinate(all_node, node_coordinates) all_link, pipe_start_node_all, pipe_end_node_all = read_inf_inp_other(wn_origin) # 节点索引与节点-管道字典 # 首先取出所有节点名称,再构造一个 pandas Series,将每个节点名称映射到一个索引(0, 1, 2, …) all_node_series = wn_origin.node_name_list all_node_series = pd.Series(range(len(all_node_series)), index=all_node_series) node_pipe_dic = {node: wn_origin.get_links_for_node(node) for node in wn_origin.node_name_list} couple_node_length = dict() for each_link in all_link: start_node = pipe_start_node_all[each_link] end_node = pipe_end_node_all[each_link] name1 = start_node + ',' + end_node name2 = end_node + ',' + start_node if each_link in pipe_length.index: couple_node_length[name1] = math.ceil(pipe_length[each_link] * 10) couple_node_length[name2] = math.ceil(pipe_length[each_link] * 10) else: couple_node_length[name1] = 1 couple_node_length[name2] = 1 # 首先排除无关节点,直接对all_node操作 n_node = [] all_node = list(set(all_node) - set(n_node)) # 计算需要排除的节点 except_node_boundary = [] tank_names = wn_origin.tank_name_list reservoir_names = wn_origin.reservoir_name_list except_node_construction = list(tank_names + reservoir_names) except_node_list = except_node_boundary + except_node_construction all_node_temp = list(set(all_node) - set(except_node_boundary)) all_node_temp = list(set(all_node_temp) - set(except_node_construction)) all_node_new = all_node_temp all_node_pcv = [] ## 模拟漏损管道 candidate_pipe_input = list(set(candidate_pipe_input)) candidate_pipe_input_initial = list(set(candidate_pipe_input)) ## 随机选择一定数量的管段 num_to_select = max(2, int(len(candidate_pipe_input_initial) * 0.001)) leakage_position_list = random.sample(candidate_pipe_input_initial, num_to_select) # leakage_position_list = ['ZBBGXSZK001865','ZBBGXSZK002094','ZBBGXSZK002075'] ## 获取水塔和水库的进出水管段及水泵 # reservoir_links = {} # tank_links = {} # for res in reservoir_names: # reservoir_links[res] = {'pipes': {'pos': [], 'neg': []}, 'pumps': {'pos': [], 'neg': []}} # for tank in tank_names: # tank_links[tank] = {'pipes': {'pos': [], 'neg': []}, 'pumps': {'pos': [], 'neg': []}} # for pipe_name in wn_origin.pipe_name_list: # pipe = wn_origin.get_link(pipe_name) # start_node = pipe.start_node_name # end_node = pipe.end_node_name # # 水库相关的管道 # if start_node in reservoir_names: # reservoir_links[start_node]['pipes']['pos'].append(pipe_name) # if end_node in reservoir_names: # reservoir_links[end_node]['pipes']['neg'].append(pipe_name) # # 水塔相关的管道 # if start_node in tank_names: # tank_links[start_node]['pipes']['pos'].append(pipe_name) # if end_node in tank_names: # tank_links[end_node]['pipes']['neg'].append(pipe_name) # for pump_name in wn_origin.pump_name_list: # pump = wn_origin.get_link(pump_name) # start_node = pump.start_node_name # end_node = pump.end_node_name # # 水库相关水泵 # if start_node in reservoir_names: # reservoir_links[start_node]['pumps']['pos'].append(pump_name) # if end_node in reservoir_names: # reservoir_links[end_node]['pumps']['neg'].append(pump_name) # # 水塔相关水泵 # if start_node in tank_names: # tank_links[start_node]['pumps']['pos'].append(pump_name) # if end_node in tank_names: # tank_links[end_node]['pumps']['neg'].append(pump_name) # all_reservoir_pos_links = [ # link # for res_data in reservoir_links.values() # for link_type in ['pipes', 'pumps'] # for link in res_data[link_type]['pos'] # ] # all_reservoir_neg_links = [ # link # for res_data in reservoir_links.values() # for link_type in ['pipes', 'pumps'] # for link in res_data[link_type]['neg'] # ] # all_tank_pos_links = [ # link # for tan_data in tank_links.values() # for link_type in ['pipes', 'pumps'] # for link in tan_data[link_type]['pos'] # ] # all_tank_neg_links = [ # link # for tan_data in tank_links.values() # for link_type in ['pipes', 'pumps'] # for link in tan_data[link_type]['neg'] # ] # all_tank_pipe_links = [ # link # for tan_data in tank_links.values() # for link_type in ['pos', 'neg'] # for link in tan_data['pipes'][link_type] # ] # f1 = [] # f_corr2_f = all_tank_pipe_links # _pos = all_reservoir_pos_links + all_tank_pos_links # 出水 # _neg = all_reservoir_neg_links + all_tank_neg_links # 进水 # f0 = _pos + _neg # 需测试的监测点布局 ## sensor analyse S5_40 ---------------------------------------------- sensor_name_list_str = ['test'] # 每个监测布局的名称 sensor_name_list = pressure_SCADA_ID_list # 不同的监测点对应的定位方法,可设置全为'CAD_new_gy' similarity_mode_list = ['COS'] * len(sensor_name_list_str) sensor_f_name_list = [[] for _ in range(len(sensor_name_list_str))] # 流量监测点 # sensor_f_name_list = flow_SCADA_ID_list sensor_level_list = list(np.arange(len(sensor_name_list_str))) sensor_name = itertools.chain.from_iterable(sensor_name_list) sensor_name = list(set(sensor_name)) sensor_f_name = itertools.chain.from_iterable(sensor_f_name_list) sensor_f_name = list(set(sensor_f_name)) # sensor_f_name = sensor_f_name + f0 + f1 + f_corr2_f # sensor_f_name = list(set(sensor_f_name)) sensor_name_all = copy.deepcopy(sensor_name) sensor_f_name_all = copy.deepcopy(sensor_f_name) r2 = pd.DataFrame( index=pd.MultiIndex.from_product([sensor_name_list_str, leakage_position_list]), columns=['TD']) r3 = pd.DataFrame( index=pd.MultiIndex.from_product([sensor_name_list_str, leakage_position_list]), columns=['SD']) r4 = pd.DataFrame( index=pd.MultiIndex.from_product([sensor_name_list_str, leakage_position_list]), columns=['PD']) r5 = pd.DataFrame( index=pd.MultiIndex.from_product([sensor_name_list_str, leakage_position_list]), columns=['lpID']) r6 = pd.DataFrame( index=pd.MultiIndex.from_product([sensor_name_list_str, leakage_position_list]), columns=['Times']) r7 = pd.DataFrame( index=pd.MultiIndex.from_product([sensor_name_list_str, leakage_position_list]), columns=['Cover']) recorded_position = [] r2 = r2.sort_index() r3 = r3.sort_index() r4 = r4.sort_index() r5 = r5.sort_index() r6 = r6.sort_index() r7 = r7.sort_index() # 定位 basic_group_num = 10 # 无需修改部分 # load network G0 = construct_graph(wn_origin) # ==================================================================================================================== pressure_basic, flow_basic, basic_p, top_sensor, base_demand = normal_simulation_pf(wn_origin, sensor_name_all, sensor_f_name_all) timestep_list = [0] pipe_x, pipe_y = cal_pipe_coordinate(candidate_pipe_input, pipe_start_node, pipe_end_node, node_coordinates) ## ------------------------------------------------------------------------------------------------------------ ## ---------------------------------------------------------------------------- # get pipe coefficient pipe_coefficient = wn_origin.query_link_attribute('roughness', link_type=wntr.network.model.Pipe) basic_demand_pd = produce_pattern_value(wn_origin, all_node_new) ## ---------------------------------------------------------------------------- # 改_wz_________________________________________ # # noise ======================================================================= # sum_flow = 0 # for p in _pos: # sum_flow += flow_basic[p] # for p in _neg: # sum_flow -= flow_basic[p] # sum_flow = sum_flow.mean() # # noise # node_d_noise = node_d_noise_list[noise_level] # /3.27 # pipe_c_noise = pipe_c_noise_list[noise_level] # /3.27 # # leak_flow_para = 1 * sum_flow.values[0] * 0.017 /3600 # leak_flow_para_mean = 1 * sum_flow * leak_flow_para_mean_list[noise_level] # leak_flow_para_std1 = 1 * sum_flow * leak_flow_para_std1_list[noise_level] # leak_flow_para_std2 = 1 * sum_flow * leak_flow_para_std2_list[noise_level] # noise_para_monitor = noise_para_monitor_list[noise_level] # noise_f_para_monitor = noise_f_para_monitor_list[noise_level] # % velocity = 1 noise_f_max = pipe_diameter ** 2 * math.pi * velocity * noise_f_para_monitor / 400 max_flow = pipe_diameter ** 2 * math.pi * velocity / 4 # noise ======================================================================= # basic_leak_similation ======================================================================= # 进行管段模拟漏损(而非节点模拟漏损),获得每根管道的漏损流量和压力 pressure_leak_all_pre_new_all = pd.DataFrame( index=pd.MultiIndex.from_product([candidate_leak_ratio, candidate_pipe_input_initial, timestep_list]), columns=sensor_name_all) pressure_leak_all_pre_new_all = pressure_leak_all_pre_new_all.sort_index() flow_leak_all_pre_new_all = pd.DataFrame( index=pd.MultiIndex.from_product([candidate_leak_ratio, candidate_pipe_input_initial, timestep_list]), columns=sensor_f_name_all) flow_leak_all_pre_new_all = flow_leak_all_pre_new_all.sort_index() pressure_leak_basic_all = pd.DataFrame( index=pd.MultiIndex.from_product([candidate_leak_ratio, candidate_pipe_input_initial]), columns=sensor_name_all) for pick_leak_ratio in candidate_leak_ratio: # leak_flow_simu = sum_flow * pick_leak_ratio leak_flow_simu = burst_leakage wn = copy.deepcopy(wn_origin) pressure_leak_all_pre, flow_leak_all_pre, leak_candidate_center = cal_signature_pipe_multi_pf(wn, leak_flow_simu, candidate_pipe_input_initial, timestep_list, sensor_name_all, sensor_f_name_all) for each in candidate_pipe_input_initial: pressure_leak_all_pre_new_all.loc[pick_leak_ratio].loc[each].loc[:, :] = pressure_leak_all_pre.loc[ each].loc[:, sensor_name_all] for each in candidate_pipe_input_initial: flow_leak_all_pre_new_all.loc[pick_leak_ratio].loc[each].loc[:, :] = flow_leak_all_pre.loc[each].loc[:, sensor_f_name_all] for candidate_pipe in candidate_pipe_input_initial: pressure_leak_basic_all.loc[pick_leak_ratio].loc[candidate_pipe, :] = pressure_leak_all_pre.loc[ candidate_pipe].loc[:, :].mean() # sensor information ======================================================================= ## ---------------------------------------------------------------------------- DEMAND_COUNT = 0 wn_change = copy.deepcopy(wn_origin) wn = copy.deepcopy(wn_origin) # ========================================================================================================== pressure_basic_basic, flow_basic_basic, basic_p, top_sensor, base_demand = normal_simulation_multi_pf(wn, sensor_name_all, sensor_f_name_all) # for each_candidate in leakage_position_list: # each_candidate='111' # wn = copy.deepcopy(wn_origin) # r1 = pd.DataFrame( # index=sensor_name_list_str, # columns=['TD', 'SD', 'PD', 'lpID', 'Times', 'Cover', 'Simu Count']) # r1 = r1.sort_index() # # recorded_position.append(each_candidate) # leak_index = int(np.round(random.random() * (len(candidate_leak_ratio) - 1))) # leak_flow_simu =candidate_leak_ratio[leak_index] * sum_flow # leak_mag = add_noise_number(leak_flow_simu, 'uni', leak_flow_para) # wn_change = copy.deepcopy(wn_origin) # 获得对应模拟时刻下,正常噪声和添加漏损后的监测点数据 # wn_change, pressure_predict_basic, flow_predict_basic, pressure_output, flow_output = add_noise_in_wn_pf( # wn_change, pipe_c_noise, timestep_list, # pipe_coefficient, sensor_name_all, sensor_f_name_all, all_node_new, # basic_demand_pd, # 'uni', node_d_noise, # each_candidate, leak_mag) # # pressure_monitor_basic = add_noise_pd(pressure_output, 'uni', noise_para_monitor) # flow_monitor_basic = add_noise_percentage_pd(flow_output, 'uni', noise_f_para_monitor) leak_index = int(np.round(random.random() * (len(candidate_leak_ratio) - 1))) leak_mag = leak_flow_simu print('leak_mag' + str(leak_mag * 3600) + '.........') pressure_monitor = pd.DataFrame(index=timestep_list, columns=sensor_name) pressure_predict = pd.DataFrame(index=timestep_list, columns=sensor_name) pressure_basic = pd.DataFrame(index=timestep_list, columns=sensor_name) flow_monitor = pd.DataFrame(index=timestep_list, columns=sensor_f_name) flow_predict = pd.DataFrame(index=timestep_list, columns=sensor_f_name) flow_basic = pd.DataFrame(index=timestep_list, columns=sensor_f_name) for i in range(len(timestep_list)): for sensor_level in sensor_level_list: sensor_name = sensor_name_list[sensor_level] pressure_monitor.iloc[i, :] = burst_SCADA_pressure.loc[sensor_name] pressure_predict.iloc[i, :] = normal_SCADA_pressure.loc[sensor_name] pressure_basic.iloc[i, :] = pressure_basic_basic.loc[:, sensor_name] sensor_f_name = sensor_f_name_list[sensor_level] pressure_leak_all_pre_new = pd.DataFrame( index=pd.MultiIndex.from_product([candidate_pipe_input_initial, timestep_list]), # 笛卡尔积,生成多级索引 columns=sensor_name) pressure_leak_all_pre_new = pressure_leak_all_pre_new.sort_index() # 排序 flow_leak_all_pre_new = pd.DataFrame( index=pd.MultiIndex.from_product([candidate_pipe_input_initial, timestep_list]), columns=sensor_f_name) flow_leak_all_pre_new = flow_leak_all_pre_new.sort_index() for each in candidate_pipe_input_initial: pressure_leak_all_pre_new.loc[each].loc[:, :] = pressure_leak_all_pre_new_all.loc[candidate_leak_ratio[leak_index]].loc[each].loc[:, sensor_name] flow_leak_all_pre_new.loc[each].loc[:, :] = flow_leak_all_pre_new_all.loc[candidate_leak_ratio[leak_index]].loc[each].loc[:, sensor_f_name] wn = copy.deepcopy(wn_origin) # start DN search # ================================================================= use_similarity_mode = similarity_mode_list[sensor_level] flow_monitor.iloc[i, :] = burst_SCADA_flow.loc[sensor_f_name] flow_predict.iloc[i, :] = normal_SCADA_flow.loc[sensor_f_name] flow_basic.iloc[i, :] = flow_basic_basic.loc[:, sensor_f_name] # ================================================================= located_pipe, dt, simu_count, wn, similarity_sp = DN_search_multi_simple_add_flow_count_new(wn, G0, all_node, node_x, node_y, pipe_start_node_all, pipe_end_node_all, couple_node_length, node_pipe_dic, all_node_series, top_group_ratio, top_pipe_num_max, top_pipe_num_min, candidate_pipe_input_initial, use_similarity_mode, pressure_monitor, pressure_predict, pressure_basic, pressure_leak_all_pre_new, flow_monitor, flow_predict, flow_basic, flow_leak_all_pre_new, timestep_list, max_flow, basic_group_num, Top_sensor_num=len( sensor_name), if_gy=0, pressure_threshold=0.05) print(located_pipe, dt, simu_count, similarity_sp) # if len(list(similarity_sp.index)) == 0: # SD = 9999 # TD = 9999 # PD = 90 # lpID = '' # cover = 0 # else: # SD = cal_SD(located_pipe, each_candidate, pipe_x, pipe_y) # TD, PD = cal_DtoTop1(G0, each_candidate, located_pipe, pipe_start_node_all, pipe_end_node_all, # pipe_length) # lpID = located_pipe # cover = cal_cover(similarity_sp, each_candidate) # r1.loc[sensor_name_list_str[sensor_level]].loc['TD'] = TD # 定位拓扑距离 # r1.loc[sensor_name_list_str[sensor_level]].loc['SD'] = SD # 定位空间距离 # r1.loc[sensor_name_list_str[sensor_level]].loc['lpID'] = lpID # 不重要的参数,可删去 # r1.loc[sensor_name_list_str[sensor_level]].loc['Times'] = dt # 定位时间 # r1.loc[sensor_name_list_str[sensor_level]].loc['Cover'] = cover # 覆盖率 # r1.loc[sensor_name_list_str[sensor_level]].loc['PD'] = PD # 定位拓扑连接数 # r1.loc[sensor_name_list_str[sensor_level]].loc['Simu Count'] = simu_count # 模拟次数 # # # --- 获取当前候选点的前10管道 --- # top_10_pipes = similarity_sp.head(10) # df_to_export = pd.DataFrame({ # "管道ID": top_10_pipes.index, # "特征相似值": top_10_pipes.values # }) # sheet_name = str(each_candidate) # # --- 写入当前候选点的子表 --- # df_to_export.to_excel( # writer, # sheet_name=sheet_name, # index=False, # header=True # ) # print(f"所有候选点的相似度排名已保存") # # print( # 'finish candidate:' + each_candidate + ' and total calculation times:' + str( # DEMAND_COUNT) + '..') # # # r1.to_excel(writer, sheet_name=each_candidate) # # for sensor_level in sensor_level_list: # sensor_name = sensor_name_list_str[sensor_level] # # 获取该传感器在r1中的所有相关数据 # sensor_data = r1.loc[sensor_name] # r2.loc[(sensor_name, each_candidate)] = sensor_data['TD'] # r3.loc[(sensor_name, each_candidate)] = sensor_data['SD'] # r4.loc[(sensor_name, each_candidate)] = sensor_data['PD'] # r5.loc[(sensor_name, each_candidate)] = sensor_data['lpID'] # r6.loc[(sensor_name, each_candidate)] = sensor_data['Times'] # r7.loc[(sensor_name, each_candidate)] = sensor_data['Cover'] # # DEMAND_COUNT += 1 # print('finish' + str(DEMAND_COUNT) + 'candidates.........') # if DEMAND_COUNT > 1: # # for sensor_level in sensor_level_list: # print('sensor_level_' + str(sensor_level)) # print('--SD: ' + # str(r3.loc[sensor_name_list_str[sensor_level]].loc[recorded_position].mean()) + # ', nowTD:' + str(r2.loc[sensor_name_list_str[sensor_level]].loc[each_candidate].mean()) + # ', PD:' + str(r3.loc[sensor_name_list_str[sensor_level]].loc[recorded_position].mean()) + # ', Cover:' + str(r7.loc[sensor_name_list_str[sensor_level]].loc[recorded_position].mean()) ) # # print('====================================================') # # # # 保存的文件 里面包含的评估参数 主要的就是TD Cover TD # r2.to_excel(writer, sheet_name='TD') # r3.to_excel(writer, sheet_name='SD') # r4.to_excel(writer, sheet_name='PD') # r5.to_excel(writer, sheet_name='lpID') # r6.to_excel(writer, sheet_name='Times') # r7.to_excel(writer, sheet_name='Cover') # writer._save() if __name__ == '__main__': # influxdb_api.query_corresponding_query_id_and_element_id('bb') # pressure_SCADA_ID_list = [list(globals.scheme_pressure_ids.values())] # # print(pressure_SCADA_ID_list) # flow_SCADA_ID_list = [list(globals.scheme_pipe_flow_ids.values())] # burst_leakage = influxdb_api.manually_get_burst_flow(scheme_Type='burst_Analysis', scheme_Name='burst_scheme', scheme_start_time='2025-03-10T12:00:00+08:00') # # print(burst_leakage) burst_SCADA_pressure, pressure_SCADA_IDs_list, normal_SCADA_pressure = manually_get_burst_time_SCADA_pressure(name='bb', manually_burst_time='2025-03-30T12:00:00+08:00', scheme_Type='burst_Analysis', scheme_Name='test0618') print(type(pressure_SCADA_IDs_list), pressure_SCADA_IDs_list) ## 平铺 pressure_SCADA_IDs_list # SCADA数据有问题,使用模拟数据代替SCADA真实数据 flat_ids = [item for sublist in pressure_SCADA_IDs_list for item in sublist] result_records = influxdb_api.query_all_record_by_time_property(query_time='2025-03-30T12:00:00+08:00', type='node', property='pressure') simulation_normal_SCADA_presssure = [record for record in result_records if record['ID'] in flat_ids] normal_SCADA_pressure = {record['ID']: record['value'] for record in simulation_normal_SCADA_presssure} print(normal_SCADA_pressure) normal_SCADA_pressure = pd.Series(normal_SCADA_pressure) normal_SCADA_pressure = normal_SCADA_pressure.reindex(burst_SCADA_pressure.index) # burst_flow = manually_get_burst_flow(scheme_Type='burst_Analysis', scheme_Name='test0618', # burst_start_time='2025-03-30T12:00:00+08:00') flow_SCADA_ID_list = [[]] burst_SCADA_flow = pd.Series(index=[], dtype=float) normal_SCADA_flow = pd.Series(index=[], dtype=float) if_detect, tag = cal_if_detect(burst_SCADA_pressure=burst_SCADA_pressure, normal_SCADA_pressure=normal_SCADA_pressure, min_dpressure=2.0) locate_burst(name='bb', pressure_SCADA_ID_list=pressure_SCADA_IDs_list, burst_SCADA_pressure=burst_SCADA_pressure, normal_SCADA_pressure=normal_SCADA_pressure, flow_SCADA_ID_list=flow_SCADA_ID_list, burst_SCADA_flow=burst_SCADA_flow, normal_SCADA_flow=normal_SCADA_flow, burst_leakage=0.057, burst_happen_time='2025-03-30T12:00:00+08:00')