Exemple #1
0
    def test_read_with_basin(self):
        """Filter TCs by (genesis) basin."""
        # South Atlantic (not usually a TC location at all)
        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(basin="SA")
        self.assertEqual(tc_track.size, 3)

        # the basin is not necessarily the genesis basin
        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(year_range=(1995, 1995), basin="SP", estimate_missing=True)
        self.assertEqual(tc_track.size, 6)
        self.assertEqual(tc_track.data[0].basin[0], 'SP')
        self.assertEqual(tc_track.data[5].basin[0], 'SI')

        # genesis in NI
        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(
            year_range=(1994, 1994), genesis_basin="NI", estimate_missing=True)
        self.assertEqual(tc_track.size, 5)
        for tr in tc_track.data:
            self.assertEqual(tr.basin[0], "NI")

        # genesis in EP, but crosses WP at some point
        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(year_range=(2002, 2003), basin="WP", genesis_basin="EP")
        self.assertEqual(tc_track.size, 3)
        for tr in tc_track.data:
            self.assertEqual(tr.basin[0], "EP")
            self.assertIn("WP", tr.basin)
    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))
Exemple #3
0
    def test_interp_track_pass(self):
        """Interpolate track to min_time_step. Compare to MATLAB reference."""
        tc_track = tc.TCTracks()
        tc_track.read_processed_ibtracs_csv(TEST_TRACK)
        tc_track.equal_timestep(time_step_h=1)

        self.assertEqual(tc_track.data[0].time.size, 223)
        self.assertAlmostEqual(tc_track.data[0].lon.values[11], -27.426151640151684)
        self.assertAlmostEqual(float(tc_track.data[0].lat[23]), 12.300006169591480)
        self.assertEqual(tc_track.data[0].time_step[7], 1)
        self.assertEqual(np.max(tc_track.data[0].radius_max_wind), 0)
        self.assertEqual(np.min(tc_track.data[0].radius_max_wind), 0)
        self.assertEqual(tc_track.data[0].max_sustained_wind[21], 25)
        self.assertTrue(np.isfinite(tc_track.data[0].central_pressure.values).all())
        self.assertAlmostEqual(tc_track.data[0].central_pressure.values[29], 1008, places=0)
        self.assertEqual(np.max(tc_track.data[0].environmental_pressure), 1010)
        self.assertEqual(np.min(tc_track.data[0].environmental_pressure), 1010)
        self.assertEqual(tc_track.data[0]['time.year'][13], 1951)
        self.assertEqual(tc_track.data[0]['time.month'][26], 8)
        self.assertEqual(tc_track.data[0]['time.day'][7], 27)
        self.assertEqual(tc_track.data[0].max_sustained_wind_unit, 'kn')
        self.assertEqual(tc_track.data[0].central_pressure_unit, 'mb')
        self.assertEqual(tc_track.data[0].orig_event_flag, 1)
        self.assertEqual(tc_track.data[0].name, '1951239N12334')
        self.assertEqual(tc_track.data[0].data_provider, 'hurdat_atl')
        np.testing.assert_array_equal(tc_track.data[0].basin, 'NA')
        self.assertEqual(tc_track.data[0].id_no, 1951239012334)
        self.assertEqual(tc_track.data[0].category, 1)

        # test some "generic floats"
        for time_step_h in [0.6663545049172093, 2.509374054925788, 8.175754471661111]:
            # artifically create data that doesn't start at full hour
            for loffset in [0, 22, 30]:
                tc_track = tc.TCTracks()
                tc_track.read_processed_ibtracs_csv(TEST_TRACK)
                tc_track.data[0].time.values[:] += np.timedelta64(loffset, "m")
                tc_track.equal_timestep(time_step_h=time_step_h)
                np.testing.assert_array_equal(tc_track.data[0].time_step, time_step_h)
                self.assertTrue(np.isfinite(tc_track.data[0].central_pressure.values).all())

        tc_track = tc.TCTracks()
        tc_track.read_processed_ibtracs_csv(TEST_TRACK)
        tc_track.equal_timestep(time_step_h=0.16667)

        self.assertEqual(tc_track.data[0].time.size, 1332)
        self.assertTrue(np.all(tc_track.data[0].time_step == 0.16667))
        self.assertTrue(np.isfinite(tc_track.data[0].central_pressure.values).all())
        self.assertAlmostEqual(tc_track.data[0].lon.values[65], -27.397636528537127)

        for time_step_h in [0, -0.5, -1]:
            tc_track = tc.TCTracks()
            tc_track.read_processed_ibtracs_csv(TEST_TRACK)
            msg = f"time_step_h is not a positive number: {time_step_h}"
            with self.assertRaises(ValueError, msg=msg) as _cm:
                tc_track.equal_timestep(time_step_h=time_step_h)
    def test_get_track_pass(self):
        """Test get_track."""
        tc_track = tc.TCTracks()
        tc_track.read_processed_ibtracs_csv(TEST_TRACK_SHORT)
        self.assertIsInstance(tc_track.get_track(), xr.Dataset)
        self.assertIsInstance(tc_track.get_track('1951239N12334'), xr.Dataset)

        tc_track_bis = tc.TCTracks()
        tc_track_bis.read_processed_ibtracs_csv(TEST_TRACK_SHORT)
        tc_track.append(tc_track_bis)
        self.assertIsInstance(tc_track.get_track(), list)
        self.assertIsInstance(tc_track.get_track('1951239N12334'), xr.Dataset)
