Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 73 additions & 78 deletions climada/hazard/tc_tracks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1944,86 +1944,81 @@ def from_FAST(cls, folder_name: str):
if Path(file).suffix != ".nc":
continue
with xr.open_dataset(file) as dataset:
for year in dataset.year:
for i in dataset.n_trk:

# Select track
track = dataset.sel(n_trk=i, year=year)
# chunk dataset at first NaN value
lon = track.lon_trks.data
last_valid_index = np.where(np.isfinite(lon))[0][-1]
track = track.isel(time=slice(0, last_valid_index + 1))
# Select lat, lon
lat = track.lat_trks.data
lon = track.lon_trks.data
# Convert lon from 0-360 to -180 - 180
lon = ((lon + 180) % 360) - 180
# Convert time to pandas Datetime "yyyy.mm.dd"
reference_time = (
f"{track.tc_years.item()}-{int(track.tc_month.item())}-01"
)
time = pd.to_datetime(
track.time.data, unit="s", origin=reference_time
).astype("datetime64[s]")
# Define variables
ms_to_kn = 1.943844
max_wind_kn = track.vmax_trks.data * ms_to_kn
env_pressure = BASIN_ENV_PRESSURE[track.tc_basins.data.item()]
cen_pres = _estimate_pressure(
np.full(lat.shape, np.nan),
lat,
lon,
max_wind_kn,
)
for i in dataset.n_trk:

# Select track
track = dataset.sel(n_trk=i)
# chunk dataset at first NaN value
lon = track.lon_trks.data
last_valid_index = np.where(np.isfinite(lon))[0][-1]
track = track.isel(time=slice(0, last_valid_index + 1))
# Select lat, lon
lat = track.lat_trks.data
lon = track.lon_trks.data
# Convert lon from 0-360 to -180 - 180
lon = ((lon + 180) % 360) - 180
# Convert time to pandas Datetime "yyyy.mm.dd"
reference_time = (
f"{track.tc_years.item()}-{int(track.tc_month.item())}-01"
)
time = pd.to_datetime(
track.time.data, unit="s", origin=reference_time
).astype("datetime64[s]")
# Define variables
ms_to_kn = 1.943844
max_wind_kn = track.vmax_trks.data * ms_to_kn
env_pressure = BASIN_ENV_PRESSURE[track.tc_basins.data.item()]
cen_pres = _estimate_pressure(
np.full(lat.shape, np.nan),
lat,
lon,
max_wind_kn,
)

data.append(
xr.Dataset(
{
"time_step": (
"time",
np.full(time.shape[0], track.time.data[1]),
),
"max_sustained_wind": (
"time",
track.vmax_trks.data,
),
"central_pressure": ("time", cen_pres),
"radius_max_wind": (
"time",
estimate_rmw(
np.full(lat.shape, np.nan), cen_pres
),
),
"environmental_pressure": (
"time",
np.full(time.shape[0], env_pressure),
),
"basin": (
"time",
np.full(
time.shape[0], track.tc_basins.data.item()
),
),
},
coords={
"time": ("time", time),
"lat": ("time", lat),
"lon": ("time", lon),
},
attrs={
"max_sustained_wind_unit": "m/s",
"central_pressure_unit": "hPa",
"name": f"storm_{track.n_trk.item()}",
"sid": track.n_trk.item(),
"orig_event_flag": True,
"data_provider": "FAST",
"id_no": track.n_trk.item(),
"category": set_category(
max_wind_kn, wind_unit="kn", saffir_scale=None
),
},
)
data.append(
xr.Dataset(
{
"time_step": (
"time",
np.full(time.shape[0], track.time.data[1]),
),
"max_sustained_wind": (
"time",
track.vmax_trks.data,
),
"central_pressure": ("time", cen_pres),
"radius_max_wind": (
"time",
estimate_rmw(np.full(lat.shape, np.nan), cen_pres),
),
"environmental_pressure": (
"time",
np.full(time.shape[0], env_pressure),
),
"basin": (
"time",
np.full(time.shape[0], track.tc_basins.data.item()),
),
},
coords={
"time": ("time", time),
"lat": ("time", lat),
"lon": ("time", lon),
},
attrs={
"max_sustained_wind_unit": "m/s",
"central_pressure_unit": "hPa",
"name": f"storm_{track.n_trk.item()}",
"sid": track.n_trk.item(),
"orig_event_flag": True,
"data_provider": "FAST",
"id_no": track.n_trk.item(),
"category": set_category(
max_wind_kn, wind_unit="kn", saffir_scale=None
),
},
)
)

return cls(data)

Expand Down
Binary file modified climada/hazard/test/data/FAST_test_tracks.nc
Binary file not shown.
9 changes: 7 additions & 2 deletions climada/hazard/test/test_tc_tracks.py
Original file line number Diff line number Diff line change
Expand Up @@ -660,8 +660,13 @@ def test_from_simulations_storm(self):
self.assertEqual(len(tc_track.data), 0)

def test_from_FAST(self):
"""test the correct import of netcdf files from FAST model and the conversion to a
different xr.array structure compatible with CLIMADA."""
"""Test the correct import of netcdf files from FAST model and the conversion to a
different xr.array structure compatible with CLIMADA.

The test fixture contains 5 tracks across 2 years. The regression check
``len(tc_track.data) == 5`` ensures that tracks are not multiplied by the
``year`` dimension (the bug would produce 5 × 2 = 10 tracks instead).
"""

tc_track = tc.TCTracks.from_FAST(TEST_TRACK_FAST)

Expand Down
Loading