Reorganize algorithm packages by business responsibility, move orchestration into services, and keep database access behind pooled repositories. Harden analysis API validation, remove unsafe legacy simulation endpoints, and add regression and architecture boundary coverage. BREAKING CHANGE: legacy algorithm module paths and obsolete simulation endpoints are removed.
198 lines
7.1 KiB
Python
198 lines
7.1 KiB
Python
"""噪声生成模块。"""
|
|
|
|
import copy
|
|
import random
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
|
|
from .leak_signature import simple_add_leak, simple_recover_wn, simple_simulation_pf
|
|
|
|
|
|
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 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):
|
|
sample_node = wn.get_node(all_node[0])
|
|
# num_categories = len(sample_node.demand_timeseries_list)
|
|
num_categories = 1
|
|
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 change_para_of_wn(wn, pipe_roughness_change):
|
|
for pipe_name, pipe in wn.pipes():
|
|
pipe.roughness = pipe_roughness_change[pipe_name]
|
|
return wn
|
|
|