Skip to content

Commit df20622

Browse files
committed
Merge branch 'implement_mean_min_max' into implement_quantiles
2 parents 3b4048e + 64149df commit df20622

File tree

4 files changed

+56
-124
lines changed

4 files changed

+56
-124
lines changed

climada/engine/impact_forecast.py

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -284,16 +284,9 @@ def min(self):
284284
ImpactForecast
285285
An ImpactForecast object with the min impact matrix and at_event.
286286
"""
287-
red_imp_mat = sparse.csr_matrix(self.imp_mat.min(axis=0))
287+
red_imp_mat = self.imp_mat.min(axis=0).tocsr()
288288
red_at_event = np.array([red_imp_mat.sum()])
289-
reduced_attrs = self._reduce_attrs("min")
290289
return ImpactForecast(
291-
lead_time=reduced_attrs["lead_time"],
292-
member=reduced_attrs["member"],
293-
event_id=reduced_attrs["event_id"],
294-
event_name=reduced_attrs["event_name"],
295-
date=reduced_attrs["date"],
296-
frequency=reduced_attrs["frequency"],
297290
frequency_unit=self.frequency_unit,
298291
coord_exp=self.coord_exp,
299292
crs=self.crs,
@@ -304,6 +297,7 @@ def min(self):
304297
unit=self.unit,
305298
imp_mat=red_imp_mat,
306299
haz_type=self.haz_type,
300+
**self._reduce_attrs("min"),
307301
)
308302

309303
def max(self):
@@ -320,16 +314,9 @@ def max(self):
320314
ImpactForecast
321315
An ImpactForecast object with the max impact matrix and at_event.
322316
"""
323-
red_imp_mat = sparse.csr_matrix(self.imp_mat.max(axis=0))
317+
red_imp_mat = self.imp_mat.max(axis=0).tocsr()
324318
red_at_event = np.array([red_imp_mat.sum()])
325-
reduced_attrs = self._reduce_attrs("max")
326319
return ImpactForecast(
327-
lead_time=reduced_attrs["lead_time"],
328-
member=reduced_attrs["member"],
329-
event_id=reduced_attrs["event_id"],
330-
event_name=reduced_attrs["event_name"],
331-
date=reduced_attrs["date"],
332-
frequency=reduced_attrs["frequency"],
333320
frequency_unit=self.frequency_unit,
334321
coord_exp=self.coord_exp,
335322
crs=self.crs,
@@ -340,6 +327,7 @@ def max(self):
340327
unit=self.unit,
341328
imp_mat=red_imp_mat,
342329
haz_type=self.haz_type,
330+
**self._reduce_attrs("max"),
343331
)
344332