Exemple #5
0
    def test_write_read_netcdf(self):
        """Test writting and reading netcdf4 TCTracks instances"""
        path = DATA_DIR.joinpath("tc_tracks_nc")
        path.mkdir(exist_ok=True)
        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(provider='usa', storm_id='1988234N13299',
                                     estimate_missing=True)
        tc_track.write_netcdf(str(path))

        tc_read = tc.TCTracks()
        tc_read.read_netcdf(str(path))

        self.assertEqual(tc_track.get_track().sid, tc_read.get_track().sid)
Exemple #6
0
    def test_raw_ibtracs_invalid_pass(self):
        """Test reading invalid/non-existing TC from IBTrACS files"""
        tc_track = tc.TCTracks()
        with self.assertRaises(ValueError) as cm:
            tc_track.read_ibtracs_netcdf(storm_id='INVALID')
        self.assertIn("IDs are invalid", str(cm.exception))
        self.assertIn("INVALID", str(cm.exception))

        tc_track = tc.TCTracks()
        with self.assertRaises(ValueError) as cm:
            tc_track.read_ibtracs_netcdf(storm_id='1988234N13298')
        self.assertIn("IDs are not in IBTrACS", str(cm.exception))
        self.assertIn("1988234N13298", str(cm.exception))
Exemple #7
0
    def test_write_read_pass(self):
        """Test writting and reading netcdf4 TCTracks instances"""
        path = os.path.join(DATA_DIR, "tc_tracks_nc")
        os.makedirs(path, exist_ok=True)
        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(provider='usa',
                                     storm_id='1988234N13299',
                                     estimate_missing=True)
        tc_track.write_netcdf(path)

        tc_read = tc.TCTracks()
        tc_read.read_netcdf(path)

        self.assertEqual(tc_track.get_track().sid, tc_read.get_track().sid)
Exemple #8
0
 def test_discard_single_points(self):
     """Check discard_single_points option"""
     tc_track_singlept = tc.TCTracks()
     passed = False
     for year in range(1863, 1981):
         tc_track_singlept.read_ibtracs_netcdf(provider='usa',
                                      year_range=(year,year),
                                      discard_single_points=False)
         n_singlepts = np.sum([x.time.size == 1 for x in tc_track_singlept.data])
         if n_singlepts > 0:
             tc_track = tc.TCTracks()
             tc_track.read_ibtracs_netcdf(provider='usa', year_range=(year,year))
             if tc_track.size == tc_track_singlept.size - n_singlepts:
                 passed = True
                 break
     self.assertTrue(passed)
Exemple #9
0
 def test_raw_ibtracs_empty_pass(self):
     """Test reading empty TC from IBTrACS files"""
     tc_track = tc.TCTracks()
     tc_track.read_ibtracs_netcdf(
         provider='usa', storm_id='1988234N13299')
     self.assertEqual(tc_track.size, 0)
     self.assertEqual(tc_track.get_track(), [])
Exemple #10
0
 def test_random_no_landfall_pass(self):
     """Test calc_random_walk with decay and no historical tracks with landfall"""
     tc_track = tc.TCTracks()
     tc_track.read_processed_ibtracs_csv(TEST_TRACK_SHORT)
     with self.assertLogs('climada.hazard.tc_tracks_synth', level='INFO') as cm:
         tc_track.calc_random_walk()
     self.assertIn('No historical track with landfall.', cm.output[1])
