def test_get_landfall_idx(self): """Test identification of landfalls""" tr_ds = xr.Dataset() datetimes = list() for h in range(0, 24, 3): datetimes.append(dt(2000, 1, 1, h)) tr_ds.coords['time'] = ('time', datetimes) # no landfall tr_ds['on_land'] = np.repeat(np.array([False]), 8) sea_land_idx, land_sea_idx = tc._get_landfall_idx(tr_ds) self.assertEqual([len(sea_land_idx), len(land_sea_idx)], [0,0]) # single landfall tr_ds['on_land'] = np.array([False, False, True, True, True, False, False, False]) sea_land_idx, land_sea_idx = tc._get_landfall_idx(tr_ds) self.assertEqual([len(sea_land_idx), len(land_sea_idx)], [1,1]) self.assertEqual([sea_land_idx, land_sea_idx], [2, 5]) # single landfall from starting point tr_ds['on_land'] = np.array([True, True, True, True, True, False, False, False]) sea_land_idx, land_sea_idx = tc._get_landfall_idx(tr_ds) self.assertEqual([len(sea_land_idx), len(land_sea_idx)], [0,0]) sea_land_idx, land_sea_idx = tc._get_landfall_idx(tr_ds, include_starting_landfall=True) self.assertEqual([sea_land_idx, land_sea_idx], [0, 5]) # two landfalls tr_ds['on_land'] = np.array([False, True, True, False, False, False, True, True]) sea_land_idx, land_sea_idx = tc._get_landfall_idx(tr_ds) self.assertEqual([len(sea_land_idx), len(land_sea_idx)], [2,2]) self.assertEqual(sea_land_idx.tolist(), [1,6]) self.assertEqual(land_sea_idx.tolist(), [3,8]) # two landfalls, starting on land tr_ds['on_land'] = np.array([True, True, False, False, True, True, False, False]) sea_land_idx, land_sea_idx = tc._get_landfall_idx(tr_ds) self.assertEqual([sea_land_idx, land_sea_idx], [4, 6]) sea_land_idx, land_sea_idx = tc._get_landfall_idx(tr_ds, include_starting_landfall=True) self.assertEqual(sea_land_idx.tolist(), [0,4]) self.assertEqual(land_sea_idx.tolist(), [2,6])
def test_decay_end_ocean(self): """Test decay is applied after landfall if the track ends over the ocean""" tracks_synth_nodecay_example = tc.TCTracks() # this track was generated without applying landfall decay # (i.e. with decay=False in tc_synth.calc_perturbed_trajectories) tracks_synth_nodecay_example.read_netcdf(TEST_TRACK_DECAY_END_OCEAN) # apply landfall decay extent = tracks_synth_nodecay_example.get_extent() land_geom = climada.util.coordinates.get_land_geometry(extent=extent, resolution=10) tracks_synth_nodecay_example.data = tc_synth._apply_land_decay( tracks_synth_nodecay_example.data, tc_synth.LANDFALL_DECAY_V, tc_synth.LANDFALL_DECAY_P, land_geom) track = tracks_synth_nodecay_example.data[0] # read its corresponding historical track track_hist = tc.TCTracks() track_hist.read_netcdf(TEST_TRACK_DECAY_END_OCEAN_HIST) track_hist = track_hist.data[0] # Part 1: is landfall applied after going back to the ocean? # get that last strip over the ocean lf_idx = tc._get_landfall_idx(track) last_lf_idx = lf_idx[-1][1] # only suitable if track ends over the ocean self.assertTrue(last_lf_idx < track.time.size - 2, 'This test should be re-written, data not suitable') # check pressure and wind values p_hist_end = track_hist.central_pressure.values[last_lf_idx:] p_synth_end = track.central_pressure.values[last_lf_idx:] self.assertTrue(np.all(p_synth_end > p_hist_end)) v_hist_end = track_hist.max_sustained_wind.values[last_lf_idx:] v_synth_end = track.max_sustained_wind.values[last_lf_idx:] self.assertTrue(np.all(v_synth_end < v_hist_end)) # Part 2: is landfall applied in all landfalls? p_hist_lf = np.concatenate([ track_hist.central_pressure.values[lfs:lfe] for lfs, lfe in zip(*lf_idx) ]) p_synth_lf = np.concatenate([ track.central_pressure.values[lfs:lfe] for lfs, lfe in zip(*lf_idx) ]) v_hist_lf = np.concatenate([ track_hist.max_sustained_wind.values[lfs:lfe] for lfs, lfe in zip(*lf_idx) ]) v_synth_lf = np.concatenate([ track.max_sustained_wind.values[lfs:lfe] for lfs, lfe in zip(*lf_idx) ]) self.assertTrue(np.all(p_synth_lf > p_hist_lf)) self.assertTrue(np.all(v_synth_lf < v_hist_lf)) self.assertTrue( np.all(track.central_pressure.values <= track.environmental_pressure.values))
def test_decay_penv_gt_pcen(self): """Test decay is applied if penv at end of landfall < pcen just before landfall""" tracks_synth_nodecay_example = tc.TCTracks() # this track was generated without applying landfall decay # (i.e. with decay=False in tc_synth.calc_perturbed_trajectories) tracks_synth_nodecay_example.read_netcdf(TEST_TRACK_DECAY_PENV_GT_PCEN) # apply landfall decay extent = tracks_synth_nodecay_example.get_extent() land_geom = climada.util.coordinates.get_land_geometry(extent=extent, resolution=10) tracks_synth_nodecay_example.data = tc_synth._apply_land_decay( tracks_synth_nodecay_example.data, tc_synth.LANDFALL_DECAY_V, tc_synth.LANDFALL_DECAY_P, land_geom) track = tracks_synth_nodecay_example.data[0] # read its corresponding historical track track_hist = tc.TCTracks() track_hist.read_netcdf(TEST_TRACK_DECAY_PENV_GT_PCEN_HIST) track_hist = track_hist.data[0] # Part 1: is landfall applied after going back to the ocean? # get that last strip over the ocean lf_idx = tc._get_landfall_idx(track) start_lf_idx, end_lf_idx = lf_idx[0][0], lf_idx[1][0] # check pressure and wind values p_hist_end = track_hist.central_pressure.values[end_lf_idx:] p_synth_end = track.central_pressure.values[end_lf_idx:] self.assertTrue(np.all(p_synth_end > p_hist_end)) v_hist_end = track_hist.max_sustained_wind.values[end_lf_idx:] v_synth_end = track.max_sustained_wind.values[end_lf_idx:] self.assertTrue(np.all(v_synth_end < v_hist_end)) # Part 2: is landfall applied in all landfalls? # central pressure p_hist_lf = track_hist.central_pressure.values[start_lf_idx:end_lf_idx] p_synth_lf = track.central_pressure.values[start_lf_idx:end_lf_idx] # central pressure should be higher in synth than hist; unless it was set to p_env self.assertTrue( np.all( np.logical_or( p_synth_lf > p_hist_lf, p_synth_lf == track. environmental_pressure.values[start_lf_idx:end_lf_idx]))) # but for this track is should be higher towards the end self.assertTrue(np.any(p_synth_lf > p_hist_lf)) self.assertTrue(np.all(p_synth_lf >= p_hist_lf)) # wind speed v_hist_lf = track_hist.max_sustained_wind.values[ start_lf_idx:end_lf_idx] v_synth_lf = track.max_sustained_wind.values[start_lf_idx:end_lf_idx] # wind should decrease over time for that landfall v_before_lf = track_hist.max_sustained_wind.values[start_lf_idx - 1] self.assertTrue(np.all(v_synth_lf[1:] < v_before_lf)) # and wind speed should be lower in synth than hist at the end of and after this landfall self.assertTrue( np.all(track.max_sustained_wind.values[end_lf_idx:] < track_hist.max_sustained_wind.values[end_lf_idx:])) # finally, central minus env pressure cannot increase during this landfall p_env_lf = track.central_pressure.values[start_lf_idx:end_lf_idx] self.assertTrue(np.all(np.diff(p_env_lf - p_synth_lf) <= 0))