345333
def mean(self):
@@ -357,14 +345,7 @@ def mean(self):
357345
"""
358346
red_imp_mat = sparse.csr_matrix(self.imp_mat.mean(axis=0))
359347
red_at_event = np.array([red_imp_mat.sum()])
360-
reduced_attrs = self._reduce_attrs("mean")
361348
return ImpactForecast(
362-
lead_time=reduced_attrs["lead_time"],
363-
member=reduced_attrs["member"],
364-
event_id=reduced_attrs["event_id"],
365-
event_name=reduced_attrs["event_name"],
366-
date=reduced_attrs["date"],
367-
frequency=reduced_attrs["frequency"],
368349
frequency_unit=self.frequency_unit,
369350
coord_exp=self.coord_exp,
370351
crs=self.crs,
@@ -375,6 +356,7 @@ def mean(self):
375356
unit=self.unit,
376357
imp_mat=red_imp_mat,
377358
haz_type=self.haz_type,
359+
**self._reduce_attrs("mean"),
378360
)
379361

380362
def quantile(self, q: float):

climada/engine/test/test_impact_forecast.py

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -223,44 +223,41 @@ def test_impact_forecast_blocked_methods(impact_forecast):
223223
impact_forecast.calc_freq_curve(np.array([10, 50, 100]))
224224

225225

226-
def test_impact_forecast_mean_min_max(impact_forecast):
226+
@pytest.fixture
227+
def impact_forecast_stats(impact_kwargs, lead_time, member):
228+
max_index = 4
229+
for key, val in impact_kwargs.items():
230+
if isinstance(val, (np.ndarray, list)):
231+
impact_kwargs[key] = val[:max_index]
232+
elif isinstance(val, csr_matrix):
233+
impact_kwargs[key] = val[:max_index, :]
234+
impact_kwargs["imp_mat"] = csr_matrix([[1, 0], [0, 1], [3, 2], [2, 3]])
235+
impact_kwargs["at_event"] = np.array([1, 1, 5, 5])
236+
return ImpactForecast(
237+
lead_time=lead_time[:max_index], member=member[:max_index], **impact_kwargs
238+
)
239+
240+
241+
@pytest.mark.parametrize("attr", ["min", "mean", "max"])
242+
def test_impact_forecast_min_mean_max(impact_forecast_stats, attr):
227243
"""Check mean, min, and max methods for ImpactForecast"""
228-
imp_fcst_mean = impact_forecast.mean()
229-
imp_fcst_min = impact_forecast.min()
230-
imp_fcst_max = impact_forecast.max()
244+
imp_fc_reduced = getattr(impact_forecast_stats, attr)()
231245

232246
# assert imp_mat
233247
npt.assert_array_equal(
234-
imp_fcst_mean.imp_mat.todense(), impact_forecast.imp_mat.todense().mean(axis=0)
248+
imp_fc_reduced.imp_mat.todense(),
249+
getattr(impact_forecast_stats.imp_mat.todense(), attr)(axis=0),
235250
)
236-
npt.assert_array_equal(imp_fcst_min.imp_mat.todense(), np.array([[0, 0]]))
237-
npt.assert_array_equal(imp_fcst_max.imp_mat.todense(), np.array([[31, 31]]))
238-
# assert at_event
239-
npt.assert_array_equal(
240-
imp_fcst_mean.at_event, impact_forecast.at_event.mean()
241-
) # 134/6
242-
npt.assert_array_equal(imp_fcst_min.at_event, impact_forecast.at_event.min())
243-
npt.assert_array_equal(imp_fcst_max.at_event, impact_forecast.at_event.max())
251+
at_event_expected = {"min": [0], "mean": [3], "max": [6]}
252+
npt.assert_array_equal(imp_fc_reduced.at_event, at_event_expected[attr])
244253

245254
# check that attributes where reduced correctly
246-
assert np.isnat(imp_fcst_mean.lead_time[0])
247-
assert np.isnat(imp_fcst_min.lead_time[0])
248-
assert np.isnat(imp_fcst_max.lead_time[0])
249-
assert imp_fcst_mean.member[0] == -1
250-
assert imp_fcst_min.member[0] == -1
251-
assert imp_fcst_max.member[0] == -1
252-
assert imp_fcst_mean.event_name[0] == "mean"
253-
assert imp_fcst_min.event_name[0] == "min"
254-
assert imp_fcst_max.event_name[0] == "max"
255-
assert imp_fcst_mean.event_id[0] == 0
256-
assert imp_fcst_min.event_id[0] == 0
257-
assert imp_fcst_max.event_id[0] == 0
258-
assert imp_fcst_mean.frequency == 1
259-
assert imp_fcst_min.frequency == 1
260-
assert imp_fcst_max.frequency == 1
261-
assert imp_fcst_mean.date == 0
262-
assert imp_fcst_min.date == 0
263-
assert imp_fcst_max.date == 0
255+
npt.assert_array_equal(np.isnat(imp_fc_reduced.lead_time), [True])
256+
npt.assert_array_equal(imp_fc_reduced.member, [-1])
257+
npt.assert_array_equal(imp_fc_reduced.event_name, [attr])
258+
npt.assert_array_equal(imp_fc_reduced.event_id, [0])
259+
npt.assert_array_equal(imp_fc_reduced.frequency, [1])
260+
npt.assert_array_equal(imp_fc_reduced.date, [0])
264261

265262

266263
def test_impact_forecast_quantile(impact_forecast):

climada/hazard/forecast.py

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -149,24 +149,17 @@ def min(self):
149149
HazardForecast
150150
A HazardForecast object with the min intensity and fraction.
151151
"""
152-
red_intensity = sparse.csr_matrix(self.intensity.min(axis=0))
153-
red_fraction = sparse.csr_matrix(self.fraction.min(axis=0))
154-
reduced_attrs = self._reduce_attrs("min")
152+
red_intensity = self.intensity.min(axis=0).tocsr()
153+
red_fraction = self.fraction.min(axis=0).tocsr()
155154
return HazardForecast(
156-
lead_time=reduced_attrs["lead_time"],
157-
member=reduced_attrs["member"],
158155
haz_type=self.haz_type,
159156
pool=self.pool,
160157
units=self.units,
161158
centroids=self.centroids,
162-
event_id=reduced_attrs["event_id"],
163-
frequency=reduced_attrs["frequency"],
164159
frequency_unit=self.frequency_unit,
165-
event_name=reduced_attrs["event_name"],
166-
date=reduced_attrs["date"],
167-
orig=reduced_attrs["orig"],
168160
intensity=red_intensity,
169161
fraction=red_fraction,
162+
**self._reduce_attrs("min"),
170163
)
171164