Exemple #11
0
    def test_read_simulations_chaz(self):
        """Test reading NetCDF output from CHAZ simulations"""
        tc_track = tc.TCTracks()

        tc_track.read_simulations_chaz(TEST_TRACK_CHAZ)
        self.assertEqual(len(tc_track.data), 13)
        self.assertEqual(tc_track.data[0].time.size, 5)
        self.assertEqual(tc_track.data[0].lon[3], 74.1388328911036)
        self.assertEqual(tc_track.data[0].lat[4], -9.813585651475156)
        self.assertEqual(tc_track.data[0].time_step[3], 6)
        self.assertEqual(tc_track.data[0].max_sustained_wind[2], 20.188325232226354)
        self.assertAlmostEqual(tc_track.data[0].central_pressure.values[1], 1008, places=0)
        self.assertTrue(np.all(tc_track.data[0].time.dt.year == 1991))
        self.assertEqual(tc_track.data[0].time.dt.month[2], 1)
        self.assertEqual(tc_track.data[0].time.dt.day[3], 15)
        self.assertEqual(tc_track.data[0].max_sustained_wind_unit, 'kn')
        self.assertEqual(tc_track.data[0].central_pressure_unit, 'mb')
        self.assertEqual(tc_track.data[0].sid, 'chaz_test_tracks.nc-1-0')
        self.assertEqual(tc_track.data[0].name, 'chaz_test_tracks.nc-1-0')
        self.assertTrue(np.all([np.all(d.basin == 'GB') for d in tc_track.data]))
        self.assertEqual(tc_track.data[4].category, 0)
        self.assertEqual(tc_track.data[3].category, -1)

        tc_track.read_simulations_chaz(TEST_TRACK_CHAZ, year_range=(1990, 1991))
        self.assertEqual(len(tc_track.data), 3)

        tc_track.read_simulations_chaz(TEST_TRACK_CHAZ, year_range=(1950, 1955))
        self.assertEqual(len(tc_track.data), 0)

        tc_track.read_simulations_chaz(TEST_TRACK_CHAZ, ensemble_nums=[0, 2])
        self.assertEqual(len(tc_track.data), 9)
Exemple #12
0
    def test_read_one_gettelman(self):
        """Test reading and model of TC from Gettelman track files"""
        tc_track_G = tc.TCTracks()
        # populate tracks by loading data from NetCDF:
        nc_data = nc.Dataset(TEST_TRACK_GETTELMAN)
        nstorms = nc_data.dimensions['storm'].size
        for i in range(nstorms):
            tc_track_G.read_one_gettelman(nc_data, i)

        self.assertEqual(tc_track_G.data[0].time.size, 29)
        self.assertEqual(tc_track_G.data[0].lon[11], 60.0)
        self.assertEqual(tc_track_G.data[0].lat[23], 10.20860481262207)
        self.assertEqual(tc_track_G.data[0].time_step[7], 3.)
        self.assertEqual(np.max(tc_track_G.data[0].radius_max_wind), 65)
        self.assertEqual(np.min(tc_track_G.data[0].radius_max_wind), 65)
        self.assertEqual(tc_track_G.data[0].max_sustained_wind[21], 39.91877223718089)
        self.assertEqual(tc_track_G.data[0].central_pressure[27], 1005.969482421875)
        self.assertEqual(np.max(tc_track_G.data[0].environmental_pressure), 1015)
        self.assertEqual(np.min(tc_track_G.data[0].environmental_pressure), 1015)
        self.assertEqual(tc_track_G.data[0].maximum_precipitation[14], 219.10108947753906)
        self.assertEqual(tc_track_G.data[0].average_precipitation[12], 101.43893432617188)
        self.assertEqual(tc_track_G.data[0].time.dt.year[13], 1979)
        self.assertEqual(tc_track_G.data[0].time.dt.month[26], 1)
        self.assertEqual(tc_track_G.data[0].time.dt.day[7], 2)
        self.assertEqual(tc_track_G.data[0].max_sustained_wind_unit, 'kn')
        self.assertEqual(tc_track_G.data[0].central_pressure_unit, 'mb')
        self.assertEqual(tc_track_G.data[0].sid, '0')
        self.assertEqual(tc_track_G.data[0].name, '0')
        np.testing.assert_array_equal(tc_track_G.data[0].basin, 'NI')
        self.assertEqual(tc_track_G.data[0].category, 0)
    def test_read_with_provider(self):
        """Read a tropical cyclone with and without explicit provider."""
        tc_track = tc.TCTracks()
        storm_id = '2012152N12130'

        tc_track.read_ibtracs_netcdf(storm_id=storm_id, provider='usa')
        track_ds = tc_track.get_track()
        self.assertEqual(track_ds.time.size, 51)
        self.assertEqual(track_ds.data_provider, 'ibtracs_usa')
        self.assertAlmostEqual(track_ds.lat.values[50], 34.3, places=5)
        self.assertAlmostEqual(track_ds.central_pressure.values[50],
                               989,
                               places=5)
        self.assertAlmostEqual(track_ds.radius_max_wind.values[46],
                               20,
                               places=5)

        tc_track.read_ibtracs_netcdf(storm_id=storm_id)
        track_ds = tc_track.get_track()
        self.assertEqual(track_ds.time.size, 35)
        self.assertEqual(track_ds.data_provider, 'ibtracs_official_3h_mixed')
        self.assertAlmostEqual(track_ds.lat.values[-1], 31.40, places=5)
        self.assertAlmostEqual(track_ds.central_pressure.values[-1],
                               980,
                               places=5)
