|
21 | 21 |
|
22 | 22 | import unittest |
23 | 23 |
|
| 24 | +import unittest |
| 25 | +from math import log |
| 26 | +import pandas as pd |
| 27 | +import numpy as np |
24 | 28 | import climada.hazard.tc_clim_change as tc_cc |
25 | 29 |
|
26 | 30 | class TestKnutson(unittest.TestCase): |
27 | | - """Test loading funcions from the TropCyclone class""" |
28 | 31 |
|
29 | | - def test_get_pass(self): |
| 32 | + def test_get_knutson_scaling_calculations(self): |
| 33 | + |
| 34 | + basin = 'NA' |
| 35 | + variable = 'cat05' |
| 36 | + percentile = '5/10' |
| 37 | + base_start, base_end = 1950, 2018 |
| 38 | + yearly_steps = 5 |
| 39 | + |
| 40 | + predicted_changes = tc_cc.get_knutson_scaling_factor( |
| 41 | + percentile=percentile, |
| 42 | + variable=variable, |
| 43 | + basin=basin, |
| 44 | + baseline=(base_start, base_end), |
| 45 | + yearly_steps=yearly_steps |
| 46 | + ) |
| 47 | + |
| 48 | + ## Test computations of future changes |
| 49 | + # Load data |
| 50 | + gmst_info = tc_cc.get_gmst_info() |
| 51 | + |
| 52 | + var_id, basin_id, perc_id = (tc_cc.MAP_VARS_NAMES[variable], |
| 53 | + tc_cc.MAP_BASINS_NAMES[basin], |
| 54 | + tc_cc.MAP_PERC_NAMES[percentile]) |
| 55 | + |
| 56 | + knutson_data = tc_cc.get_knutson_data() |
| 57 | + knutson_value = knutson_data[var_id, basin_id, perc_id] |
| 58 | + |
| 59 | + start_ind = base_start - gmst_info['gmst_start_year'] |
| 60 | + end_ind = base_end - gmst_info['gmst_start_year'] |
| 61 | + |
| 62 | + # Apply model |
| 63 | + beta = 0.5 * log(0.01 * knutson_value + 1) |
| 64 | + tc_properties = np.exp(beta * gmst_info['gmst_data']) |
| 65 | + |
| 66 | + # Assess baseline value |
| 67 | + baseline = np.mean(tc_properties[:, start_ind:end_ind + 1], 1) |
| 68 | + |
| 69 | + # Assess future value and test predicted change from baseline is |
| 70 | + # the same as given by function |
| 71 | + smoothing = 5 |
| 72 | + |
| 73 | + for target_year in [2030, 2050, 2070, 2090]: |
| 74 | + target_year_ind = target_year - gmst_info['gmst_start_year'] |
| 75 | + ind1 = target_year_ind - smoothing |
| 76 | + ind2 = target_year_ind + smoothing + 1 |
| 77 | + |
| 78 | + prediction = np.mean(tc_properties[:, ind1:ind2], 1) |
| 79 | + predicted_change = ((prediction - baseline) / baseline) * 100 |
| 80 | + |
| 81 | + np.testing.assert_array_almost_equal(predicted_changes.loc[target_year, '2.6'], predicted_change[0]) |
| 82 | + np.testing.assert_array_almost_equal(predicted_changes.loc[target_year, '4.5'], predicted_change[1]) |
| 83 | + np.testing.assert_array_almost_equal(predicted_changes.loc[target_year, '6.0'], predicted_change[2]) |
| 84 | + np.testing.assert_array_almost_equal(predicted_changes.loc[target_year, '8.5'], predicted_change[3]) |
| 85 | + |
| 86 | + def test_get_knutson_scaling_structure(self): |
30 | 87 | """Test get_knutson_criterion function.""" |
31 | | - criterion = tc_cc.get_knutson_criterion() |
32 | | - self.assertTrue(len(criterion), 20) |
33 | | - for crit_val in criterion: |
34 | | - self.assertTrue('year' in crit_val) |
35 | | - self.assertTrue('change' in crit_val) |
36 | | - self.assertTrue('variable' in crit_val) |
37 | | - self.assertEqual(criterion[0]['variable'], "frequency") |
38 | | - self.assertEqual(criterion[0]['change'], 1) |
39 | | - self.assertEqual(criterion[4]['variable'], "intensity") |
40 | | - self.assertEqual(criterion[4]['change'], 1.045) |
41 | | - self.assertEqual(criterion[-10]['basin'], "SP") |
42 | | - self.assertEqual(criterion[-10]['variable'], "frequency") |
43 | | - self.assertEqual(criterion[-10]['change'], 1 - 0.583) |
44 | | - |
45 | | - def test_scale_pass(self): |
46 | | - """Test calc_scale_knutson function.""" |
47 | | - self.assertAlmostEqual(tc_cc.calc_scale_knutson(ref_year=2050, rcp_scenario=45), |
48 | | - 0.759630751756698) |
49 | | - self.assertAlmostEqual(tc_cc.calc_scale_knutson(ref_year=2070, rcp_scenario=45), |
50 | | - 0.958978483788876) |
51 | | - self.assertAlmostEqual(tc_cc.calc_scale_knutson(ref_year=2060, rcp_scenario=60), |
52 | | - 0.825572149523299) |
53 | | - self.assertAlmostEqual(tc_cc.calc_scale_knutson(ref_year=2080, rcp_scenario=60), |
54 | | - 1.309882943406079) |
55 | | - self.assertAlmostEqual(tc_cc.calc_scale_knutson(ref_year=2090, rcp_scenario=85), |
56 | | - 2.635069196605717) |
57 | | - self.assertAlmostEqual(tc_cc.calc_scale_knutson(ref_year=2100, rcp_scenario=85), |
58 | | - 2.940055236533517) |
59 | | - self.assertAlmostEqual(tc_cc.calc_scale_knutson(ref_year=2066, rcp_scenario=26), |
60 | | - 0.341930203294547) |
61 | | - self.assertAlmostEqual(tc_cc.calc_scale_knutson(ref_year=2078, rcp_scenario=26), |
62 | | - 0.312383928930456) |
| 88 | + |
| 89 | + yearly_steps = 8 |
| 90 | + predicted_changes = tc_cc.get_knutson_scaling_factor(yearly_steps=yearly_steps) |
| 91 | + |
| 92 | + np.testing.assert_equal(predicted_changes.columns, np.array(['2.6', '4.5', '6.0', '8.5'])) |
| 93 | + |
| 94 | + simulated_years = np.arange(tc_cc.YEAR_WINDOWS_PROPS['start'], |
| 95 | + tc_cc.YEAR_WINDOWS_PROPS['end']+1, |
| 96 | + yearly_steps) |
| 97 | + np.testing.assert_equal(predicted_changes.index, simulated_years) |
| 98 | + |
| 99 | + def test_get_knutson_scaling_valid_inputs(self): |
| 100 | + df = tc_cc.get_knutson_scaling_factor() |
| 101 | + self.assertIsInstance(df, pd.DataFrame) |
| 102 | + np.testing.assert_equal(df.shape, (21, 4)) |
| 103 | + |
| 104 | + def test_get_knutson_scaling_invalid_baseline_start_year(self): |
| 105 | + with self.assertRaises(ValueError): |
| 106 | + tc_cc.get_knutson_scaling_factor(baseline=(1870, 2022)) |
| 107 | + |
| 108 | + def test_get_knutson_scaling_invalid_baseline_end_year(self): |
| 109 | + with self.assertRaises(ValueError): |
| 110 | + tc_cc.get_knutson_scaling_factor(baseline=(1982, 2110)) |
| 111 | + |
| 112 | + def test_get_knutson_scaling_no_scaling_factors_for_unknonw_basin(self): |
| 113 | + df = tc_cc.get_knutson_scaling_factor(basin='ZZZZZ') |
| 114 | + self.assertIsInstance(df, pd.DataFrame) |
| 115 | + np.testing.assert_equal(df.values, np.ones_like(df.values)) |
| 116 | + |
| 117 | + def test_get_gmst(self): |
| 118 | + """Test get_gmst_info function.""" |
| 119 | + gmst_info = tc_cc.get_gmst_info() |
| 120 | + |
| 121 | + self.assertAlmostEqual(gmst_info['gmst_start_year'], 1880) |
| 122 | + self.assertAlmostEqual(gmst_info['gmst_end_year'], 2100) |
| 123 | + self.assertAlmostEqual(len(gmst_info['rcps']), 4) |
| 124 | + |
| 125 | + self.assertAlmostEqual(gmst_info['gmst_data'].shape, |
| 126 | + (len(gmst_info['rcps']), |
| 127 | + gmst_info['gmst_end_year']-gmst_info['gmst_start_year']+1)) |
| 128 | + self.assertAlmostEqual(gmst_info['gmst_data'][0,0], -0.16) |
| 129 | + self.assertAlmostEqual(gmst_info['gmst_data'][0,-1], 1.27641, 4) |
| 130 | + self.assertAlmostEqual(gmst_info['gmst_data'][-1,0], -0.16) |
| 131 | + self.assertAlmostEqual(gmst_info['gmst_data'][-1,-1], 4.477764, 4) |
| 132 | + |
| 133 | + def test_get_knutson_data_pass(self): |
| 134 | + """Test get_knutson_data function.""" |
| 135 | + |
| 136 | + data_knutson = tc_cc.get_knutson_data() |
| 137 | + |
| 138 | + self.assertAlmostEqual(data_knutson.shape, (4,6,5)) |
| 139 | + self.assertAlmostEqual(data_knutson[0,0,0], -34.49) |
| 140 | + self.assertAlmostEqual(data_knutson[-1,-1,-1], 15.419) |
| 141 | + self.assertAlmostEqual(data_knutson[0,-1,-1], 4.689) |
| 142 | + self.assertAlmostEqual(data_knutson[-1,0,0], 5.848) |
| 143 | + self.assertAlmostEqual(data_knutson[-1,0,-1], 22.803) |
| 144 | + self.assertAlmostEqual(data_knutson[2,3,2], 4.324) |
63 | 145 |
|
64 | 146 | if __name__ == "__main__": |
65 | 147 | TESTS = unittest.TestLoader().loadTestsFromTestCase(TestKnutson) |
|
0 commit comments