From f49938943865103e504d7e52dc4b732af359db14 Mon Sep 17 00:00:00 2001 From: ankurmahiwal118028 Date: Wed, 13 May 2026 23:25:53 +0530 Subject: [PATCH] Raise clear error for empty Hazard in ImpactCalc.impact Computing impact with a Hazard containing zero events previously crashed deep inside ``np.array_split`` with the obscure message "number sections must be larger than 0". This adds an early guard in ``ImpactCalc.impact`` that raises a ``ValueError`` with a clear explanation when ``self.hazard.size == 0``. Closes #814 --- CHANGELOG.md | 1 + climada/engine/impact_calc.py | 9 +++++++++ climada/engine/test/test_impact_calc.py | 16 ++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a77a164208..4f2723d9f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Code freeze date: YYYY-MM-DD - Fixed asset count in impact logging message [#1195](https://github.com/CLIMADA-project/climada_python/pull/1195). - `Hazard.from_raster_xarray` now returns a sparse matrix instead of a sparse array [#1261](https://github.com/CLIMADA-project/climada_python/pull/1261). +- `ImpactCalc.impact` now raises a clear `ValueError` when the supplied `Hazard` contains no events, instead of failing later inside `np.array_split` with an obscure message [#814](https://github.com/CLIMADA-project/climada_python/issues/814). ### Deprecated - `Impact.calc_freq_curve()` should not be given the parameter `return_per`. Use the parameter `return_periods` in `Impact.calc_freq_curve().interpolate()` instead. diff --git a/climada/engine/impact_calc.py b/climada/engine/impact_calc.py index 0f35bc904b..bd944e3792 100644 --- a/climada/engine/impact_calc.py +++ b/climada/engine/impact_calc.py @@ -136,6 +136,15 @@ def impact( climada.entity.exposures.assign_centroids : assign centroids to exposures explicitly """ # TODO: consider refactoring, making use of Exposures.hazard_impf + # check that the hazard contains at least one event; an empty hazard + # otherwise produces an obscure error from ``np.array_split`` deeper in + # the calculation (see GH #814). + if self.hazard.size == 0: + raise ValueError( + "Impact calculation not possible. The hazard object contains " + "no events. Please provide a Hazard with at least one event." + ) + # check for compatibility of exposures and hazard type if all( name not in self.exposures.gdf.columns diff --git a/climada/engine/test/test_impact_calc.py b/climada/engine/test/test_impact_calc.py index 9e7b2e2cb2..54565da78b 100644 --- a/climada/engine/test/test_impact_calc.py +++ b/climada/engine/test/test_impact_calc.py @@ -147,6 +147,22 @@ def test_error_handling_mismatch_haz_type(self): "functions found for hazard type TC in impf_set.", ) + def test_error_handling_empty_hazard(self): + """An empty Hazard must raise a clear ValueError (see GH #814).""" + haz_empty = Hazard("TC") + exp = Exposures() + exp.gdf["impf_TC"] = 1 + impf = ImpactFunc( + haz_type="TC", + id=1, + intensity=np.array([0, 20]), + paa=np.array([0, 1]), + mdd=np.array([0, 0.5]), + ) + impfset = ImpactFuncSet([impf]) + with self.assertRaisesRegex(ValueError, "no events"): + ImpactCalc(exp, impfset, haz_empty).impact() + def test_error_handling_mismatch_impf_ids(self): """Test error handling in case impf ids in exposures does not appear in impf_set"""