|
32 | 32 | interp, floor
|
33 | 33 | from netCDF4 import Dataset
|
34 | 34 | from .generic import distance_grid, distance
|
35 |
| -from shapely.geometry import Polygon |
36 |
| -from shapely.geos import TopologicalError |
37 | 35 | from . import VAR_DESCR, VAR_DESCR_inv
|
38 | 36 | import logging
|
39 | 37 | from datetime import datetime
|
40 | 38 | from numba import njit, types as numba_types
|
| 39 | +from Polygon import Polygon as Polygon |
| 40 | + |
| 41 | + |
| 42 | +@njit(cache=True, fastmath=True) |
| 43 | +def custom_concat(x, y): |
| 44 | + ''' |
| 45 | + ''' |
| 46 | + nb = x.shape[0] |
| 47 | + a = empty((nb,2)) |
| 48 | + for i in range(nb): |
| 49 | + a[i,0] = x[i] |
| 50 | + a[i,1] = y[i] |
| 51 | + return a |
41 | 52 |
|
42 | 53 |
|
43 | 54 | class EddiesObservations(object):
|
@@ -342,59 +353,59 @@ def propagate(previous_obs, current_obs, obs_to_extend, dead_track, nb_next, mod
|
342 | 353 | next_obs['segment_size'][:] += 1
|
343 | 354 | return next_obs
|
344 | 355 |
|
| 356 | + |
| 357 | + |
| 358 | + |
| 359 | + |
345 | 360 | @staticmethod
|
346 |
| - def cost_function_common_area(records_in, records_out, distance, intern=False): |
347 |
| - """ |
348 |
| - How it's work on x bound ? |
| 361 | + def cost_function_common_area(xy_in, xy_out, distance, intern=False): |
| 362 | + """ How does it work on x bound ? |
349 | 363 | Args:
|
350 |
| - records_in: |
351 |
| - records_out: |
| 364 | + xy_in: |
| 365 | + xy_out: |
352 | 366 | distance:
|
353 | 367 | intern:
|
354 |
| -
|
355 | 368 | Returns:
|
356 | 369 |
|
357 | 370 | """
|
358 |
| - x_name, y_name = ('contour_lon_s', 'contour_lat_s') if intern else ('contour_lon_e', 'contour_lat_e') |
| 371 | + x_name, y_name = (('contour_lon_s', 'contour_lat_s') if intern |
| 372 | + else ('contour_lon_e', 'contour_lat_e')) |
359 | 373 | r_name = 'radius_s' if intern else 'radius_e'
|
360 |
| - nb_records = records_in.shape[0] |
361 |
| - costs = ma.empty(nb_records,dtype='f4') |
362 |
| - tolerance = 0.025 |
363 |
| - x_in, y_in = records_in[x_name], records_in[y_name] |
364 |
| - x_out, y_out = records_out[x_name], records_out[y_name] |
| 374 | + nb_records = xy_in.shape[0] |
| 375 | + x_in, y_in = xy_in[x_name], xy_in[y_name] |
| 376 | + x_out, y_out = xy_out[x_name], xy_out[y_name] |
365 | 377 | x_in_min, y_in_min = x_in.min(axis=1), y_in.min(axis=1)
|
366 | 378 | x_in_max, y_in_max = x_in.max(axis=1), y_in.max(axis=1)
|
367 | 379 | x_out_min, y_out_min = x_out.min(axis=1), y_out.min(axis=1)
|
368 | 380 | x_out_max, y_out_max = x_out.max(axis=1), y_out.max(axis=1)
|
369 |
| - for i_record in range(nb_records): |
370 |
| - if x_in_max[i_record] < x_out_min[i_record] or x_in_min[i_record] > x_out_max[i_record]: |
371 |
| - costs[i_record] = 1 |
| 381 | + costs = ma.empty(nb_records, dtype='f4') |
| 382 | + |
| 383 | + for i in range(nb_records): |
| 384 | + if (x_in_max[i] < x_out_min[i] or |
| 385 | + x_in_min[i] > x_out_max[i]): |
| 386 | + costs[i] = 1 |
372 | 387 | continue
|
373 |
| - if y_in_max[i_record] < y_out_min[i_record] or y_in_min[i_record] > y_out_max[i_record]: |
374 |
| - costs[i_record] = 1 |
| 388 | + if (y_in_max[i] < y_out_min[i] or |
| 389 | + y_in_min[i] > y_out_max[i]): |
| 390 | + costs[i] = 1 |
375 | 391 | continue
|
376 |
| - poly_in = Polygon(concatenate(((x_in[i_record],), (y_in[i_record],))).T) |
377 |
| - poly_out = Polygon(concatenate(((x_out[i_record],),(y_out[i_record],))).T) |
378 |
| - if not poly_in.is_valid: |
379 |
| - poly_in = poly_in.simplify(tolerance=tolerance) |
380 |
| - if not poly_in.is_valid: |
381 |
| - logging.warning('Need to simplify polygon in for a second time') |
382 |
| - poly_in = poly_in.buffer(0) |
383 |
| - if not poly_out.is_valid: |
384 |
| - poly_out = poly_out.simplify(tolerance=tolerance) |
385 |
| - if not poly_out.is_valid: |
386 |
| - logging.warning('Need to simplify polygon out for a second time') |
387 |
| - poly_out = poly_out.buffer(0) |
388 |
| - try: |
389 |
| - costs[i_record] = 1 - poly_in.intersection(poly_out).area / poly_in.area |
390 |
| - except TopologicalError: |
391 |
| - costs[i_record] = 1 |
| 392 | + |
| 393 | + x_in_, x_out_ = x_in[i], x_out[i] |
| 394 | + p_in = Polygon(custom_concat(x_in_, y_in[i])) |
| 395 | + if abs(x_in_[0] - x_out_[0]) > 180: |
| 396 | + x_out_ = (x_out[i] - (x_in_[0] - 180)) % 360 + x_in_[0] - 180 |
| 397 | + p_out = Polygon(custom_concat(x_out_, y_out[i])) |
| 398 | + costs[i] = 1 - (p_in & p_out).area() / min(p_in.area(), p_out.area()) |
392 | 399 | costs.mask = costs == 1
|
393 | 400 | return costs
|
394 | 401 |
|
| 402 | + |
| 403 | + |
| 404 | + |
395 | 405 | def mask_function(self, other, distance):
|
396 | 406 | return distance < 125
|
397 | 407 |
|
| 408 | + |
398 | 409 | @staticmethod
|
399 | 410 | def cost_function(records_in, records_out, distance):
|
400 | 411 | cost = ((records_in['amplitude'] - records_out['amplitude']
|
@@ -577,13 +588,13 @@ def solve_first(cost, multiple_link=False):
|
577 | 588 | if hasattr(cost_reduce[i,j], 'mask'):
|
578 | 589 | continue
|
579 | 590 | links_resolve += 1
|
580 |
| - # Set to False all link |
| 591 | + # Set all links to False |
581 | 592 | mask[i_self_keep[i]] = False
|
582 | 593 | cost_reduce.mask[i] = True
|
583 | 594 | if not multiple_link:
|
584 | 595 | mask[:, i_other_keep[j]] = False
|
585 | 596 | cost_reduce.mask[:, j] = True
|
586 |
| - # we active only this link |
| 597 | + # We activate this link only |
587 | 598 | mask[i_self_keep[i], i_other_keep[j]] = True
|
588 | 599 |
|
589 | 600 | logging.debug('%d links resolve', links_resolve)
|
@@ -747,7 +758,7 @@ def shifted_ellipsoid_degrees_mask(lon0, lat0, lon1, lat1, minor=1.5, major=1.5)
|
747 | 758 | # Focal
|
748 | 759 | f_right = lon0
|
749 | 760 | f_left = f_right - (c - minor)
|
750 |
| - # Ellips center |
| 761 | + # Ellipse center |
751 | 762 | x_c = (f_left + f_right) * .5
|
752 | 763 |
|
753 | 764 | nb_0, nb_1 = lat0.shape[0], lat1.shape[0]
|
|
0 commit comments