Exemple #14
0
    def test_interp_track_pass(self):
        """Interpolate track to min_time_step. Compare to MATLAB reference."""
        tc_track = tc.TCTracks()
        tc_track.read_processed_ibtracs_csv(TEST_TRACK)
        tc_track.equal_timestep(time_step_h=1)

        self.assertEqual(tc_track.data[0].time.size, 223)
        self.assertAlmostEqual(tc_track.data[0].lon.values[11],
                               -27.426151640151684)
        self.assertAlmostEqual(float(tc_track.data[0].lat[23]),
                               12.300006169591480)
        self.assertEqual(tc_track.data[0].time_step[7], 1)
        self.assertEqual(np.max(tc_track.data[0].radius_max_wind), 0)
        self.assertEqual(np.min(tc_track.data[0].radius_max_wind), 0)
        self.assertEqual(tc_track.data[0].max_sustained_wind[21], 25)
        self.assertAlmostEqual(tc_track.data[0].central_pressure.values[29],
                               1.0077614e+03)
        self.assertEqual(np.max(tc_track.data[0].environmental_pressure), 1010)
        self.assertEqual(np.min(tc_track.data[0].environmental_pressure), 1010)
        self.assertEqual(tc_track.data[0]['time.year'][13], 1951)
        self.assertEqual(tc_track.data[0]['time.month'][26], 8)
        self.assertEqual(tc_track.data[0]['time.day'][7], 27)
        self.assertEqual(tc_track.data[0].max_sustained_wind_unit, 'kn')
        self.assertEqual(tc_track.data[0].central_pressure_unit, 'mb')
        self.assertEqual(tc_track.data[0].orig_event_flag, 1)
        self.assertEqual(tc_track.data[0].name, '1951239N12334')
        self.assertEqual(tc_track.data[0].data_provider, 'hurdat_atl')
        self.assertTrue(np.isnan(tc_track.data[0].basin))
        self.assertEqual(tc_track.data[0].id_no, 1951239012334)
        self.assertEqual(tc_track.data[0].category, 1)
 def test_random_walk_decay_pass(self):
     """Test land decay is called from calc_perturbed_trajectories."""
     tc_track = tc.TCTracks()
     assert TC_ANDREW_FL.is_file()
     tc_track.read_processed_ibtracs_csv(TC_ANDREW_FL)
     nb_synth_tracks = 2
     with self.assertLogs('climada.hazard.tc_tracks_synth',
                          level='DEBUG') as cm:
         tc_track.calc_perturbed_trajectories(
             nb_synth_tracks=nb_synth_tracks, seed=25, decay=True)
     self.assertIn(
         'No historical track of category Tropical Depression '
         'with landfall.', cm.output[1])
     self.assertIn('Decay parameters from category Hurricane Cat. 4 taken.',
                   cm.output[2])
     self.assertIn(
         'No historical track of category Hurricane Cat. 1 with '
         'landfall.', cm.output[3])
     self.assertIn('Decay parameters from category Hurricane Cat. 4 taken.',
                   cm.output[4])
     self.assertIn(
         'No historical track of category Hurricane Cat. 3 with '
         'landfall. Decay parameters from category Hurricane Cat. '
         '4 taken.', cm.output[5])
     self.assertIn(
         'No historical track of category Hurricane Cat. 5 with '
         'landfall.', cm.output[6])
 def test_random_walk_identical_pass(self):
     """Test 0 perturbation leads to identical tracks."""
     tc_track = tc.TCTracks()
     tc_track.read_processed_ibtracs_csv(TC_ANDREW_FL)
     nb_synth_tracks = 2
     tc_track.calc_perturbed_trajectories(nb_synth_tracks=nb_synth_tracks,
                                          max_shift_ini=0,
                                          max_dspeed_rel=0,
                                          max_ddirection=0,
                                          decay=False)
     orig_track = tc_track.data[0]
     for syn_track in tc_track.data[1:]:
         np.testing.assert_allclose(orig_track.lon.values,
                                    syn_track.lon.values,
                                    atol=1e-4)
         np.testing.assert_allclose(orig_track.lat.values,
                                    syn_track.lat.values,
                                    atol=1e-4)
         for varname in [
                 "time", "time_step", "radius_max_wind",
                 "max_sustained_wind", "central_pressure",
                 "environmental_pressure"
         ]:
             np.testing.assert_array_equal(orig_track[varname].values,
                                           syn_track[varname].values)
    def test_read_processed_ibtracs_csv(self):
        tc_track = tc.TCTracks()
        tc_track.read_processed_ibtracs_csv(TEST_TRACK)

        self.assertEqual(tc_track.data[0].time.size, 38)
        self.assertEqual(tc_track.data[0].lon[11], -39.60)
        self.assertEqual(tc_track.data[0].lat[23], 14.10)
        self.assertEqual(tc_track.data[0].time_step[7], 6)
        self.assertEqual(np.max(tc_track.data[0].radius_max_wind), 0)
        self.assertEqual(np.min(tc_track.data[0].radius_max_wind), 0)
        self.assertEqual(tc_track.data[0].max_sustained_wind[21], 55)
        self.assertAlmostEqual(tc_track.data[0].central_pressure.values[29],
                               976,
                               places=0)
        self.assertEqual(np.max(tc_track.data[0].environmental_pressure), 1010)
        self.assertEqual(np.min(tc_track.data[0].environmental_pressure), 1010)
        self.assertEqual(tc_track.data[0].time.dt.year[13], 1951)
        self.assertEqual(tc_track.data[0].time.dt.month[26], 9)
        self.assertEqual(tc_track.data[0].time.dt.day[7], 29)
        self.assertEqual(tc_track.data[0].max_sustained_wind_unit, 'kn')
        self.assertEqual(tc_track.data[0].central_pressure_unit, 'mb')
        self.assertEqual(tc_track.data[0].orig_event_flag, 1)
        self.assertEqual(tc_track.data[0].name, '1951239N12334')
        self.assertEqual(tc_track.data[0].sid, '1951239N12334')
        self.assertEqual(tc_track.data[0].id_no, 1951239012334)
        self.assertEqual(tc_track.data[0].data_provider, 'hurdat_atl')
        self.assertTrue(np.isnan(tc_track.data[0].basin))
        self.assertEqual(tc_track.data[0].id_no, 1951239012334)
        self.assertEqual(tc_track.data[0].category, 1)
    def test_read_simulations_storm(self):
        """Test reading NetCDF output from STORM simulations"""
        tc_track = tc.TCTracks()

        tc_track.read_simulations_storm(TEST_TRACK_STORM)
        self.assertEqual(len(tc_track.data), 6)
        self.assertEqual(tc_track.data[0].time.size, 15)
        self.assertEqual(tc_track.data[0].lon[3], 245.3)
        self.assertEqual(tc_track.data[0].lat[4], 11.9)
        self.assertEqual(tc_track.data[0].time_step[3], 3)
        self.assertEqual(tc_track.data[0].max_sustained_wind[2],
                         37.127429805615556)
        self.assertEqual(tc_track.data[0].radius_max_wind[5],
                         19.07407454551836)
        self.assertEqual(tc_track.data[0].central_pressure[1], 999.4)
        self.assertTrue(np.all(tc_track.data[0].time.dt.year == 1980))
        self.assertEqual(tc_track.data[0].time.dt.month[2].item(), 6)
        self.assertEqual(tc_track.data[0].time.dt.day[3].item(), 1)
        self.assertEqual(tc_track.data[0].max_sustained_wind_unit, 'kn')
        self.assertEqual(tc_track.data[0].central_pressure_unit, 'mb')
        self.assertEqual(tc_track.data[0].sid, 'storm_test_tracks.txt-0-0')
        self.assertEqual(tc_track.data[0].name, 'storm_test_tracks.txt-0-0')
        self.assertTrue(np.all([d.basin == 'EP' for d in tc_track.data]))
        self.assertEqual(tc_track.data[4].category, 0)
        self.assertEqual(tc_track.data[3].category, 1)

        tc_track.read_simulations_storm(TEST_TRACK_STORM, years=[0, 2])
        self.assertEqual(len(tc_track.data), 4)

        tc_track.read_simulations_storm(TEST_TRACK_STORM, years=[7])
        self.assertEqual(len(tc_track.data), 0)
    def test_read_estimate_missing(self):
        """Read a tropical cyclone and estimate missing values."""
        tc_track = tc.TCTracks()
        storm_id = '2012152N12130'

        tc_track.read_ibtracs_netcdf(storm_id=storm_id, estimate_missing=True)
        track_ds = tc_track.get_track()
        # less time steps are discarded, leading to a larger total size
        self.assertEqual(track_ds.time.size, 99)
        self.assertEqual(track_ds.data_provider, 'ibtracs_official_3h_mixed')
        self.assertAlmostEqual(track_ds.lat.values[44], 33.30, places=5)
        self.assertAlmostEqual(track_ds.central_pressure.values[44],
                               976,
                               places=5)
        self.assertAlmostEqual(track_ds.central_pressure.values[42],
                               980,
                               places=5)
        # the wind speed at position 44 is missing in the original data
        self.assertAlmostEqual(track_ds.max_sustained_wind.values[44],
                               58,
                               places=0)
        self.assertAlmostEqual(track_ds.radius_oci.values[40], 160, places=0)
        # after position 42, ROCI is missing in the original data
        self.assertAlmostEqual(track_ds.radius_oci.values[42], 200, places=-1)
        self.assertAlmostEqual(track_ds.radius_oci.values[85], 165, places=-1)
        self.assertAlmostEqual(track_ds.radius_oci.values[95], 155, places=-1)
    def test_read_interpolate_missing(self):
        """Read a tropical cyclone with and without interpolating missing values."""
        tc_track = tc.TCTracks()
        storm_id = '2010066S19050'

        tc_track.read_ibtracs_netcdf(storm_id=storm_id,
                                     interpolate_missing=False)
        track_ds = tc_track.get_track()
        self.assertEqual(track_ds.time.size, 50)
        self.assertAlmostEqual(track_ds.central_pressure.values[30],
                               992,
                               places=5)
        self.assertAlmostEqual(track_ds.central_pressure.values[31],
                               1006,
                               places=5)

        tc_track.read_ibtracs_netcdf(storm_id=storm_id,
                                     interpolate_missing=True)
        track_ds = tc_track.get_track()
        self.assertEqual(track_ds.time.size, 65)
        self.assertAlmostEqual(track_ds.central_pressure.values[30],
                               992,
                               places=5)
        self.assertAlmostEqual(track_ds.central_pressure.values[38],
                               999,
                               places=5)
        self.assertAlmostEqual(track_ds.central_pressure.values[46],
                               1006,
                               places=5)
