@@ -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