def test_fraction_on_land(self): """Test _fraction_on_land helper function.""" res_deg = 10 / (60 * 60) bounds = (-149.54, -23.42, -149.40, -23.33) lat = np.arange(bounds[1] + 0.5 * res_deg, bounds[3], res_deg) lon = np.arange(bounds[0] + 0.5 * res_deg, bounds[2], res_deg) shape = (lat.size, lon.size) lon, lat = [ar.ravel() for ar in np.meshgrid(lon, lat)] centroids = Centroids() centroids.set_lat_lon(lat, lon) centroids.set_dist_coast(signed=True, precomputed=True) dem_bounds = (bounds[0] - 1, bounds[1] - 1, bounds[2] + 1, bounds[3] + 1) dem_res = 3 / (60 * 60) with tmp_artifical_topo(dem_bounds, dem_res) as topo_path: fraction = _fraction_on_land(centroids, topo_path) fraction = fraction.reshape(shape) dist_coast = centroids.dist_coast.reshape(shape) # check valid range and order of magnitude self.assertTrue(np.all((fraction >= 0) & (fraction <= 1))) np.testing.assert_array_equal(fraction[dist_coast > 1000], 0) np.testing.assert_array_equal(fraction[dist_coast < -1000], 1) # check individual known pixel values self.assertAlmostEqual(fraction[24, 10], 0.0) self.assertAlmostEqual(fraction[22, 11], 0.21) self.assertAlmostEqual(fraction[22, 12], 0.93) self.assertAlmostEqual(fraction[21, 14], 1.0)
def centroids(self, latlon=None, res_as=360): """Return centroids in this region Parameters ---------- latlon : pair (lat, lon), optional Latitude and longitude of centroids. If not given, values are taken from CLIMADA's base grid (see `res_as`). res_as : int, optional One of 150 or 360. When `latlon` is not given, choose coordinates from centroids according to CLIMADA's base grid of given resolution in arc-seconds. Default: 360. Returns ------- centroids : climada.hazard.Centroids object """ if latlon is None: centroids = Centroids.from_base_grid(res_as=res_as) centroids.set_meta_to_lat_lon() lat, lon = centroids.lat, centroids.lon else: lat, lon = latlon centroids = Centroids() centroids.set_lat_lon(lat, lon) msk = shapely.vectorized.contains(self.shape, lon, lat) centroids = centroids.select(sel_cen=msk) centroids.id = np.arange(centroids.lon.shape[0]) return centroids
def calc_tc(expo_dict, tracks, data_dir, pool): """ Compute tropical cyclone events from tracks at every island group, if not contained in data_dir. """ try: abs_path = os.path.join(data_dir, 'tc_isl.p') with open(abs_path, 'rb') as f: tc_dict = pickle.load(f) print('Loaded tc_isl:', len(tc_dict)) except FileNotFoundError: all_isl = BlackMarble(pd.concat(list(expo_dict.values()))) centr = Centroids() centr.set_lat_lon(all_isl.latitude.values, all_isl.longitude.values) centr.region_id = all_isl.region_id.values centr.check() tc = TropCyclone(pool) tc.set_from_tracks(tracks, centr) tc_dict = dict() for ent_iso, ent_val in expo_dict.items(): reg_id = np.unique(ent_val.region_id)[0] tc_dict[ent_iso] = tc.select(reg_id=reg_id) save(os.path.join(data_dir, 'tc_isl.p'), tc_dict) return tc_dict
def irma_tc(exp, data_irma): centr = Centroids() centr.set_lat_lon(exp.latitude.values, exp.longitude.values) tc_irma = TropCyclone() data_irma.equal_timestep(0.1) tc_irma.set_from_tracks(data_irma, centr) return tc_irma
def __init__(self, bounds, res_deg): """Read distance to coast values from raster file for later use. Parameters ---------- bounds : tuple (lon_min, lat_min, lon_max, lat_max) Coordinates of bounding box res_deg : float Resolution in degrees """ lat = np.arange(bounds[3] - 0.5 * res_deg, bounds[1], -res_deg) lon = np.arange(bounds[0] + 0.5 * res_deg, bounds[2], res_deg) self.shape = (lat.size, lon.size) self.transform = rasterio.Affine(res_deg, 0, bounds[0], 0, -res_deg, bounds[3]) centroids = Centroids() centroids.set_lat_lon(*[ar.ravel() for ar in np.meshgrid(lon, lat)][::-1]) centroids.set_dist_coast(signed=True, precomputed=True) self.dist_coast = centroids.dist_coast
def test_surge_from_track(self): """Test TCSurgeBathtub.from_tc_winds function.""" # similar to IBTrACS 2010029S12177 (OLI, 2010) hitting Tubuai, but much stronger track = xr.Dataset({ 'radius_max_wind': ('time', [15., 15, 15, 15, 15, 17, 20, 20]), 'radius_oci': ('time', [202., 202, 202, 202, 202, 202, 202, 202]), 'max_sustained_wind': ('time', [155., 147, 140, 135, 130, 122, 115, 116]), 'central_pressure': ('time', [894., 901, 906, 909, 913, 918, 924, 925]), 'environmental_pressure': ('time', np.full((8,), 1004.0, dtype=np.float64)), 'time_step': ('time', np.full((8,), 3.0, dtype=np.float64)), }, coords={ 'time': np.arange('2010-02-05T09:00', '2010-02-06T09:00', np.timedelta64(3, 'h'), dtype='datetime64[h]'), 'lat': ('time', [-24.33, -25.54, -24.79, -24.05, -23.35, -22.7, -22.07, -21.50]), 'lon': ('time', [-147.27, -148.0, -148.51, -148.95, -149.41, -149.85, -150.27, -150.56]), }, attrs={ 'max_sustained_wind_unit': 'kn', 'central_pressure_unit': 'mb', 'name': 'test', 'sid': '2010029S12177_test', 'orig_event_flag': True, 'data_provider': 'unit_test', 'basin': 'SP', 'id_no': 0, 'category': 4, }) tc_track = TCTracks() tc_track.data = [track] tc_track.equal_timestep(time_step_h=1) res_deg = 10 / (60 * 60) bounds = (-149.54, -23.42, -149.40, -23.33) lat = np.arange(bounds[1] + 0.5 * res_deg, bounds[3], res_deg) lon = np.arange(bounds[0] + 0.5 * res_deg, bounds[2], res_deg) shape = (lat.size, lon.size) lon, lat = [ar.ravel() for ar in np.meshgrid(lon, lat)] centroids = Centroids() centroids.set_lat_lon(lat, lon) centroids.set_dist_coast(signed=True, precomputed=True) wind_haz = TropCyclone() wind_haz.set_from_tracks(tc_track, centroids=centroids) dem_bounds = (bounds[0] - 1, bounds[1] - 1, bounds[2] + 1, bounds[3] + 1) dem_res = 3 / (60 * 60) with tmp_artifical_topo(dem_bounds, dem_res) as topo_path: for slr in [0, 0.5, 1.5]: surge_haz = TCSurgeBathtub.from_tc_winds(wind_haz, topo_path, add_sea_level_rise=slr) inten = surge_haz.intensity.toarray().reshape(shape) fraction = surge_haz.fraction.toarray().reshape(shape) # check valid range and order of magnitude np.testing.assert_array_equal(inten >= 0, True) np.testing.assert_array_equal(inten <= 10, True) np.testing.assert_array_equal((fraction >= 0) & (fraction <= 1), True) np.testing.assert_array_equal(inten[fraction == 0], 0) # check individual known pixel values self.assertAlmostEqual(inten[9, 31], max(-0.391 + slr, 0), places=2) self.assertAlmostEqual(inten[14, 34] - slr, 3.637, places=2)