Exemple #21
0
 def test_ibtracs_correct_pass(self):
     """Check estimate_missing option"""
     tc_try = tc.TCTracks()
     tc_try.read_ibtracs_netcdf(provider='usa', storm_id='1982267N25289',
                                estimate_missing=True)
     self.assertAlmostEqual(tc_try.data[0].central_pressure.values[0], 1013, places=0)
     self.assertAlmostEqual(tc_try.data[0].central_pressure.values[5], 1008, places=0)
     self.assertAlmostEqual(tc_try.data[0].central_pressure.values[-1], 1012, places=0)
    def test_to_geodataframe_line(self):
        """Conversion of TCTracks to GeoDataFrame using LineStrings."""
        tc_track = tc.TCTracks()
        tc_track.read_processed_ibtracs_csv(TEST_TRACK)

        gdf_line = tc_track.to_geodataframe()
        self.assertIsInstance(gdf_line.basin[0], np.float64)
        self.assertEqual(gdf_line.size, 10)
        self.assertAlmostEqual(gdf_line.geometry[0].length, 54.0634224372971)
        self.assertIsInstance(gdf_line.bounds.minx, pd.core.series.Series)

        anti_track = tc.TCTracks()
        # test data set with two tracks:
        # * 1980052S16155: crosses the antimeridian
        # * 2018079S09162: close, but doesn't cross antimeridian; has self-intersections
        anti_track.read_netcdf(TEST_TRACKS_ANTIMERIDIAN)

        split = anti_track.to_geodataframe(split_lines_antimeridian=True)
        split.set_index('sid', inplace=True)
        self.assertIsInstance(split.loc['1980052S16155'].geometry,
                              MultiLineString)
        self.assertIsInstance(split.loc['2018079S09162'].geometry, LineString)
        self.assertEqual(len(split.loc['1980052S16155'].geometry), 8)
        self.assertFalse(split.loc['2018079S09162'].geometry.is_simple)

        nosplit = anti_track.to_geodataframe(split_lines_antimeridian=False)
        nosplit.set_index('sid', inplace=True)
        self.assertIsInstance(nosplit.loc['1980052S16155'].geometry,
                              LineString)
        self.assertIsInstance(nosplit.loc['2018079S09162'].geometry,
                              LineString)
        self.assertFalse(nosplit.loc['2018079S09162'].geometry.is_simple)

        np.testing.assert_array_almost_equal(
            split.loc['1980052S16155'].geometry.bounds,
            (-180, -38.583244, 180, -17))
        np.testing.assert_array_almost_equal(
            nosplit.loc['1980052S16155'].geometry.bounds,
            (150.800003, -38.583244, 185, -17))
        np.testing.assert_array_almost_equal(
            split.loc['2018079S09162'].geometry.bounds,
            (148.600006, -22.41, 162.399994, -13.4))
        np.testing.assert_array_almost_equal(
            nosplit.loc['2018079S09162'].geometry.bounds,
            (148.600006, -22.41, 162.399994, -13.4))
 def test_random_walk_decay_pass(self):
     """Test land decay is called from calc_perturbed_trajectories."""
     tc_track = tc.TCTracks()
     assert TC_ANDREW_FL.is_file()
     tc_track.read_processed_ibtracs_csv(TC_ANDREW_FL)
     nb_synth_tracks = 2
     # should work if using global parameters
     with self.assertLogs('climada.hazard.tc_tracks_synth',
                          level='DEBUG') as cm0:
         tc_track.calc_perturbed_trajectories(
             nb_synth_tracks=nb_synth_tracks,
             seed=25,
             decay=True,
             use_global_decay_params=True)
     self.assertEqual(len(cm0), 2)
     self.assertEqual(tc_track.size, 3)
     # but alert the user otherwise
     tc_track = tc.TCTracks()
     tc_track.read_processed_ibtracs_csv(TC_ANDREW_FL)
     with self.assertLogs('climada.hazard.tc_tracks_synth',
                          level='DEBUG') as cm:
         tc_track.calc_perturbed_trajectories(
             nb_synth_tracks=nb_synth_tracks,
             seed=25,
             decay=True,
             use_global_decay_params=False)
     self.assertIn(
         'No historical track of category Tropical Depression '
         'with landfall.', cm.output[2])
     self.assertIn('Decay parameters from category Hurricane Cat. 4 taken.',
                   cm.output[3])
     self.assertIn(
         'No historical track of category Hurricane Cat. 1 with '
         'landfall.', cm.output[4])
     self.assertIn('Decay parameters from category Hurricane Cat. 4 taken.',
                   cm.output[5])
     self.assertIn(
         'No historical track of category Hurricane Cat. 3 with '
         'landfall. Decay parameters from category Hurricane Cat. '
         '4 taken.', cm.output[6])
     self.assertIn(
         'No historical track of category Hurricane Cat. 5 with '
         'landfall.', cm.output[7])
 def test_cutoff_tracks(self):
     tc_track = tc.TCTracks()
     tc_track.read_ibtracs_netcdf(storm_id='1986226N30276')
     tc_track.equal_timestep()
     with self.assertLogs('climada.hazard.tc_tracks_synth',
                          level='DEBUG') as cm:
         tc_track.calc_perturbed_trajectories(nb_synth_tracks=10)
     self.assertIn(
         'The following generated synthetic tracks moved beyond '
         'the range of [-70, 70] degrees latitude', cm.output[1])
