2727import geopandas as gpd
2828import numpy as np
2929import pandas as pd
30+ import pytest
3031from scipy import sparse
3132
3233from climada import CONFIG
4950DATA_FOLDER .mkdir (exist_ok = True )
5051
5152
53+ @pytest .fixture (autouse = True )
54+ def exposure_fixture ():
55+ n_exp = 50
56+ lats = np .linspace (- 10 , 10 , n_exp )
57+ lons = np .linspace (- 10 , 10 , n_exp )
58+ data = gpd .GeoDataFrame (
59+ {
60+ "impf_TC" : 1 ,
61+ "value" : 1 ,
62+ },
63+ index = range (n_exp ),
64+ geometry = gpd .points_from_xy (lons , lats ),
65+ crs = "EPSG:4326" ,
66+ )
67+ exposures = Exposures (data = data )
68+ return exposures
69+
70+
71+ @pytest .fixture (autouse = True )
72+ def hazard_fixture (exposure_fixture ):
73+ n_events = 10
74+ centroids = Centroids (
75+ lat = exposure_fixture .gdf .geometry .x ,
76+ lon = exposure_fixture .gdf .geometry .y ,
77+ )
78+ intensity = (
79+ np .ones ((n_events , exposure_fixture .gdf .shape [0 ])) * 50
80+ ) # uniform intensity
81+ haz = Hazard ()
82+ haz .haz_type = "TC"
83+ haz .centroids = centroids
84+ haz .intensity = intensity
85+ haz .frequency = 1 / 10 * np .ones (n_events ) # uniform frequency (10 n_events)
86+ return haz
87+
88+
89+ @pytest .fixture (autouse = True )
90+ def hazard_forecast_fixture (hazard_fixture ):
91+ n_events = hazard_fixture .size
92+ lead_time = pd .timedelta_range ("1h" , periods = n_events ).to_numpy ()
93+ member = np .arange (10 )
94+ haz_fc = HazardForecast .from_hazard (
95+ hazard = hazard_fixture ,
96+ lead_time = lead_time ,
97+ member = member ,
98+ )
99+ return haz_fc
100+
101+
102+ @pytest .fixture (autouse = True )
103+ def impact_func_set_fixture (exposure_fixture , hazard_fixture ):
104+ step_impf = ImpactFunc ()
105+ step_impf .id = exposure_fixture .data [f"impf_{ hazard_fixture .haz_type } " ].unique ()[0 ]
106+ step_impf .haz_type = hazard_fixture .haz_type
107+ step_impf .name = "fixture step function"
108+ step_impf .intensity_unit = ""
109+ step_impf .intensity = np .array ([0 , 0.495 , 0.4955 , 0.5 , 1 , 10 ])
110+ step_impf .mdd = np .array ([0 , 0 , 0 , 1 , 1 , 1 ])
111+ step_impf .paa = np .sort (np .linspace (1 , 1 , num = 6 ))
112+ return ImpactFuncSet ([step_impf ])
113+
114+
115+ @pytest .fixture (autouse = True )
116+ def impact_calc_fixture (exposure_fixture , hazard_fixture , impact_func_set_fixture ):
117+ imp_mat = np .ones (
118+ (
119+ len (hazard_fixture .event_id ),
120+ exposure_fixture .gdf .shape [0 ],
121+ exposure_fixture .gdf .shape [0 ],
122+ )
123+ )
124+ aai_agg = np .sum (exposure_fixture .gdf ["value" ]) * hazard_fixture .frequency [0 ]
125+ eai_exp = np .ones (exposure_fixture .gdf .shape [0 ]) * hazard_fixture .frequency [0 ]
126+ at_event = np .ones (hazard_fixture .size ) * np .sum (exposure_fixture .gdf ["value" ])
127+ return {
128+ "imp_mat" : imp_mat ,
129+ "aai_agg" : aai_agg ,
130+ "eai_exp" : eai_exp ,
131+ "at_event" : at_event ,
132+ }
133+
134+
52135def check_impact (self , imp , haz , exp , aai_agg , eai_exp , at_event , imp_mat_array = None ):
53136 """Test properties of impacts"""
54137 self .assertEqual (len (haz .event_id ), len (imp .at_event ))
@@ -609,108 +692,34 @@ def test_single_exp_zero_mdr(self):
609692 check_impact (self , imp , haz , exp , aai_agg , eai_exp , at_event , at_event )
610693
611694
612- class TestImpactCalcForecast ( unittest . TestCase ) :
695+ class TestImpactCalcForecast :
613696 """Test impact calc for forecast hazard"""
614697
615- def test_impactForecast (self ):
698+ def test_impactForecast_type (
699+ exposure_fixture ,
700+ hazard_forecast_fixture ,
701+ impact_func_set_fixture ,
702+ impact_calc_fixture ,
703+ ):
616704 """Test that ImpactForecast is returned correctly"""
617- lead_time = pd .timedelta_range ("1h" , periods = 6 ).to_numpy ()
618- member = np .arange (6 )
619- _haz = Hazard .from_hdf5 (get_test_file ("test_hazard_US_flood_random_locations" ))
620- haz_fc = HazardForecast .from_hazard (_haz , lead_time = lead_time , member = member )
621705
622- exp = Exposures .from_hdf5 (
623- get_test_file ("test_exposure_US_flood_random_locations" )
624- )
625- impf_set = ImpactFuncSet .from_excel (
626- Path (__file__ ).parent / "data" / "flood_imp_func_set.xls"
627- )
628- icalc = ImpactCalc (exp , impf_set , haz_fc )
629- impact = icalc .impact (assign_centroids = False )
630- aai_agg = 161436.05112960344
631- eai_exp = np .array (
632- [
633- 1.61159701e05 ,
634- 1.33742847e02 ,
635- 0.00000000e00 ,
636- 4.21352988e-01 ,
637- 1.42185609e02 ,
638- 0.00000000e00 ,
639- 0.00000000e00 ,
640- 0.00000000e00 ,
641- ]
642- )
643- at_event = np .array (
644- [
645- 0.00000000e00 ,
646- 0.00000000e00 ,
647- 9.85233619e04 ,
648- 3.41245461e04 ,
649- 7.73566566e07 ,
650- 0.00000000e00 ,
651- 0.00000000e00 ,
652- ]
653- )
654- # fmt: off
655- imp_mat_array = np .array (
656- [
657- [
658- 0.00000000e00 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
659- 0.00000000e00 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
660- ],
661- [
662- 0.00000000e00 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
663- 0.00000000e00 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
664- ],
665- [
666- 0.00000000e00 , 6.41965663e04 , 0.00000000e00 , 2.02249434e02 ,
667- 3.41245461e04 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
668- ],
669- [
670- 0.00000000e00 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
671- 3.41245461e04 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
672- ],
673- [
674- 7.73566566e07 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
675- 0.00000000e00 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
676- ],
677- [
678- 0.00000000e00 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
679- 0.00000000e00 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
680- ],
681- [
682- 0.00000000e00 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
683- 0.00000000e00 , 0.00000000e00 , 0.00000000e00 , 0.00000000e00 ,
684- ],
685- ]
686- )
687- # fmt: on
688- check_impact (
689- self , impact , haz_fc , exp , aai_agg , eai_exp , at_event , imp_mat_array
706+ # check that impact is indeed ImpactForecast
707+ assert isinstance (impact , ImpactForecast )
708+ np .testing .assert_array_equal (
709+ impact .lead_time , hazard_forecast_fixture .lead_time
690710 )
711+ assert impact .lead_time .dtype == hazard_forecast_fixture .lead_time .dtype
712+ np .testing .assert_array_equal (impact .member , hazard_forecast_fixture .member )
691713
692- # additional test to check that impact is indeed ImpactForecast
693- self .assertIsInstance (impact , ImpactForecast )
694- np .testing .assert_array_equal (impact .lead_time , lead_time )
695- self .assertIs (impact .lead_time .dtype , lead_time .dtype )
696- np .testing .assert_array_equal (impact .member , member )
697-
698- def test_impact_forecast_empty_impmat_error (self ):
714+ def test_impact_forecast_empty_impmat_error (
715+ hazard_forecast_fixture , exposure_fixture , impact_func_set_fixture
716+ ):
699717 """Test that error is raised when trying to compute impact forecast
700718 without saving impact matrix
701719 """
702- lead_time = pd .timedelta_range ("1h" , periods = 6 ).to_numpy ()
703- member = np .arange (6 )
704- _haz = Hazard .from_hdf5 (get_test_file ("test_hazard_US_flood_random_locations" ))
705- haz_fc = HazardForecast .from_hazard (_haz , lead_time = lead_time , member = member )
706-
707- exp = Exposures .from_hdf5 (
708- get_test_file ("test_exposure_US_flood_random_locations" )
709- )
710- impf_set = ImpactFuncSet .from_excel (
711- Path (__file__ ).parent / "data" / "flood_imp_func_set.xls"
720+ icalc = ImpactCalc (
721+ exposure_fixture , impact_func_set_fixture , hazard_forecast_fixture
712722 )
713- icalc = ImpactCalc (exp , impf_set , haz_fc )
714723 with self .assertRaises (ValueError ) as cm :
715724 icalc .impact (assign_centroids = False , save_mat = False )
716725 no_impmat_exception = cm .exception
@@ -720,25 +729,19 @@ def test_impact_forecast_empty_impmat_error(self):
720729 "Please set save_mat=True." ,
721730 )
722731
723- def test_impact_forecast_blocked_nonsense_attrs (self ):
732+ def test_impact_forecast_blocked_nonsense_attrs (
733+ hazard_forecast_fixture , exposure_fixture , impact_func_set_fixture
734+ ):
724735 """Test that nonsense attributes are blocked when computing impact forecast"""
725- lead_time = pd .timedelta_range ("1h" , periods = 6 ).to_numpy ()
726- member = np .arange (6 )
727- haz = Hazard .from_hdf5 (get_test_file ("test_hazard_US_flood_random_locations" ))
728- haz_fc = HazardForecast .from_hazard (haz , lead_time = lead_time , member = member )
736+ lead_time = hazard_fixture .lead_time
737+ member = hazard_fixture .member
729738
730- exp = Exposures .from_hdf5 (
731- get_test_file ("test_exposure_US_flood_random_locations" )
732- )
733- impf_set = ImpactFuncSet .from_excel (
734- Path (__file__ ).parent / "data" / "flood_imp_func_set.xls"
735- )
736- impact = ImpactCalc (exp , impf_set , haz_fc ).impact (
737- assign_centroids = False , save_mat = True
738- )
739+ impact = ImpactCalc (
740+ exposure_fixture , impact_func_set_fixture , hazard_forecast_fixture
741+ ).impact (assign_centroids = True , save_mat = True )
739742 assert np .isnan (impact .aai_agg )
740743 assert np .all (np .isnan (impact .eai_exp ))
741- assert impact .eai_exp .shape == (len (exp .gdf ),)
744+ assert impact .eai_exp .shape == (len (exposure_fixture .gdf ),)
742745
743746
744747class TestImpactMatrixCalc (unittest .TestCase ):
0 commit comments