started stripping down risk-and-reliability to create template

This commit is contained in:
Guilherme Alvarenga 2024-02-23 18:02:52 +02:00
parent 6697c0f5f8
commit 75ff95fa67
127 changed files with 54699 additions and 0 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 KiB

View file

@ -0,0 +1,163 @@
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
def find_scenarios_with_segment_i(segments_fixed, df):
"""Given a list of segments, return set of dependent scenarios."""
idx = []
segments_fixed = set(segments_fixed)
for i, row in enumerate(df['failed_segments'].values):
segments_row = set([int(seg) for seg in row.split(",")])
intersection = list(segments_fixed.intersection(segments_row))
if len(intersection) > 0:
idx.append(True)
else:
idx.append(False)
segment_table = df.iloc[idx]
return segment_table
def assemble_analysis_cases(df):
"""From scenario dataframe collect damage and fatality information."""
econ_damage_case_1 = df.iloc[:,3] # Unexpected, no evacuation
econ_damage_case_2 = df.iloc[:,5] # Unexpected, unorganised evacuation
econ_damage_case_3 = df.iloc[:,7] # Expected, unorganised evacuation
econ_damage_case_4 = df.iloc[:,9] # Expected, organised evacuation
fatalities_case_1 = df.iloc[:,4]
fatalities_case_2 = df.iloc[:,6]
fatalities_case_3 = df.iloc[:,8]
fatalities_case_4 = df.iloc[:,10]
scenario_prob = df.iloc[:,1] # scenario probability
cases = {'damage': [econ_damage_case_1, econ_damage_case_2, econ_damage_case_3, econ_damage_case_4],
'fatality': [fatalities_case_1, fatalities_case_2, fatalities_case_3, fatalities_case_4]}
return cases
def exceedance_prob(cases, scenario_prob):
"""Compute exceedance probability."""
case_1 = cases[0]
case_2 = cases[1]
case_3 = cases[2]
case_4 = cases[3]
key = case_1.index
# Combine Evacuation Scenarios into new Dataframe
scenarios = [pd.DataFrame({'Nr': key, 'N/D': case_1}),
pd.DataFrame({'Nr': key, 'N/D': case_2}),
pd.DataFrame({'Nr': key, 'N/D': case_3}),
pd.DataFrame({'Nr': key, 'N/D': case_4})]
scen_combi = pd.concat(scenarios, ignore_index=True)
# Sort values by key ('Nr')
scen_combi_sorted = scen_combi.sort_values(by=['Nr']) # useful if scen_combi_nodup.sort_values(by=['Nr']) in case of no duplicates
# scen_combi_sorted = scen_combi.reset_index(drop=True) # Reset index starting from 0
# Create new Dataframe for scenario prob with corresponding key
prob = pd.DataFrame({'Nr': key, 'scen_prob':scenario_prob})
# Join both Dataframes based on common key
join_scen_prob = scen_combi_sorted.join(prob.set_index('Nr'), on='Nr')
# Determine Exceedance Probability
sorted_N_D = scen_combi.sort_values(by=['N/D']) # Sort N/D based on ascending order
complete_table = sorted_N_D.join(prob.set_index('Nr'), on='Nr')
N_D_prob_ordered = complete_table.iloc[:,2]
# N_D = join_scen_prob.dropna(axis=0).iloc[:,1].reset_index(drop=True) # N/D
# N_D_prob = join_scen_prob.dropna(axis=0).iloc[:,2].reset_index(drop=True) # Corresponding scenario prob
# print('N_D', N_D)
# print('N_D_PROB', N_D_prob)
# order = N_D.argsort() # Sort N/D based on ascending order
# N_D_prob_ordered = N_D_prob[order]
N_D_prob_cs = np.cumsum(N_D_prob_ordered[::-1]) # Take cumulative sum of reversed order
exceed_prob = (1/4) * N_D_prob_cs[::-1] # Reverse result (1-FN(n)) and /4 as 4 evacuation scenarios are considered
complete_table = complete_table.join(exceed_prob, lsuffix='_orignal', rsuffix='_new') # complete resulting table
# N_D_ordered = N_D[order].reset_index(drop=True)
N_D_ordered = complete_table.iloc[:,1]
return N_D_ordered, exceed_prob, complete_table
def sensitivity_analysis(cases, scenario_prob, idx_segment, N_D_ordered_original, exceed_prob_original, complete_table):
"""Docstring incomplete."""
case_1 = cases[0]
case_2 = cases[1]
case_3 = cases[2]
case_4 = cases[3]
# Dropping segment(s)
case_1_exc = case_1.drop(idx_segment, axis=0).reset_index(drop=True)
case_2_exc = case_2.drop(idx_segment, axis=0).reset_index(drop=True)
case_3_exc = case_3.drop(idx_segment, axis=0).reset_index(drop=True)
case_4_exc = case_4.drop(idx_segment, axis=0).reset_index(drop=True)
scenario_prob_exc = scenario_prob.drop(idx_segment, axis=0).reset_index(drop=True)
# Determine new exceedance probability - Excluding segment(s)
N_D_ordered_new, exceed_prob_new, complete_table_new = exceedance_prob([case_1_exc, case_2_exc, case_3_exc, case_4_exc], scenario_prob_exc)
# Plotting
plot_curves(N_D_ordered_original, exceed_prob_original)
plt.plot(N_D_ordered_new.dropna(axis=0), exceed_prob_new.dropna(axis=0), marker="o", linewidth=2, markersize=5, color= 'darkblue', label='Excluding segment(s)', zorder=10)
# Plot dropped points
x_point = []
y_point = []
for i in range(len(idx_segment)):
row_i = complete_table[complete_table['Nr']== (idx_segment[i] + 1)]
for j in range(len(row_i)):
x_point.append(row_i.iloc[j, 1])
y_point.append(row_i.iloc[j, 3])
plt.scatter(x_point, y_point, label='Dropped Points', s=45, color='darkred', zorder=15) # Plot the points corresponding to deleted segment
plt.legend()
plt.show()
return N_D_ordered_new, exceed_prob_new, complete_table_new
def plot_curves(N_D, exceedance_prob):
"""Plot FN or FD risk curve."""
plt.figure(figsize=(10,6))
set_TUDstyle()
# Plot FN/FD curve
plt.plot(N_D, exceedance_prob, marker="o", linewidth=2, markersize=5, label='FN/D-curve',zorder=0)
# Add acceptable limit line
ND = np.linspace(1,100000,100000) # fatalities
alpha = 1
C = 0.010
limit_line = (C/ND**alpha)
plt.plot(limit_line, linewidth=2, color='darkgreen', label='Acceptable Limit Line', zorder=5)
# Styling
plt.yscale('log')
plt.xscale('log')
plt.grid(True, which="both", axis='x')
plt.grid(True, which="major", axis='y')
plt.title('FN/D-curve')
plt.ylabel('Probability of Exceedance, $1-F_N(n)$')
plt.xlabel('Economic damage [meuro] / Fatalities')
plt.xlim(1,100000)
plt.ylim(10**(-7),10**(-3))
plt.legend()
def compute_benefit(table_old, table_new):
"""Compute new and old consequences and net benefit."""
old_consequences = np.sum(table_old["N/D"].values * table_old["scen_prob_new"].values)
new_consequences = np.sum(table_new["N/D"].values * table_new["scen_prob_new"].values)
benefit = old_consequences - new_consequences
return old_consequences, new_consequences, benefit
def set_TUDstyle():
TUcolor = {"cyan": "#00A6D6", "darkgreen": "#009B77", "purple": "#6F1D77",
"darkred": "#A50034", "darkblue": "#0C2340",
"orange": "#EC6842", "green": "#6CC24A",
"lightcyan": "#00B8C8", "red": "#E03C31", "pink": "#EF60A3",
"yellow": "#FFB81C", "blue": "#0076C2"}
plt.rcParams.update({'axes.prop_cycle': plt.cycler(color=TUcolor.values()),
'font.size': 16, "lines.linewidth": 4})
return TUcolor