Skip to content

Commit 2e3c26e

Browse files
committed
Review
* Update tests * Rename event name for median
1 parent 35cb0fa commit 2e3c26e

File tree

4 files changed

+140
-79
lines changed

4 files changed

+140
-79
lines changed

climada/engine/impact_forecast.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -355,22 +355,14 @@ def select(
355355
reset_frequency=reset_frequency,
356356
)
357357

358-
def quantile(self, q: float):
358+
def _quantile(self, q: float, event_name: str | None = None):
359359
"""
360360
Reduce the impact matrix and at_event of an ImpactForecast to the quantile value.
361-
362-
Parameters
363-
----------
364-
q : float
365-
The quantile to compute, which must be between 0 and 1.
366-
367-
Returns
368-
-------
369-
ImpactForecast
370-
An ImpactForecast object with the quantile impact matrix and at_event.
371361
"""
372362
red_imp_mat = sparse.csr_matrix(np.quantile(self.imp_mat.toarray(), q, axis=0))
373363
red_at_event = np.array([red_imp_mat.sum()])
364+
if event_name is None:
365+
event_name = f"quantile_{q}"
374366
return ImpactForecast(
375367
frequency_unit=self.frequency_unit,
376368
coord_exp=self.coord_exp,
@@ -382,9 +374,25 @@ def quantile(self, q: float):
382374
unit=self.unit,
383375
imp_mat=red_imp_mat,
384376
haz_type=self.haz_type,
385-
**self._reduce_attrs(f"quantile_{q}"),
377+
**self._reduce_attrs(event_name),
386378
)
387379

380+
def quantile(self, q: float):
381+
"""
382+
Reduce the impact matrix and at_event of an ImpactForecast to the quantile value.
383+
384+
Parameters
385+
----------
386+
q : float
387+
The quantile to compute, which must be between 0 and 1.
388+
389+
Returns
390+
-------
391+
ImpactForecast
392+
An ImpactForecast object with the quantile impact matrix and at_event.
393+
"""
394+
return self._quantile(q=q)
395+
388396
def median(self):
389397
"""
390398
Reduce the impact matrix and at_event of an ImpactForecast to the median value.
@@ -398,4 +406,4 @@ def median(self):
398406
ImpactForecast
399407
An ImpactForecast object with the median impact matrix and at_event.
400408
"""
401-
return self.quantile(0.5)
409+
return self._quantile(q=0.5, event_name="median")

climada/engine/test/test_impact_forecast.py

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -270,30 +270,47 @@ def test_impact_forecast_min_mean_max(impact_forecast_stats, attr):
270270
npt.assert_array_equal(imp_fc_reduced.date, [0])
271271

272272

273-
def test_impact_forecast_quantile(impact_forecast):
273+
@pytest.mark.parametrize("quantile", [0.3, 0.6, 0.8])
274+
def test_impact_forecast_quantile(impact_forecast, quantile):
274275
"""Check quantile method for ImpactForecast"""
275-
for q in [0.0, 0.5, 0.8]:
276-
imp_fcst_quantile = impact_forecast.quantile(q)
276+
imp_fcst_quantile = impact_forecast.quantile(q=quantile)
277277

278-
# assert imp_mat
279-
npt.assert_array_equal(
280-
imp_fcst_quantile.imp_mat.toarray().squeeze(),
281-
np.quantile(impact_forecast.imp_mat.toarray(), q, axis=0),
282-
)
283-
# assert at_event
284-
npt.assert_array_equal(
285-
imp_fcst_quantile.at_event,
286-
np.quantile(impact_forecast.at_event, q, axis=0).sum(),
287-
)
278+
# assert imp_mat
279+
npt.assert_array_equal(
280+
imp_fcst_quantile.imp_mat.toarray().squeeze(),
281+
np.quantile(impact_forecast.imp_mat.toarray(), quantile, axis=0),
282+
)
283+
# assert at_event
284+
npt.assert_array_equal(
285+
imp_fcst_quantile.at_event,
286+
np.quantile(impact_forecast.at_event, quantile, axis=0).sum(),
287+
)
288288

