Skip to content

Commit f0f635b

Browse files
committed
Tidies up calc_risk_metrics
1 parent 2a0cf66 commit f0f635b

File tree

1 file changed

+67
-69
lines changed

1 file changed

+67
-69
lines changed

climada/trajectories/calc_risk_metrics.py

Lines changed: 67 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,39 @@ def impact_computation_strategy(self, value, /):
555555
self._impact_computation_strategy = value
556556
self._reset_impact_data()
557557

558-
##### Impact objects cube / Risk Cube #####
558+
def apply_measure(self, measure: Measure) -> "CalcRiskMetricsPeriod":
559+
"""Creates a new `CalcRiskMetricsPeriod` object with a measure.
560+
561+
The given measure is applied to both snapshot of the risk period.
562+
563+
Parameters
564+
----------
565+
measure : Measure
566+
The measure to apply.
567+
568+
Returns
569+
-------
570+
571+
CalcRiskPeriod
572+
The risk period with given measure applied.
573+
574+
"""
575+
snap0 = self.snapshot_start.apply_measure(measure)
576+
snap1 = self.snapshot_end.apply_measure(measure)
577+
578+
risk_period = CalcRiskMetricsPeriod(
579+
snap0,
580+
snap1,
581+
self.time_resolution,
582+
self.interpolation_strategy,
583+
self.impact_computation_strategy,
584+
)
585+
586+
risk_period.measure = measure
587+
return risk_period
588+
589+
###################################################
590+
##### Impact objects cube / Risk Cube corners #####
559591

560592
@lazy_property
561593
def E0H0V0(self) -> Impact:
@@ -631,7 +663,8 @@ def E1H1V1(self) -> Impact:
631663

632664
###############################
633665

634-
### Impact Matrices arrays ####
666+
#################################################
667+
### Impact Matrices arrays / Risk Cube edges ####
635668

636669
def _interp_mats(self, start_attr, end_attr) -> list:
637670
"""Helper to reduce repetition in impact matrix interpolation."""
@@ -661,23 +694,26 @@ def imp_mats_H1V1(self) -> list:
661694
"""List of `time_points` impact matrices with changing exposure, future hazard and future vulnerability."""
662695
return self._interp_mats("E0H1V1", "E1H1V1")
663696

697+
### The following are for risk contributions
698+
664699
@property
665700
def imp_mats_E0H0V0(self) -> list:
666701
"""List of `time_points` impact matrices with base exposure, base hazard and base vulnerability."""
667-
return self._interp_mats("E0H0V0", "E0H0V0")
702+
return [self.E0H0V0.imp_mat] * self.time_points
668703

669704
@property
670705
def imp_mats_E0H1V0(self) -> list:
671706
"""List of `time_points` impact matrices with base exposure, future hazard and base vulnerability."""
672-
return self._interp_mats("E0H1V0", "E0H1V0")
707+
return [self.E0H1V0.imp_mat] * self.time_points
673708

674709
@property
675710
def imp_mats_E0H0V1(self) -> list:
676711
"""List of `time_points` impact matrices with base exposure, base hazard and base vulnerability."""
677-
return self._interp_mats("E0H0V1", "E0H0V1")
712+
return [self.E0H0V1.imp_mat] * self.time_points
678713

679714
###############################
680715

716+
###############################
681717
########## Core EAI ###########
682718

683719
@property
@@ -729,10 +765,12 @@ def per_date_eai_E0H0V1(self) -> np.ndarray:
729765
self.imp_mats_E0H0V1, self.snapshot_start.hazard.frequency
730766
)
731767

732-
##################################
733-
768+
##############################
734769
######### Core AAIs ##########
735770

771+
# Not required for final AAIs computation (we use final EAIs instead),
772+
# but could be useful in the future?
773+
736774
@property
737775
def per_date_aai_H0V0(self) -> np.ndarray:
738776
"""Average annual impacts for changing exposure, starting hazard and starting vulnerability."""
@@ -768,8 +806,7 @@ def per_date_aai_E0H0V1(self) -> np.ndarray:
768806
"""Average annual impacts for base exposure, base hazard and base vulnerability."""
769807
return calc_per_date_aais(self.per_date_eai_E0H0V1)
770808

