Skip to content

Commit a624b6d

Browse files
committed
Bugfix in rWHALE's aggregate loss output
The aggregate_results function was aggregating losses across components for each asset. This is unnecessary since it is already done by Pelicun earlier in the workflow. Aggregation can be more complex than simply summing up losses for each component. So, it is more appropriate to use the DL_summary_stats file directly and rely on Pelicun to take care of the appropriate aggregation. This commit modifies the code to drop the old functionality and utilize DL_summary_stats. In another, minor update, it also fixes a bug in naming. R2Dres_mean_RepairCost is used when results are scaled with replacement costs. When such scaling is not performed, the R2Dres_mean_RepairCost_{cost_unit} naming is used. Consequently, when loss ratios are returned by a method and we have replacement cost available, rWHALE will return both the loss ratios and the absolute losses.
1 parent 8dc806a commit a624b6d

1 file changed

Lines changed: 52 additions & 43 deletions

File tree

modules/Workflow/whale/main.py

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3126,7 +3126,7 @@ def aggregate_results( # noqa: C901, PLR0912, PLR0915
31263126
# deter_pointer[asset_id].update({
31273127
# "R2Dres":r2d_res_i
31283128
# })
3129-
if 'DMG' in out_types:
3129+
if 'DM' in out_types:
31303130
dmg_out_file_i = 'DMG_grp.json'
31313131

31323132
if dmg_out_file_i not in os.listdir(asset_dir):
@@ -3188,16 +3188,25 @@ def aggregate_results( # noqa: C901, PLR0912, PLR0915
31883188

31893189
if 'DV' in out_types:
31903190
dv_out_file_i = 'DV_repair_grp.json'
3191+
dl_summary_file = 'DL_summary_stats.json'
31913192

31923193
if dv_out_file_i not in os.listdir(asset_dir):
31933194
show_warning(
31943195
f"Couldn't find DV file for {assetTypeHierarchy[-1]} {asset_id}"
31953196
)
31963197

3198+
elif dl_summary_file not in os.listdir(asset_dir):
3199+
show_warning(
3200+
f"Couldn't find DL summary file for {assetTypeHierarchy[-1]} {asset_id}"
3201+
)
3202+
31973203
else:
31983204
with open(asset_dir / dv_out_file_i, encoding='utf-8') as f: # noqa: PTH123
31993205
dv_data_i = json.load(f)
32003206

3207+
with open(asset_dir / dl_summary_file, encoding='utf-8') as f: # noqa: PTH123
3208+
dl_summary = json.load(f)
3209+
32013210
# extract DV unit info
32023211
dv_units = dv_data_i['Units']
32033212
del dv_data_i['Units']
@@ -3243,48 +3252,48 @@ def aggregate_results( # noqa: C901, PLR0912, PLR0915
32433252

32443253
if 'DV' in R2D_res_out_types:
32453254
r2d_res_dv = dict() # noqa: C408
3246-
cost_columns = [
3247-
col
3248-
for col in dv_data_i.columns
3249-
if col.startswith('Cost')
3250-
]
3251-
if len(cost_columns) != 0:
3252-
cost_data = dv_data_i[cost_columns].mean()
3253-
cost_data_std = dv_data_i[cost_columns].std()
3254-
cost_key = cost_data.idxmax()
3255-
meanKey = ( # noqa: N806
3256-
f'R2Dres_mean_RepairCost_{dv_units[cost_key]}'
3257-
)
3258-
stdKey = ( # noqa: N806
3259-
f'R2Dres_std_RepairCost_{dv_units[cost_key]}'
3260-
)
3261-
r2d_res_dv.update(
3262-
{
3263-
meanKey: cost_data[cost_key],
3264-
stdKey: cost_data_std[cost_key],
3265-
}
3266-
)
3267-
time_columns = [
3268-
col
3269-
for col in dv_data_i.columns
3270-
if col.startswith('Time')
3271-
]
3272-
if len(time_columns) != 0:
3273-
time_data = dv_data_i[time_columns].mean()
3274-
time_data_std = dv_data_i[time_columns].std()
3275-
time_key = time_data.idxmax()
3276-
meanKey = ( # noqa: N806
3277-
f'R2Dres_mean_RepairTime_{dv_units[time_key]}'
3278-
)
3279-
stdKey = ( # noqa: N806
3280-
f'R2Dres_std_RepairTime_{dv_units[time_key]}'
3281-
)
3282-
r2d_res_dv.update(
3283-
{
3284-
meanKey: time_data[time_key],
3285-
stdKey: time_data_std[time_key],
3286-
}
3287-
)
3255+
3256+
if 'repair_cost' in dl_summary:
3257+
repair_cost_data = dl_summary['repair_cost']
3258+
3259+
elif 'repair_cost-' in dl_summary:
3260+
repair_cost_data = dl_summary['repair_cost-']
3261+
3262+
else:
3263+
repair_cost_data = None
3264+
3265+
if repair_cost_data:
3266+
3267+
cost_unit = [unit for dv_output, unit in dv_units.items() if dv_output.startswith('Cost')][0]
3268+
3269+
r2d_res_dv.update({
3270+
f'R2Dres_mean_RepairCost_{cost_unit}': repair_cost_data['mean'],
3271+
f'R2Dres_std_RepairCost_{cost_unit}': repair_cost_data['std']
3272+
})
3273+
3274+
if cost_unit == 'loss_ratio' and np.abs(replacement_cost-1.0)>1e-5:
3275+
r2d_res_dv.update({
3276+
f'R2Dres_mean_RepairCost': repair_cost_data['mean'] * replacement_cost,
3277+
f'R2Dres_std_RepairCost': repair_cost_data['std'] * replacement_cost
3278+
})
3279+
3280+
if 'repair_time' in dl_summary:
3281+
repair_time_data = dl_summary['repair_time']
3282+
3283+
elif 'repair_time-sequential' in dl_summary:
3284+
repair_time_data = dl_summary['repair_time-sequential']
3285+
3286+
else:
3287+
repair_time_data = None
3288+
3289+
if repair_time_data:
3290+
3291+
time_unit = [unit for dv_output, unit in dv_units.items() if dv_output.startswith('Time')][0]
3292+
3293+
r2d_res_dv.update({
3294+
f'R2Dres_mean_RepairTime_{time_unit}': repair_time_data['mean'],
3295+
f'R2Dres_std_RepairTime_{time_unit}': repair_time_data['std']
3296+
})
32883297

32893298
r2d_res_i = deter_pointer[asset_id].get('R2Dres', {})
32903299
r2d_res_i.update(r2d_res_dv)

0 commit comments

Comments
 (0)