162162 "SI" : 1005 ,
163163 "WP" : 1005 ,
164164 "SP" : 1004 ,
165+ "AU" : 1004 ,
165166}
166167"""Basin-specific default environmental pressure"""
167168
@@ -1619,6 +1620,118 @@ def from_netcdf(cls, folder_name):
16191620 data .append (track )
16201621 return cls (data )
16211622
1623+ @classmethod
1624+ def from_FAST (cls , folder_name : str ):
1625+ """Create a new TCTracks object from NetCDF files generated by the FAST model, modifying
1626+ the xr.array structure to ensure compatibility with CLIMADA, and calculating the central
1627+ pressure and radius of maximum wind.
1628+
1629+ Model GitHub Repository: https://github.com/linjonathan/tropical_cyclone_risk?
1630+ tab=readme-ov-file
1631+ Model Publication: https://agupubs.onlinelibrary.wiley.com/doi/epdf/10.1029/2023MS003686
1632+
1633+ Parameters:
1634+ ----------
1635+ folder_name : str
1636+ Folder name from where to read files.
1637+ storm_id : int
1638+ Number of the simulated storm
1639+
1640+ Returns:
1641+ -------
1642+ tracks : TCTracks
1643+ TCTracks object with tracks data from the given directory of NetCDF files.
1644+ """
1645+
1646+ LOGGER .info ("Reading %s files." , len (get_file_names (folder_name )))
1647+ data = []
1648+ for file in get_file_names (folder_name ):
1649+ if Path (file ).suffix != ".nc" :
1650+ continue
1651+ with xr .open_dataset (file ) as dataset :
1652+ for year in dataset .year :
1653+ for i in dataset .n_trk :
1654+
1655+ # Select track
1656+ track = dataset .sel (n_trk = i , year = year )
1657+ # chunk dataset at first NaN value
1658+ lon = track .lon_trks .data
1659+ last_valid_index = np .where (np .isfinite (lon ))[0 ][- 1 ]
1660+ track = track .isel (time = slice (0 , last_valid_index + 1 ))
1661+ # Select lat, lon
1662+ lat = track .lat_trks .data
1663+ lon = track .lon_trks .data
1664+ # Convert lon from 0-360 to -180 - 180
1665+ lon = ((lon + 180 ) % 360 ) - 180
1666+ # Convert time to pandas Datetime "yyyy.mm.dd"
1667+ reference_time = (
1668+ f"{ track .tc_years .item ()} -{ int (track .tc_month .item ())} -01"
1669+ )
1670+ time = pd .to_datetime (
1671+ track .time .data , unit = "s" , origin = reference_time
1672+ ).astype ("datetime64[s]" )
1673+ # Define variables
1674+ ms_to_kn = 1.943844
1675+ max_wind_kn = track .vmax_trks .data * ms_to_kn
1676+ env_pressure = BASIN_ENV_PRESSURE [track .tc_basins .data .item ()]
1677+ cen_pres = _estimate_pressure (
1678+ np .full (lat .shape , np .nan ),
1679+ lat ,
1680+ lon ,
1681+ max_wind_kn ,
1682+ )
1683+
1684+ data .append (
1685+ xr .Dataset (
1686+ {
1687+ "time_step" : (
1688+ "time" ,
1689+ np .full (time .shape [0 ], track .time .data [1 ]),
1690+ ),
1691+ "max_sustained_wind" : (
1692+ "time" ,
1693+ track .vmax_trks .data ,
1694+ ),
1695+ "central_pressure" : ("time" , cen_pres ),
1696+ "radius_max_wind" : (
1697+ "time" ,
1698+ estimate_rmw (
1699+ np .full (lat .shape , np .nan ), cen_pres
1700+ ),
1701+ ),
1702+ "environmental_pressure" : (
1703+ "time" ,
1704+ np .full (time .shape [0 ], env_pressure ),
1705+ ),
1706+ "basin" : (
1707+ "time" ,
1708+ np .full (
1709+ time .shape [0 ], track .tc_basins .data .item ()
1710+ ),
1711+ ),
1712+ },
1713+ coords = {
1714+ "time" : ("time" , time ),
1715+ "lat" : ("time" , lat ),
1716+ "lon" : ("time" , lon ),
1717+ },
1718+ attrs = {
1719+ "max_sustained_wind_unit" : "m/s" ,
1720+ "central_pressure_unit" : "hPa" ,
1721+ "name" : f"storm_{ track .n_trk .item ()} " ,
1722+ "sid" : track .n_trk .item (),
1723+ "orig_event_flag" : True ,
1724+ "data_provider" : "FAST" ,
1725+ "id_no" : track .n_trk .item (),
1726+ "category" : set_category (
1727+ max_wind_kn , wind_unit = "kn" , saffir_scale = None
1728+ ),
1729+ },
1730+ )
1731+ )
1732+
1733+ return cls (data )
1734+
16221735 def write_hdf5 (self , file_name , complevel = 5 ):
16231736 """Write TC tracks in NetCDF4-compliant HDF5 format.
16241737
@@ -2665,20 +2778,20 @@ def ibtracs_fit_param(explained, explanatory, year_range=(1980, 2019), order=1):
26652778 return sm_results
26662779
26672780
2668- def ibtracs_track_agency (ds_sel ):
2781+ def ibtracs_track_agency (track ):
26692782 """Get preferred IBTrACS agency for each entry in the dataset.
26702783
26712784 Parameters
26722785 ----------
2673- ds_sel : xarray.Dataset
2786+ track : xarray.Dataset
26742787 Subselection of original IBTrACS NetCDF dataset.
26752788
26762789 Returns
26772790 -------
26782791 agency_pref : list of str
26792792 Names of IBTrACS agencies in order of preference.
26802793 track_agency_ix : xarray.DataArray of ints
2681- For each entry in `ds_sel `, the agency to use, given as an index into `agency_pref`.
2794+ For each entry in `track `, the agency to use, given as an index into `agency_pref`.
26822795 """
26832796 agency_pref = ["wmo" ] + IBTRACS_AGENCIES
26842797 agency_map = {a .encode ("utf-8" ): i for i , a in enumerate (agency_pref )}
@@ -2687,11 +2800,11 @@ def ibtracs_track_agency(ds_sel):
26872800 )
26882801 agency_map [b"" ] = agency_map [b"wmo" ]
26892802 agency_fun = lambda x : agency_map [x ]
2690- if "track_agency" not in ds_sel .data_vars .keys ():
2691- ds_sel ["track_agency" ] = ds_sel ["wmo_agency" ].where (
2692- ds_sel ["wmo_agency" ] != b"" , ds_sel ["usa_agency" ]
2803+ if "track_agency" not in track .data_vars .keys ():
2804+ track ["track_agency" ] = track ["wmo_agency" ].where (
2805+ track ["wmo_agency" ] != b"" , track ["usa_agency" ]
26932806 )
2694- track_agency_ix = xr .apply_ufunc (agency_fun , ds_sel ["track_agency" ], vectorize = True )
2807+ track_agency_ix = xr .apply_ufunc (agency_fun , track ["track_agency" ], vectorize = True )
26952808 return agency_pref , track_agency_ix
26962809
26972810
0 commit comments