771-
#################################
772-
809+
#############################
773810
######### Core RPs #########
774811

775812
def per_date_return_periods_H0V0(self, return_periods: list[int]) -> np.ndarray:
@@ -809,8 +846,9 @@ def per_date_return_periods_H1V1(self, return_periods: list[int]) -> np.ndarray:
809846
)
810847

811848
##################################
849+
##### Interpolation of metrics ###
812850

813-
##### Interpolation of metrics #####
851+
# Actual results
814852

815853
def calc_eai(self) -> np.ndarray:
816854
"""Compute the EAIs at each date of the risk period (including changes in exposure, hazard and vulnerability)."""
@@ -843,8 +881,10 @@ def per_date_aai(self) -> np.ndarray:
843881
"""Average annual impacts per date with changing exposure, changing hazard and changing vulnerability."""
844882
return calc_per_date_aais(self.per_date_eai)
845883

846-
@lazy_property
847-
def eai_gdf(self) -> pd.DataFrame:
884+
####################################
885+
######## Tidying results ###########
886+
887+
def calc_eai_gdf(self) -> pd.DataFrame:
848888
"""Convenience function returning a DataFrame (with both datetime and coordinates ids) from `per_date_eai`.
849889
850890
This dataframe can easily be merged with one of the snapshot exposure geodataframe.
@@ -855,19 +895,6 @@ def eai_gdf(self) -> pd.DataFrame:
855895
The DataFrame from the starting snapshot is used as a basis (notably for `value` and `group_id`).
856896
857897
"""
858-
return self.calc_eai_gdf()
859-
860-
####################################
861-
862-
### Metrics from impact matrices ###
863-
864-
# These methods might go in a utils file instead, to be reused
865-
# for a no interpolation case (and maybe the timeseries?)
866-
867-
####################################
868-
869-
def calc_eai_gdf(self) -> pd.DataFrame:
870-
"""Merge the per date EAIs of the risk period with the GeoDataframe of the exposure of the starting snapshot."""
871898
df = pd.DataFrame(self.per_date_eai, index=self.date_idx)
872899
df = df.reset_index().melt(
873900
id_vars=DEFAULT_PERIOD_INDEX_NAME,
@@ -924,7 +951,8 @@ def calc_aai_per_group_metric(self) -> pd.DataFrame | None:
924951
)
925952
return None
926953