Exemple #25
0
    def test_read_raw_pass(self):
        """Read a tropical cyclone."""
        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(provider='usa', storm_id='2017242N16333')
        self.assertEqual(len(tc_track.data), 1)
        self.assertEqual(tc_track.get_track().time.dt.year.values[0], 2017)
        self.assertEqual(tc_track.get_track().time.dt.month.values[0], 8)
        self.assertEqual(tc_track.get_track().time.dt.day.values[0], 30)
        self.assertEqual(tc_track.get_track().time.dt.hour.values[0], 0)
        self.assertAlmostEqual(tc_track.get_track().lat.values[0],
                               16.1 + 3.8146972514141453e-07)
        self.assertAlmostEqual(tc_track.get_track().lon.values[0],
                               -26.9 + 3.8146972514141453e-07)
        self.assertAlmostEqual(
            tc_track.get_track().max_sustained_wind.values[0], 30)
        self.assertAlmostEqual(tc_track.get_track().central_pressure.values[0],
                               1008)
        self.assertAlmostEqual(
            tc_track.get_track().environmental_pressure.values[0], 1012)
        self.assertAlmostEqual(tc_track.get_track().radius_max_wind.values[0],
                               60)
        self.assertEqual(tc_track.get_track().time.size, 123)

        self.assertAlmostEqual(tc_track.get_track().lat.values[-1],
                               36.8 - 7.629394502828291e-07)
        self.assertAlmostEqual(tc_track.get_track().lon.values[-1], -90.100006,
                               5)
        self.assertAlmostEqual(
            tc_track.get_track().central_pressure.values[-1], 1005)
        self.assertAlmostEqual(
            tc_track.get_track().max_sustained_wind.values[-1], 15)
        self.assertAlmostEqual(
            tc_track.get_track().environmental_pressure.values[-1], 1008)
        self.assertAlmostEqual(tc_track.get_track().radius_max_wind.values[-1],
                               60)

        self.assertFalse(
            np.isnan(tc_track.get_track().radius_max_wind.values).any())
        self.assertFalse(
            np.isnan(tc_track.get_track().environmental_pressure.values).any())
        self.assertFalse(
            np.isnan(tc_track.get_track().max_sustained_wind.values).any())
        self.assertFalse(
            np.isnan(tc_track.get_track().central_pressure.values).any())
        self.assertFalse(np.isnan(tc_track.get_track().lat.values).any())
        self.assertFalse(np.isnan(tc_track.get_track().lon.values).any())

        self.assertEqual(tc_track.get_track().basin, 'NA')
        self.assertEqual(tc_track.get_track().max_sustained_wind_unit, 'kn')
        self.assertEqual(tc_track.get_track().central_pressure_unit, 'mb')
        self.assertEqual(tc_track.get_track().sid, '2017242N16333')
        self.assertEqual(tc_track.get_track().name, 'IRMA')
        self.assertEqual(tc_track.get_track().orig_event_flag, True)
        self.assertEqual(tc_track.get_track().data_provider, 'usa')
        self.assertEqual(tc_track.get_track().category, 5)