172165
def max(self):
@@ -183,24 +176,17 @@ def max(self):
183176
HazardForecast
184177
A HazardForecast object with the min intensity and fraction.
185178
"""
186-
red_intensity = sparse.csr_matrix(self.intensity.max(axis=0))
187-
red_fraction = sparse.csr_matrix(self.fraction.max(axis=0))
188-
reduced_attrs = self._reduce_attrs("max")
179+
red_intensity = self.intensity.max(axis=0).tocsr()
180+
red_fraction = self.fraction.max(axis=0).tocsr()
189181
return HazardForecast(
190-
lead_time=reduced_attrs["lead_time"],
191-
member=reduced_attrs["member"],
192182
haz_type=self.haz_type,
193183
pool=self.pool,
194184
units=self.units,
195185
centroids=self.centroids,
196-
event_id=reduced_attrs["event_id"],
197-
frequency=reduced_attrs["frequency"],
198186
frequency_unit=self.frequency_unit,
199-
event_name=reduced_attrs["event_name"],
200-
date=reduced_attrs["date"],
201-
orig=reduced_attrs["orig"],
202187
intensity=red_intensity,
203188
fraction=red_fraction,
189+
**self._reduce_attrs("max"),
204190
)
205191

206192
def mean(self):
@@ -218,22 +204,15 @@ def mean(self):
218204
"""
219205
red_intensity = sparse.csr_matrix(self.intensity.mean(axis=0))
220206
red_fraction = sparse.csr_matrix(self.fraction.mean(axis=0))
221-
reduced_attrs = self._reduce_attrs("mean")
222207
return HazardForecast(
223-
lead_time=reduced_attrs["lead_time"],
224-
member=reduced_attrs["member"],
225208
haz_type=self.haz_type,
226209
pool=self.pool,
227210
units=self.units,
228211
centroids=self.centroids,
229-
event_id=reduced_attrs["event_id"],
230-
frequency=reduced_attrs["frequency"],
231212
frequency_unit=self.frequency_unit,
232-
event_name=reduced_attrs["event_name"],
233-
date=reduced_attrs["date"],
234-
orig=reduced_attrs["orig"],
235213
intensity=red_intensity,
236214
fraction=red_fraction,
215+
**self._reduce_attrs("mean"),
237216
)
238217

239218
def quantile(self, q: float):

climada/hazard/test/test_forecast.py

Lines changed: 16 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -166,55 +166,29 @@ def test_write_read_hazard_forecast(haz_fc, tmp_path):
166166
npt.assert_array_equal(haz_fc.__dict__[key], haz_fc_read.__dict__[key])
167167

