Skip to content

Commit 0bc5846

Browse files
committed
Add mean max min methods to impact forecast and tests
1 parent 727357e commit 0bc5846

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

climada/engine/impact_forecast.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import logging
2323

2424
import numpy as np
25+
import scipy.sparse as sparse
2526

2627
from ..util import log_level
2728
from ..util.forecast import Forecast
@@ -152,3 +153,137 @@ def calc_freq_curve(self, return_per=None):
152153

153154
LOGGER.error("calc_freq_curve is not defined for ImpactForecast")
154155
raise NotImplementedError("calc_freq_curve is not defined for ImpactForecast")
156+
157+
def _reduce_attrs(self, reduce_method: str):
158+
"""
159+
Reduce the attributes of an ImpactForecast to a single value.
160+
161+
Attributes are modified as follows:
162+
- event_id: set to [0]
163+
- event_name: set to [reduce_method]
164+
- date: set to the minimum value
165+
- frequency: set to 0
166+
167+
Parameters
168+
----------
169+
reduce_method : str
170+
The reduction method used to reduce the attributes.
171+
"""
172+
red_event_id = np.asarray([0])
173+
red_event_name = np.asarray([reduce_method])
174+
red_date = np.array([self.date.min()])
175+
red_frequency = np.array([0])
176+
return red_event_id, red_event_name, red_date, red_frequency
177+
178+
def min(self):
179+
"""
180+
Reduce the impact matrix and at_event of an ImpactForecast to the minimum
181+
value.
182+
183+
Parameters
184+
----------
185+
None
186+
187+
Returns
188+
-------
189+
None
190+
"""
191+
red_imp_mat = sparse.csr_matrix(self.imp_mat.min(axis=0))
192+
red_at_event = np.array([red_imp_mat.sum()])
193+
red_event_id, red_event_name, red_date, red_frequency = self._reduce_attrs(
194+
"min"
195+
)
196+
return ImpactForecast(
197+
lead_time=self.lead_time,
198+
member=self.member,
199+
event_id=red_event_id,
200+
event_name=red_event_name,
201+
date=red_date,
202+
frequency=red_frequency,
203+
frequency_unit=self.frequency_unit,
204+
coord_exp=self.coord_exp,
205+
crs=self.crs,
206+
eai_exp=self.eai_exp,
207+
at_event=red_at_event,
208+
tot_value=self.tot_value,
209+
aai_agg=self.aai_agg,
210+
unit=self.unit,
211+
imp_mat=red_imp_mat,
212+
haz_type=self.haz_type,
213+
)
214+
215+
def max(self):
216+
"""
217+
Reduce the impact matrix and at_event of an ImpactForecast to the maximum
218+
value.
219+
220+
Parameters
221+
----------
222+
None
223+
224+
Returns
225+
-------
226+
None
227+
"""
228+
red_imp_mat = sparse.csr_matrix(self.imp_mat.max(axis=0))
229+
red_at_event = np.array([red_imp_mat.sum()])
230+
red_event_id, red_event_name, red_date, red_frequency = self._reduce_attrs(
231+
"max"
232+
)
233+
return ImpactForecast(
234+
lead_time=self.lead_time,
235+
member=self.member,
236+
event_id=red_event_id,
237+
event_name=red_event_name,
238+
date=red_date,
239+
frequency=red_frequency,
240+
frequency_unit=self.frequency_unit,
241+
coord_exp=self.coord_exp,
242+
crs=self.crs,
243+
eai_exp=self.eai_exp,
244+
at_event=red_at_event,
245+
tot_value=self.tot_value,
246+
aai_agg=self.aai_agg,
247+
unit=self.unit,
248+
imp_mat=red_imp_mat,
249+
haz_type=self.haz_type,
250+
)
251+
252+
def mean(self):
253+
"""
254+
Reduce the impact matrix and at_event of an ImpactForecast to the mean value.
255+
256+
The mean value is computed by taking the mean of the impact matrix along the
257+
exposure points axis (axis=1) and then taking the mean of the resulting array.
258+
259+
Parameters
260+
----------
261+
None
262+
263+
Returns
264+
-------
265+
None
266+
"""
267+
red_imp_mat = sparse.csr_matrix(self.imp_mat.mean(axis=0))
268+
red_at_event = np.array([red_imp_mat.sum()])
269+
red_event_id, red_event_name, red_date, red_frequency = self._reduce_attrs(
270+
"mean"
271+
)
272+
return ImpactForecast(
273+
lead_time=self.lead_time,
274+
member=self.member,
275+
event_id=red_event_id,
276+
event_name=red_event_name,
277+
date=red_date,
278+
frequency=red_frequency,
279+
frequency_unit=self.frequency_unit,
280+
coord_exp=self.coord_exp,
281+
crs=self.crs,
282+
eai_exp=self.eai_exp,
283+
at_event=red_at_event,
284+
tot_value=self.tot_value,
285+
aai_agg=self.aai_agg,
286+
unit=self.unit,
287+
imp_mat=red_imp_mat,
288+
haz_type=self.haz_type,
289+
)

climada/engine/test/test_impact_forecast.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,39 @@ def test_impact_forecast_blocked_methods(impact_forecast):
115115

116116
with pytest.raises(NotImplementedError):
117117
impact_forecast.calc_freq_curve(np.array([10, 50, 100]))
118+
119+
120+
def test_impact_forecast_mean_min_max(impact_forecast):
121+
"""Check mean, min, and max methods for ImpactForecast"""
122+
imp_fcst_mean = impact_forecast.mean()
123+
imp_fcst_min = impact_forecast.min()
124+
imp_fcst_max = impact_forecast.max()
125+
# sparse.csr_matrix(
126+
# np.array([[0, 0], [1, 1], [2, 2], [3, 3], [30, 30], [31, 31]])
127+
128+
# assert imp_mat
129+
npt.assert_array_equal(
130+
imp_fcst_mean.imp_mat.todense(), impact_forecast.imp_mat.todense().mean(axis=0)
131+
)
132+
npt.assert_array_equal(imp_fcst_min.imp_mat.todense(), np.array([[0, 0]]))
133+
npt.assert_array_equal(imp_fcst_max.imp_mat.todense(), np.array([[31, 31]]))
134+
# assert at_event
135+
npt.assert_array_equal(
136+
imp_fcst_mean.at_event, impact_forecast.at_event.mean()
137+
) # 134/6
138+
npt.assert_array_equal(imp_fcst_min.at_event, impact_forecast.at_event.min())
139+
npt.assert_array_equal(imp_fcst_max.at_event, impact_forecast.at_event.max())
140+
141+
# check that attributes where reduced correctly
142+
assert imp_fcst_mean.event_name[0] == "mean"
143+
assert imp_fcst_min.event_name[0] == "min"
144+
assert imp_fcst_max.event_name[0] == "max"
145+
assert imp_fcst_mean.event_id[0] == 0
146+
assert imp_fcst_min.event_id[0] == 0
147+
assert imp_fcst_max.event_id[0] == 0
148+
assert imp_fcst_mean.frequency == 0
149+
assert imp_fcst_min.frequency == 0
150+
assert imp_fcst_max.frequency == 0
151+
assert imp_fcst_mean.date == impact_forecast.date.min()
152+
assert imp_fcst_min.date == impact_forecast.date.min()
153+
assert imp_fcst_max.date == impact_forecast.date.min()

0 commit comments

Comments
 (0)