Exemple #26
0
    def test_read_legacy_netcdf(self):
        """Test reading from NetCDF files with legacy basin attributes"""
        anti_track = tc.TCTracks()
        # test data set with two tracks:
        # * 1980052S16155: crosses the antimeridian
        # * 2018079S09162: close, but doesn't cross antimeridian; has self-intersections
        anti_track.read_netcdf(TEST_TRACKS_ANTIMERIDIAN)

        for tr in anti_track.data:
            self.assertEqual(tr.basin.shape, tr.time.shape)
            np.testing.assert_array_equal(tr.basin, "SP")
Exemple #27
0
    def test_penv_rmax_penv_pass(self):
        """read_ibtracs_netcdf"""
        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(provider='usa', storm_id='1992230N11325')
        penv_ref = np.ones(97) * 1010
        penv_ref[26:36] = [1011, 1012, 1013, 1014, 1015, 1014, 1014, 1014, 1014, 1012]

        self.assertTrue(np.allclose(
            tc_track.get_track().environmental_pressure.values, penv_ref))
        self.assertTrue(np.allclose(
            tc_track.get_track().radius_max_wind.values, np.zeros(97)))
Exemple #28
0
 def test_get_extent(self):
     """Test extent/bounds attributes."""
     storms = ['1988169N14259', '2002073S16161', '2002143S07157']
     tc_track = tc.TCTracks()
     tc_track.read_ibtracs_netcdf(storm_id=storms, provider=["usa", "bom"])
     bounds = (153.585022, -23.200001, 258.714996, 17.514986)
     extent = (bounds[0], bounds[2], bounds[1], bounds[3])
     bounds_buf = (153.485022, -23.300001, 258.814996, 17.614986)
     np.testing.assert_array_almost_equal(tc_track.bounds, bounds)
     np.testing.assert_array_almost_equal(tc_track.get_bounds(deg_buffer=0.1), bounds_buf)
     np.testing.assert_array_almost_equal(tc_track.extent, extent)