168168

169-
def test_hazard_forecast_mean_min_max(haz_fc):
169+
@pytest.mark.parametrize("attr", ["min", "mean", "max"])
170+
def test_hazard_forecast_mean_min_max(haz_fc, attr):
170171
"""Check mean, min, and max methods for ImpactForecast"""
171-
haz_fcst_mean = haz_fc.mean()
172-
haz_fcst_min = haz_fc.min()
173-
haz_fcst_max = haz_fc.max()
172+
haz_fcst_reduced = getattr(haz_fc, attr)()
174173

175-
# assert intensity
174+
# Assert sparse matrices
176175
npt.assert_array_equal(
177-
haz_fcst_mean.intensity.todense(), haz_fc.intensity.todense().mean(axis=0)
176+
haz_fcst_reduced.intensity.todense(),
177+
getattr(haz_fc.intensity.todense(), attr)(axis=0),
178178
)
179179
npt.assert_array_equal(
180-
haz_fcst_min.intensity.todense(), haz_fc.intensity.todense().min(axis=0)
181-
)
182-
npt.assert_array_equal(
183-
haz_fcst_max.intensity.todense(), haz_fc.intensity.todense().max(axis=0)
184-
)
185-
# assert fraction
186-
npt.assert_array_equal(
187-
haz_fcst_mean.fraction.todense(), haz_fc.fraction.todense().mean(axis=0)
188-
)
189-
npt.assert_array_equal(
190-
haz_fcst_min.fraction.todense(), haz_fc.fraction.todense().min(axis=0)
191-
)
192-
npt.assert_array_equal(
193-
haz_fcst_max.fraction.todense(), haz_fc.fraction.todense().max(axis=0)
180+
haz_fcst_reduced.fraction.todense(),
181+
getattr(haz_fc.fraction.todense(), attr)(axis=0),
194182
)
195183

196-
# check that attributes where reduced correctly
197-
assert np.isnat(haz_fcst_mean.lead_time[0])
198-
assert np.isnat(haz_fcst_min.lead_time[0])
199-
assert np.isnat(haz_fcst_max.lead_time[0])
200-
assert haz_fcst_mean.member[0] == -1
201-
assert haz_fcst_min.member[0] == -1
202-
assert haz_fcst_max.member[0] == -1
203-
assert haz_fcst_mean.event_name[0] == "mean"
204-
assert haz_fcst_min.event_name[0] == "min"
205-
assert haz_fcst_max.event_name[0] == "max"
206-
assert haz_fcst_mean.event_id[0] == 0
207-
assert haz_fcst_min.event_id[0] == 0
208-
assert haz_fcst_max.event_id[0] == 0
209-
assert haz_fcst_mean.frequency == 1
210-
assert haz_fcst_min.frequency == 1
211-
assert haz_fcst_max.frequency == 1
212-
assert haz_fcst_mean.date == 0
213-
assert haz_fcst_min.date == 0
214-
assert haz_fcst_max.date == 0
215-
assert np.all(haz_fcst_mean.orig)
216-
assert np.all(haz_fcst_min.orig)
217-
assert np.all(haz_fcst_max.orig)
184+
# Check that attributes where reduced correctly
185+
npt.assert_array_equal(np.isnat(haz_fcst_reduced.lead_time), [True])
186+
npt.assert_array_equal(haz_fcst_reduced.member, [-1])
187+
npt.assert_array_equal(haz_fcst_reduced.event_name, [attr])
188+
npt.assert_array_equal(haz_fcst_reduced.event_id, [0])
189+
npt.assert_array_equal(haz_fcst_reduced.frequency, [1])
190+
npt.assert_array_equal(haz_fcst_reduced.date, [0])
191+
npt.assert_array_equal(haz_fcst_reduced.orig, [True])
218192

219193

220194
def test_hazard_forecast_quantile(haz_fc):

0 commit comments

Comments
 (0)