From c920e2315284ac0ae7be2e64d940e1c8e87e6e5c Mon Sep 17 00:00:00 2001 From: "Pui Man (Mannie) Kam" Date: Thu, 3 Nov 2022 15:44:52 +0100 Subject: [PATCH] Feature/init tc tracks (#559) * update __init__ in tc_tracks.py * update tc_tracks.py * update tc_tracks.py * remove trailing white space * Update usage of TCTracks.__init__ * Update TCTracks.__init__ docstring Add information on `data` parameter. Co-authored-by: emanuel-schmid Co-authored-by: Lukas Riedel <34276446+peanutfun@users.noreply.github.com> --- climada/hazard/tc_tracks.py | 59 +++++++++------------ climada/hazard/test/test_tc_tracks_synth.py | 3 +- 2 files changed, 25 insertions(+), 37 deletions(-) diff --git a/climada/hazard/tc_tracks.py b/climada/hazard/tc_tracks.py index 18780284c..0cc3c98e5 100644 --- a/climada/hazard/tc_tracks.py +++ b/climada/hazard/tc_tracks.py @@ -26,6 +26,7 @@ import datetime as dt import itertools import logging +from typing import Optional, List import pathlib import re import shutil @@ -36,6 +37,7 @@ import cartopy.crs as ccrs import cftime import geopandas as gpd +import pathos import matplotlib.cm as cm_mp from matplotlib.collections import LineCollection from matplotlib.colors import BoundaryNorm, ListedColormap @@ -188,20 +190,24 @@ class TCTracks(): - on_land (bool for each track position) - dist_since_lf (in km) """ - def __init__(self, pool=None): + def __init__(self, + data: Optional[List[xr.Dataset]] = None, + pool: Optional[pathos.multiprocessing.ProcessPool] = None): """Create new (empty) TCTracks instance. Parameters ---------- - pool : pathos.pool, optional + data : list of xarray.Dataset, optional + List of tropical cyclone tracks, each stored as single xarray Dataset. + See the Attributes for a full description of the required Dataset variables + and attributes. Defaults to an empty list. + pool : pathos.pools, optional Pool that will be used for parallel computation when applicable. Default: None """ - self.data = list() + self.data = data if data is not None else list() + self.pool = pool if pool: - self.pool = pool LOGGER.debug('Using %s CPUs.', self.pool.ncpus) - else: - self.pool = None def append(self, tracks): """Append tracks to current. @@ -308,8 +314,7 @@ def tracks_in_exp(self, exposure, buffer=1.0): tc_tracks_lines = self.to_geodataframe().buffer(distance=buffer) select_tracks = tc_tracks_lines.intersects(exp_buffer) tracks_in_exp = [track for j, track in enumerate(self.data) if select_tracks[j]] - filtered_tracks = TCTracks() - filtered_tracks.append(tracks_in_exp) + filtered_tracks = TCTracks(tracks_in_exp) return filtered_tracks @@ -705,9 +710,7 @@ def from_ibtracs_netcdf(cls, provider=None, rescale_windspeeds=True, storm_id=No # If all tracks have been discarded in the loop due to the basin filters: LOGGER.info('There were no tracks left in the specified basin ' 'after discarding invalid track positions.') - tr = cls() - tr.data = all_tracks - return tr + return cls(all_tracks) def read_processed_ibtracs_csv(self, *args, **kwargs): """This function is deprecated, use TCTracks.from_processed_ibtracs_csv instead.""" @@ -729,9 +732,7 @@ def from_processed_ibtracs_csv(cls, file_names): tracks : TCTracks TCTracks with data from the processed ibtracs CSV file. """ - tr = cls() - tr.data = [_read_ibtracs_csv_single(f) for f in get_file_names(file_names)] - return tr + return cls([_read_ibtracs_csv_single(f) for f in get_file_names(file_names)]) def read_simulations_emanuel(self, *args, **kwargs): """This function is deprecated, use TCTracks.from_simulations_emanuel instead.""" @@ -756,13 +757,11 @@ def from_simulations_emanuel(cls, file_names, hemisphere=None): tracks : TCTracks TCTracks with data from Kerry Emanuel's simulations. """ - tr = cls() - tr.data = [] + data = [] for path in get_file_names(file_names): - tr.data.extend(_read_file_emanuel( - path, hemisphere=hemisphere, - rmw_corr=Path(path).name in EMANUEL_RMW_CORR_FILES)) - return tr + data.extend(_read_file_emanuel(path, hemisphere=hemisphere, + rmw_corr=Path(path).name in EMANUEL_RMW_CORR_FILES)) + return cls(data) def read_one_gettelman(self, nc_data, i_track): """This function is deprecated, use TCTracks.from_gettelman instead.""" @@ -786,9 +785,7 @@ def from_gettelman(cls, path): """ nc_data = nc.Dataset(path) nstorms = nc_data.dimensions['storm'].size - tr = cls() - tr.data = [_read_one_gettelman(nc_data, i) for i in range(nstorms)] - return tr + return cls([_read_one_gettelman(nc_data, i) for i in range(nstorms)]) def read_simulations_chaz(self, *args, **kwargs): """This function is deprecated, use TCTracks.from_simulations_chaz instead.""" @@ -916,9 +913,7 @@ def from_simulations_chaz(cls, file_names, year_range=None, ensemble_nums=None): })) if last_perc != 100: LOGGER.info("Progress: 100%") - tr = cls() - tr.data = data - return tr + return cls(data) def read_simulations_storm(self, *args, **kwargs): """This function is deprecated, use TCTracks.from_simulations_storm instead.""" @@ -1042,9 +1037,7 @@ def from_simulations_storm(cls, path, years=None): })) if last_perc != 100: LOGGER.info("Progress: 100%") - tr = cls() - tr.data = data - return tr + return cls(data) def equal_timestep(self, time_step_h=1, land_params=False, pool=None): """Generate interpolated track values to time steps of time_step_h. @@ -1292,9 +1285,7 @@ def from_netcdf(cls, folder_name): del track.attrs['basin'] track['basin'] = ("time", np.full(track.time.size, basin, dtype="