289-
# check that attributes where reduced correctly
290-
npt.assert_array_equal(imp_fcst_quantile.member, np.array([-1]))
291-
npt.assert_array_equal(
292-
imp_fcst_quantile.lead_time, np.array([np.timedelta64("NaT")])
293-
)
294-
npt.assert_array_equal(imp_fcst_quantile.event_id, np.array([0]))
295-
npt.assert_array_equal(
296-
imp_fcst_quantile.event_name, np.array([f"quantile_{q}"])
297-
)
298-
npt.assert_array_equal(imp_fcst_quantile.frequency, np.array([1]))
299-
npt.assert_array_equal(imp_fcst_quantile.date, np.array([0]))
289+
# check that attributes where reduced correctly
290+
npt.assert_array_equal(imp_fcst_quantile.member, np.array([-1]))
291+
npt.assert_array_equal(
292+
imp_fcst_quantile.lead_time, np.array([np.timedelta64("NaT")])
293+
)
294+
npt.assert_array_equal(imp_fcst_quantile.event_id, np.array([0]))
295+
npt.assert_array_equal(
296+
imp_fcst_quantile.event_name, np.array([f"quantile_{quantile}"])
297+
)
298+
npt.assert_array_equal(imp_fcst_quantile.frequency, np.array([1]))
299+
npt.assert_array_equal(imp_fcst_quantile.date, np.array([0]))
300+
301+
302+
def test_median(impact_forecast):
303+
imp_fcst_median = impact_forecast.median()
304+
imp_fcst_quantile = impact_forecast.quantile(q=0.5)
305+
npt.assert_array_equal(
306+
imp_fcst_median.imp_mat.toarray(), imp_fcst_quantile.imp_mat.toarray()
307+
)
308+
npt.assert_array_equal(imp_fcst_median.imp_mat.toarray(), [[2.5, 2.5]])
309+
310+
# check that attributes where reduced correctly
311+
npt.assert_array_equal(imp_fcst_median.member, np.array([-1]))
312+
npt.assert_array_equal(imp_fcst_median.lead_time, np.array([np.timedelta64("NaT")]))
313+
npt.assert_array_equal(imp_fcst_median.event_id, np.array([0]))
314+
npt.assert_array_equal(imp_fcst_median.event_name, np.array(["median"]))
315+
npt.assert_array_equal(imp_fcst_median.frequency, np.array([1]))
316+
npt.assert_array_equal(imp_fcst_median.date, np.array([0]))

climada/hazard/forecast.py

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -282,30 +282,18 @@ def select(
282282
reset_frequency=reset_frequency,
283283
)
284284

285-
def quantile(self, q: float):
285+
def _quantile(self, q: float, event_name: str | None = None):
286286
"""
287287
Reduce the impact matrix and at_event of a HazardForecast to the quantile value.
288-
289-
The quantile value is computed by taking the quantile of the impact matrix
290-
along the event dimension axis (axis=0) and then taking the quantile of the
291-
resulting array.
292-
293-
Parameters
294-
----------
295-
q : float
296-
The quantile to compute, between 0 and 1.
297-
298-
Returns
299-
-------
300-
HazardForecast
301-
A HazardForecast object with the quantile intensity and fraction.
302288
"""
303289
red_intensity = sparse.csr_matrix(
304290
np.quantile(self.intensity.toarray(), q, axis=0)
305291
)
306292
red_fraction = sparse.csr_matrix(
307293
np.quantile(self.fraction.toarray(), q, axis=0)
308294
)
295+
if event_name is None:
296+
event_name = f"quantile_{q}"
309297
return HazardForecast(
310298
haz_type=self.haz_type,
311299
pool=self.pool,
@@ -314,9 +302,29 @@ def quantile(self, q: float):
314302
frequency_unit=self.frequency_unit,
315303
intensity=red_intensity,
316304
fraction=red_fraction,
317-
**self._reduce_attrs(f"quantile_{q}"),
305+
**self._reduce_attrs(event_name),
318306
)
319307

308+
def quantile(self, q: float):
309+
"""
310+
Reduce the impact matrix and at_event of a HazardForecast to the quantile value.
311+
312+
The quantile value is computed by taking the quantile of the impact matrix
313+
along the event dimension axis (axis=0) and then taking the quantile of the
314+
resulting array.
315+
316+
Parameters
317+
----------
318+
q : float
319+
The quantile to compute, between 0 and 1.
320+
321+
Returns
322+
-------
323+
HazardForecast
324+
A HazardForecast object with the quantile intensity and fraction.
325+
"""
326+
return self._quantile(q=q)
327+
320328
def median(self):
321329
"""
322330
Reduce the impact matrix and at_event of a HazardForecast to the median value.
@@ -329,4 +337,4 @@ def median(self):
329337
HazardForecast
330338
A HazardForecast object with the median intensity and fraction.
331339
"""
332-
return self.quantile(0.5)
340+
return self._quantile(q=0.5, event_name="median")

climada/hazard/test/test_forecast.py

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -260,31 +260,59 @@ def test_hazard_forecast_mean_min_max(haz_fc, attr):
260260
npt.assert_array_equal(haz_fcst_reduced.orig, [True])
261261