927-
eai_pres_groups = self.eai_gdf[
954+
eai_gdf = self.calc_eai_gdf()
955+
eai_pres_groups = eai_gdf[
928956
[
929957
DEFAULT_PERIOD_INDEX_NAME,
930958
COORD_ID_COL_NAME,
@@ -939,7 +967,7 @@ def calc_aai_per_group_metric(self) -> pd.DataFrame | None:
939967
LOGGER.warning(
940968
"Group id are changing between present and future snapshot. Per group AAI will be linearly interpolated."
941969
)
942-
eai_fut_groups = self.eai_gdf.copy()
970+
eai_fut_groups = eai_gdf.copy()
943971
eai_fut_groups[GROUP_COL_NAME] = pd.Categorical(
944972
np.tile(self._group_id_E1, len(self.date_idx)),
945973
categories=self._groups_id,
@@ -1009,24 +1037,24 @@ def calc_risk_contributions_metric(self) -> pd.DataFrame:
10091037
hazard and vulnerability).
10101038
10111039
"""
1012-
per_date_aai_E0V0 = self.interpolation_strategy.interp_over_hazard_dim(
1040+
aai_changes_hazard_only = self.interpolation_strategy.interp_over_hazard_dim(
10131041
self.per_date_aai_E0H0V0, self.per_date_aai_E0H1V0
10141042
)
1015-
per_date_aai_E0H0 = self.interpolation_strategy.interp_over_vulnerability_dim(
1016-
self.per_date_aai_E0H0V0, self.per_date_aai_E0H0V1
1043+
aai_changes_vulnerability_only = (
1044+
self.interpolation_strategy.interp_over_vulnerability_dim(
1045+
self.per_date_aai_E0H0V0, self.per_date_aai_E0H0V1
1046+
)
10171047
)
10181048
df = pd.DataFrame(
10191049
{
10201050
CONTRIBUTION_TOTAL_RISK_NAME: self.per_date_aai,
10211051
CONTRIBUTION_BASE_RISK_NAME: self.per_date_aai[0],
10221052
CONTRIBUTION_EXPOSURE_NAME: self.per_date_aai_H0V0
10231053
- self.per_date_aai[0],
1024-
CONTRIBUTION_HAZARD_NAME: per_date_aai_E0V0
1025-
# - (self.per_date_aai_H0V0 - self.per_date_aai[0])
1054+
CONTRIBUTION_HAZARD_NAME: aai_changes_hazard_only
10261055
- self.per_date_aai[0],
1027-
CONTRIBUTION_VULNERABILITY_NAME: per_date_aai_E0H0
1056+
CONTRIBUTION_VULNERABILITY_NAME: aai_changes_vulnerability_only
10281057
- self.per_date_aai[0],
1029-
# - (self.per_date_aai_H0V0 - self.per_date_aai[0]),
10301058
},
10311059
index=self.date_idx,
10321060
)
@@ -1056,36 +1084,9 @@ def calc_risk_contributions_metric(self) -> pd.DataFrame:
10561084
df[UNIT_COL_NAME] = self.snapshot_start.exposure.value_unit
10571085
return df
10581086

1059-
def apply_measure(self, measure: Measure) -> "CalcRiskMetricsPeriod":
1060-
"""Creates a new `CalcRiskMetricsPeriod` object with a measure.
1061-
1062-
The given measure is applied to both snapshot of the risk period.
1063-
1064-
Parameters
1065-
----------
1066-
measure : Measure
1067-
The measure to apply.
10681087

1069-
Returns
1070-
-------
1071-
1072-
CalcRiskPeriod
1073-
The risk period with given measure applied.
1074-
1075-
"""
1076-
snap0 = self.snapshot_start.apply_measure(measure)
1077-
snap1 = self.snapshot_end.apply_measure(measure)
1078-
1079-
risk_period = CalcRiskMetricsPeriod(
1080-
snap0,
1081-
snap1,
1082-
self.time_resolution,
1083-
self.interpolation_strategy,
1084-
self.impact_computation_strategy,
1085-
)
1086-
1087-
risk_period.measure = measure
1088-
return risk_period
1088+
####################################
1089+
### Metrics from impact matrices ###
10891090

10901091

10911092
def calc_per_date_eais(imp_mats: list[csr_matrix], frequency: np.ndarray) -> np.ndarray:
@@ -1106,10 +1107,9 @@ def calc_per_date_eais(imp_mats: list[csr_matrix], frequency: np.ndarray) -> np.
11061107
2D array of EAI (1D) for each dates.
11071108
11081109
"""
1109-
per_date_eai_exp = np.array(
1110+
return np.array(
11101111
[ImpactCalc.eai_exp_from_mat(imp_mat, frequency) for imp_mat in imp_mats]
11111112
)
1112-
return per_date_eai_exp
11131113

11141114

11151115
def calc_per_date_aais(per_date_eai_exp: np.ndarray) -> np.ndarray:
@@ -1127,10 +1127,9 @@ def calc_per_date_aais(per_date_eai_exp: np.ndarray) -> np.ndarray:
11271127
np.ndarray
11281128
1D array of AAI (0D) for each dates.
11291129
"""
1130-
per_date_aai = np.array(
1130+
return np.array(
11311131
[ImpactCalc.aai_agg_from_eai_exp(eai_exp) for eai_exp in per_date_eai_exp]
11321132
)
1133-
return per_date_aai
11341133

11351134

11361135
def calc_per_date_rps(
@@ -1158,13 +1157,12 @@ def calc_per_date_rps(
11581157
2D array of impacts per return periods (1D) for each dates.
11591158
11601159
"""
1161-
rp = np.array(
1160+
return np.array(
11621161
[
11631162
calc_freq_curve(imp_mat, frequency, frequency_unit, return_periods).impact
11641163
for imp_mat in imp_mats
11651164
]
11661165
)
1167-
return rp
11681166

11691167

11701168
def calc_freq_curve(

0 commit comments

Comments
 (0)