@@ -38,10 +38,11 @@ def compute_impacts(
3838 self ,
3939 snapshot0 : Snapshot ,
4040 snapshot1 : Snapshot ,
41+ future : tuple [int , int , int ],
4142 risk_transf_attach : float | None ,
4243 risk_transf_cover : float | None ,
4344 calc_residual : bool ,
44- ) -> tuple :
45+ ) -> Impact :
4546 pass
4647
4748
@@ -52,47 +53,40 @@ def compute_impacts(
5253 self ,
5354 snapshot0 : Snapshot ,
5455 snapshot1 : Snapshot ,
56+ future : tuple [int , int , int ],
5557 risk_transf_attach : float | None ,
5658 risk_transf_cover : float | None ,
5759 calc_residual : bool = False ,
5860 ):
59- impacts = self ._calculate_impacts_for_snapshots (snapshot0 , snapshot1 )
61+ impact = self .compute_impacts_pre_transfer (snapshot0 , snapshot1 , future )
6062 self ._apply_risk_transfer (
61- impacts , risk_transf_attach , risk_transf_cover , calc_residual
63+ impact , risk_transf_attach , risk_transf_cover , calc_residual
6264 )
63- return impacts
65+ return impact
6466
65- def _calculate_impacts_for_snapshots (
66- self , snapshot0 : Snapshot , snapshot1 : Snapshot
67- ):
68- """Calculate impacts for the given snapshots and impact function set."""
69- imp_E0H0 = ImpactCalc (
70- snapshot0 .exposure , snapshot0 .impfset , snapshot0 .hazard
71- ).impact ()
72- imp_E1H0 = ImpactCalc (
73- snapshot1 .exposure , snapshot1 .impfset , snapshot0 .hazard
74- ).impact ()
75- imp_E0H1 = ImpactCalc (
76- snapshot0 .exposure , snapshot0 .impfset , snapshot1 .hazard
77- ).impact ()
78- imp_E1H1 = ImpactCalc (
79- snapshot1 .exposure , snapshot1 .impfset , snapshot1 .hazard
80- ).impact ()
81- return imp_E0H0 , imp_E1H0 , imp_E0H1 , imp_E1H1
67+ def compute_impacts_pre_transfer (
68+ self ,
69+ snapshot0 : Snapshot ,
70+ snapshot1 : Snapshot ,
71+ future : tuple [int , int , int ],
72+ ) -> Impact :
73+ exp = snapshot1 .exposure if future [0 ] else snapshot0 .exposure
74+ haz = snapshot1 .hazard if future [1 ] else snapshot0 .hazard
75+ vul = snapshot1 .impfset if future [2 ] else snapshot0 .impfset
76+ return ImpactCalc (exposures = exp , impfset = vul , hazard = haz ).impact ()
8277
8378 def _apply_risk_transfer (
8479 self ,
85- impacts : tuple [ Impact , Impact , Impact , Impact ] ,
80+ impact : Impact ,
8681 risk_transf_attach : float | None ,
8782 risk_transf_cover : float | None ,
8883 calc_residual : bool ,
8984 ):
9085 """Apply risk transfer to the calculated impacts."""
9186 if risk_transf_attach is not None and risk_transf_cover is not None :
92- for imp in impacts :
93- imp .imp_mat = self .calculate_residual_or_risk_transfer_impact_matrix (
94- imp .imp_mat , risk_transf_attach , risk_transf_cover , calc_residual
95- )
87+ impact .imp_mat = self .calculate_residual_or_risk_transfer_impact_matrix (
88+ impact .imp_mat , risk_transf_attach , risk_transf_cover , calc_residual
89+ )
9690
9791 def calculate_residual_or_risk_transfer_impact_matrix (
9892 self , imp_mat , risk_transf_attach , risk_transf_cover , calc_residual
@@ -111,9 +105,9 @@ def calculate_residual_or_risk_transfer_impact_matrix(
111105 ----------
112106 imp_mat : scipy.sparse.csr_matrix
113107 The original impact matrix to be scaled.
114- attachment : float, optional
108+ attachment : float
115109 The attachment point for the risk layer.
116- cover : float, optional
110+ cover : float
117111 The maximum coverage for the risk layer.
118112 calc_residual : bool, default=True
119113 Determines if the function calculates the residual (if True) or the
@@ -125,36 +119,30 @@ def calculate_residual_or_risk_transfer_impact_matrix(
125119 The adjusted impact matrix, either residual or risk transfer.
126120
127121 """
122+ imp_mat = copy .deepcopy (imp_mat )
123+ # Calculate the total impact per event
124+ total_at_event = imp_mat .sum (axis = 1 ).A1
125+ # Risk layer at event
126+ transfer_at_event = np .minimum (
127+ np .maximum (total_at_event - risk_transf_attach , 0 ), risk_transf_cover
128+ )
129+ residual_at_event = np .maximum (total_at_event - transfer_at_event , 0 )
128130
129- if risk_transf_attach and risk_transf_cover :
130- imp_mat = copy .deepcopy (imp_mat )
131- # Calculate the total impact per event
132- total_at_event = imp_mat .sum (axis = 1 ).A1
133- # Risk layer at event
134- transfer_at_event = np .minimum (
135- np .maximum (total_at_event - risk_transf_attach , 0 ), risk_transf_cover
136- )
137- residual_at_event = np .maximum (total_at_event - transfer_at_event , 0 )
138-
139- # Calculate either the residual or transfer impact matrix
140- # Choose the denominator to rescale the impact values
141- if calc_residual :
142- numerator = residual_at_event
143- else :
144- numerator = transfer_at_event
145-
146- rescale_impact_values = np .divide (
147- numerator ,
148- total_at_event ,
149- out = np .zeros_like (numerator , dtype = float ),
150- where = total_at_event != 0 ,
151- )
152-
153- # The multiplication is broadcasted across the columns for each row
154- result_matrix = imp_mat .multiply (rescale_impact_values [:, np .newaxis ])
131+ # Calculate either the residual or transfer impact matrix
132+ # Choose the denominator to rescale the impact values
133+ if calc_residual :
134+ numerator = residual_at_event
135+ else :
136+ numerator = transfer_at_event
155137
156- return result_matrix
138+ rescale_impact_values = np .divide (
139+ numerator ,
140+ total_at_event ,
141+ out = np .zeros_like (numerator , dtype = float ),
142+ where = total_at_event != 0 ,
143+ )
157144
158- else :
145+ # The multiplication is broadcasted across the columns for each row
146+ result_matrix = imp_mat .multiply (rescale_impact_values [:, np .newaxis ])
159147
160- return imp_mat
148+ return result_matrix
0 commit comments