262262

263-
def test_hazard_forecast_quantile(haz_fc):
263+
@pytest.mark.parametrize("quantile", [0.3, 0.6, 0.8])
264+
def test_hazard_forecast_quantile(haz_fc, quantile):
264265
"""Check quantile method for HazardForecast"""
265-
for q in [0.0, 0.5, 0.8]:
266-
haz_fcst_quantile = haz_fc.quantile(q)
266+
haz_fcst_quantile = haz_fc.quantile(q=quantile)
267267

268-
# assert intensity
269-
npt.assert_array_equal(
270-
haz_fcst_quantile.intensity.toarray().squeeze(),
271-
np.quantile(haz_fc.intensity.toarray(), q, axis=0),
272-
)
273-
# assert fraction
274-
npt.assert_array_equal(
275-
haz_fcst_quantile.fraction.toarray().squeeze(),
276-
np.quantile(haz_fc.fraction.toarray(), q, axis=0),
277-
)
268+
# assert intensity
269+
npt.assert_array_equal(
270+
haz_fcst_quantile.intensity.toarray().squeeze(),
271+
np.quantile(haz_fc.intensity.toarray(), quantile, axis=0),
272+
)
273+
# assert fraction
274+
npt.assert_array_equal(
275+
haz_fcst_quantile.fraction.toarray().squeeze(),
276+
np.quantile(haz_fc.fraction.toarray(), quantile, axis=0),
277+
)
278278

279-
# check that attributes where reduced correctly
280-
npt.assert_array_equal(
281-
haz_fcst_quantile.lead_time, np.array([np.timedelta64("NaT")])
282-
)
283-
npt.assert_array_equal(haz_fcst_quantile.member, np.array([-1]))
284-
npt.assert_array_equal(
285-
haz_fcst_quantile.event_name, np.array([f"quantile_{q}"])
286-
)
287-
npt.assert_array_equal(haz_fcst_quantile.event_id, np.array([0]))
288-
npt.assert_array_equal(haz_fcst_quantile.frequency, np.array([1]))
289-
npt.assert_array_equal(haz_fcst_quantile.date, np.array([0]))
290-
npt.assert_array_equal(haz_fcst_quantile.orig, np.array([True]))
279+
# check that attributes where reduced correctly
280+
npt.assert_array_equal(
281+
haz_fcst_quantile.lead_time, np.array([np.timedelta64("NaT")])
282+
)
283+
npt.assert_array_equal(haz_fcst_quantile.member, np.array([-1]))
284+
npt.assert_array_equal(
285+
haz_fcst_quantile.event_name, np.array([f"quantile_{quantile}"])
286+
)
287+
npt.assert_array_equal(haz_fcst_quantile.event_id, np.array([0]))
288+
npt.assert_array_equal(haz_fcst_quantile.frequency, np.array([1]))
289+
npt.assert_array_equal(haz_fcst_quantile.date, np.array([0]))
290+
npt.assert_array_equal(haz_fcst_quantile.orig, np.array([True]))
291+
292+
293+
def test_median(haz_fc):
294+
haz_fcst_median = haz_fc.median()
295+
haz_fcst_quantile = haz_fc.quantile(q=0.5)
296+
npt.assert_array_equal(
297+
haz_fcst_median.intensity.todense(), haz_fcst_quantile.intensity.todense()
298+
)
299+
npt.assert_array_equal(
300+
haz_fcst_median.intensity.todense(),
301+
np.median(haz_fc.intensity.todense(), axis=0),
302+
)
303+
npt.assert_array_equal(
304+
haz_fcst_median.fraction.todense(), haz_fcst_quantile.fraction.todense()
305+
)
306+
npt.assert_array_equal(
307+
haz_fcst_median.fraction.todense(),
308+
np.median(haz_fc.fraction.todense(), axis=0),
309+
)
310+
311+
# check that attributes where reduced correctly
312+
npt.assert_array_equal(haz_fcst_median.member, np.array([-1]))
313+
npt.assert_array_equal(haz_fcst_median.lead_time, np.array([np.timedelta64("NaT")]))
314+
npt.assert_array_equal(haz_fcst_median.event_id, np.array([0]))
315+
npt.assert_array_equal(haz_fcst_median.event_name, np.array(["median"]))
316+
npt.assert_array_equal(haz_fcst_median.frequency, np.array([1]))
317+
npt.assert_array_equal(haz_fcst_median.date, np.array([0]))
318+
npt.assert_array_equal(haz_fcst_median.orig, np.array([True]))

0 commit comments

Comments
 (0)