Exemple #29
0
    def test_read_range(self):
        """Read several TCs."""
        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(year_range=(2100, 2150))
        self.assertEqual(tc_track.size, 0)

        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(provider='usa', storm_id=None,
                                     year_range=(1915, 1916), basin='WP')
        self.assertEqual(tc_track.size, 0)

        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(provider='usa', year_range=(1993, 1994),
                                     basin='EP', estimate_missing=False)
        self.assertEqual(tc_track.size, 33)

        tc_track = tc.TCTracks()
        tc_track.read_ibtracs_netcdf(provider='usa', year_range=(1993, 1994),
                                     basin='EP', estimate_missing=True)
        self.assertEqual(tc_track.size, 45)
Exemple #30
0
    def test_to_geodataframe_points(self):
        """Conversion of TCTracks to GeoDataFrame using Points."""
        tc_track = tc.TCTracks()
        tc_track.read_processed_ibtracs_csv(TEST_TRACK)

        gdf_points = tc_track.to_geodataframe(as_points=True)
        self.assertIsInstance(gdf_points.unary_union.bounds, tuple)
        self.assertEqual(gdf_points.shape[0], len(tc_track.data[0].time))
        self.assertEqual(gdf_points.shape[1], len(tc_track.data[0].variables)+len(tc_track.data[0].attrs)-1)
        self.assertAlmostEqual(gdf_points.buffer(3).unary_union.area, 348.79972062947854)
        self.assertIsInstance(gdf_points.iloc[0].time, pd._libs.tslibs.timestamps.Timestamp)