Skip to content

Commit fa15c83

Browse files
Merge branch 'develop'
# Conflicts: # climada/_version.py # setup.py
2 parents a66c72b + 27b9e80 commit fa15c83

File tree

9 files changed

+309
-210
lines changed

9 files changed

+309
-210
lines changed

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,25 @@ Release date: 2024-02-14
66

77
### Dependency Changes
88

9+
### Added
10+
11+
### Changed
12+
13+
### Fixed
14+
15+
- Fix `util.coordinates.latlon_bounds` for cases where the specified buffer is very large so that the bounds cover more than the full longitudinal range `[-180, 180]` [#839](https://github.com/CLIMADA-project/climada_python/pull/839)
16+
- Fix `climada.hazard.trop_cyclone` for TC tracks crossing the antimeridian [#839](https://github.com/CLIMADA-project/climada_python/pull/839)
17+
18+
### Deprecated
19+
20+
### Removed
21+
22+
## 4.1.0
23+
24+
Release date: 2024-02-14
25+
26+
### Dependency Changes
27+
928
Added:
1029

1130
- `pyproj` >=3.5

climada/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '4.1.0'
1+
__version__ = '4.1.1-dev'

climada/hazard/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ def year_month_day_accessor(
840840
return array.dt.strftime("%Y-%m-%d").values
841841

842842
# Handle access errors
843-
except (ValueError, TypeError) as err:
843+
except (ValueError, TypeError, AttributeError) as err:
844844
if strict:
845845
raise err
846846

climada/hazard/test/test_trop_cyclone.py

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,25 @@ def test_set_one_pass(self):
127127
msk = (intensity > 0)
128128
np.testing.assert_array_equal(windfield_norms[msk], intensity[msk])
129129

130+
def test_cross_antimeridian(self):
131+
# Two locations on the island Taveuni (Fiji), one west and one east of 180° longitude.
132+
# We list the second point twice, with different lon-normalization:
133+
cen = Centroids.from_lat_lon([-16.95, -16.8, -16.8], [179.9, 180.1, -179.9])
134+
cen.set_dist_coast(precomputed=True)
135+
136+
# Cyclone YASA (2020) passed directly over Fiji
137+
tr = TCTracks.from_ibtracs_netcdf(storm_id=["2020346S13168"])
138+
139+
inten = TropCyclone.from_tracks(tr, centroids=cen).intensity.toarray()[0, :]
140+
141+
# Centroids 1 and 2 are identical, they just use a different normalization for lon. This
142+
# should not affect the result at all:
143+
self.assertEqual(inten[1], inten[2])
144+
145+
# All locations should be clearly affected by strong winds of appx. 40 m/s. The exact
146+
# values are not so important for this test:
147+
np.testing.assert_allclose(inten, 40, atol=10)
148+
130149
def test_windfield_models(self):
131150
"""Test _tc_from_track function with different wind field models."""
132151
intensity_idx = [0, 1, 2, 3, 80, 100, 120, 200, 220, 250, 260, 295]
@@ -256,31 +275,54 @@ class TestWindfieldHelpers(unittest.TestCase):
256275

257276
def test_get_close_centroids_pass(self):
258277
"""Test get_close_centroids function."""
259-
t_lat = np.array([0, -0.5, 0])
260-
t_lon = np.array([0.9, 2, 3.2])
278+
si_track = xr.Dataset({
279+
"lat": ("time", np.array([0, -0.5, 0])),
280+
"lon": ("time", np.array([0.9, 2, 3.2])),
281+
}, attrs={"mid_lon": 0.0})
261282
centroids = np.array([
262283
[0, -0.2], [0, 0.9], [-1.1, 1.2], [1, 2.1], [0, 4.3], [0.6, 3.8], [0.9, 4.1],
263284
])
264-
test_mask = np.array([[False, True, False, False, False, False, False],
265-
[False, False, True, False, False, False, False],
266-
[False, False, False, False, False, True, False]])
267-
mask = get_close_centroids(t_lat, t_lon, centroids, 112.0)
268-
np.testing.assert_equal(mask, test_mask)
285+
centroids_close, mask_close, mask_close_alongtrack = (
286+
get_close_centroids(si_track, centroids, 112.0)
287+
)
288+
self.assertEqual(centroids_close.shape[0], mask_close.sum())
289+
self.assertEqual(mask_close_alongtrack.shape[0], si_track.sizes["time"])
290+
self.assertEqual(mask_close_alongtrack.shape[1], centroids_close.shape[0])
291+
np.testing.assert_equal(mask_close_alongtrack.any(axis=0), True)
292+
np.testing.assert_equal(mask_close, np.array(
293+
[False, True, True, False, False, True, False]
294+
))
295+
np.testing.assert_equal(mask_close_alongtrack, np.array([
296+
[True, False, False],
297+
[False, True, False],
298+
[False, False, True],
299+
]))
300+
np.testing.assert_equal(centroids_close, centroids[mask_close])
269301

270302
# example where antimeridian is crossed
271-
t_lat = np.linspace(-10, 10, 11)
272-
t_lon = np.linspace(170, 200, 11)
273-
t_lon[t_lon > 180] -= 360
303+
si_track = xr.Dataset({
304+
"lat": ("time", np.linspace(-10, 10, 11)),
305+
"lon": ("time", np.linspace(170, 200, 11)),
306+
}, attrs={"mid_lon": 180.0})
274307
centroids = np.array([[-11, 169], [-7, 176], [4, -170], [10, 170], [-10, -160]])
275-
test_mask = np.array([True, True, True, False, False])
276-
mask = get_close_centroids(t_lat, t_lon, centroids, 600.0)
277-
np.testing.assert_equal(mask.any(axis=0), test_mask)
308+
centroids_close, mask_close, mask_close_alongtrack = (
309+
get_close_centroids(si_track, centroids, 600.0)
310+
)
311+
self.assertEqual(centroids_close.shape[0], mask_close.sum())
312+
self.assertEqual(mask_close_alongtrack.shape[0], si_track.sizes["time"])
313+
self.assertEqual(mask_close_alongtrack.shape[1], centroids_close.shape[0])
314+
np.testing.assert_equal(mask_close_alongtrack.any(axis=0), True)
315+
np.testing.assert_equal(mask_close, np.array([True, True, True, False, False]))
316+
np.testing.assert_equal(centroids_close, np.array([
317+
# the longitudinal coordinate of the third centroid is normalized
318+
[-11, 169], [-7, 176], [4, 190],
319+
]))
278320

279321
def test_B_holland_1980_pass(self):
280322
"""Test _B_holland_1980 function."""
281323
si_track = xr.Dataset({
282-
"env": ("time", MBAR_TO_PA * np.array([1010, 1010])),
283-
"cen": ("time", MBAR_TO_PA * np.array([995, 980])),
324+
"env": ("time", MBAR_TO_PA * np.array([1010, 1010])),
325+
"cen": ("time", MBAR_TO_PA * np.array([995, 980])),
284326
"vgrad": ("time", [35, 40]),
285327
})
286328
_B_holland_1980(si_track)

0 commit comments

Comments
 (0)