Skip to content

Commit 1f5863a

Browse files
committed
Manage wrapping in poly_index
1 parent ee83f00 commit 1f5863a

File tree

2 files changed

+113
-58
lines changed

2 files changed

+113
-58
lines changed

src/py_eddy_tracker/observations/observation.py

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,10 @@
6565
convexs,
6666
create_vertice,
6767
get_pixel_in_regular,
68+
insidepoly,
69+
poly_indexs,
6870
reduce_size,
6971
vertice_overlap,
70-
winding_number_poly,
7172
)
7273

7374
logger = logging.getLogger("pet")
@@ -2062,6 +2063,7 @@ def inside(self, x, y, intern=False):
20622063
:rtype: array[bool]
20632064
"""
20642065
xname, yname = self.intern(intern)
2066+
# FIXME: wrapping
20652067
return insidepoly(x, y, self[xname], self[yname])
20662068

20672069
def grid_count(self, bins, intern=False, center=False, filter=slice(None)):
@@ -2330,62 +2332,6 @@ def grid_count_pixel_in(
23302332
grid_count_(grid, i, j)
23312333

23322334

2333-
@njit(cache=True)
2334-
def poly_indexs(x_p, y_p, x_c, y_c):
2335-
"""
2336-
index of contour for each postion inside a contour, -1 in case of no contour
2337-
2338-
:param array x_p: longitude to test
2339-
:param array y_p: latitude to test
2340-
:param array x_c: longitude of contours
2341-
:param array y_c: latitude of contours
2342-
"""
2343-
nb_p = x_p.shape[0]
2344-
nb_c = x_c.shape[0]
2345-
indexs = -ones(nb_p, dtype=numba_types.int32)
2346-
for i in range(nb_c):
2347-
x_, y_ = reduce_size(x_c[i], y_c[i])
2348-
x_c_min, y_c_min = x_.min(), y_.min()
2349-
x_c_max, y_c_max = x_.max(), y_.max()
2350-
v = create_vertice(x_, y_)
2351-
for j in range(nb_p):
2352-
if indexs[j] != -1:
2353-
continue
2354-
x, y = x_p[j], y_p[j]
2355-
if x > x_c_min and x < x_c_max and y > y_c_min and y < y_c_max:
2356-
if winding_number_poly(x, y, v) != 0:
2357-
indexs[j] = i
2358-
return indexs
2359-
2360-
2361-
@njit(cache=True)
2362-
def insidepoly(x_p, y_p, x_c, y_c):
2363-
"""
2364-
True for each postion inside a contour
2365-
2366-
:param array x_p: longitude to test
2367-
:param array y_p: latitude to test
2368-
:param array x_c: longitude of contours
2369-
:param array y_c: latitude of contours
2370-
"""
2371-
nb_p = x_p.shape[0]
2372-
nb_c = x_c.shape[0]
2373-
flag = zeros(nb_p, dtype=numba_types.bool_)
2374-
for i in range(nb_c):
2375-
x_, y_ = reduce_size(x_c[i], y_c[i])
2376-
x_c_min, y_c_min = x_.min(), y_.min()
2377-
x_c_max, y_c_max = x_.max(), y_.max()
2378-
v = create_vertice(x_, y_)
2379-
for j in range(nb_p):
2380-
if flag[j]:
2381-
continue
2382-
x, y = x_p[j], y_p[j]
2383-
if x > x_c_min and x < x_c_max and y > y_c_min and y < y_c_max:
2384-
if winding_number_poly(x, y, v) != 0:
2385-
flag[j] = True
2386-
return flag
2387-
2388-
23892335
@njit(cache=True)
23902336
def grid_box_stat(x_c, y_c, grid, mask, x, y, value, circular=False, method=50):
23912337
"""

src/py_eddy_tracker/poly.py

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77

88
from numba import njit, prange
99
from numba import types as numba_types
10-
from numpy import arctan, array, concatenate, empty, nan, ones, pi, where
10+
from numpy import arctan, array, concatenate, empty, nan, ones, pi, where, zeros
1111
from numpy.linalg import lstsq
1212
from Polygon import Polygon
1313

14+
from .generic import build_index
15+
1416

1517
@njit(cache=True)
1618
def is_left(
@@ -788,3 +790,110 @@ def reduce_size(x, y):
788790
# In case of virtual obs all value could be fill with same value, to avoid empty array
789791
i = max(3, i)
790792
return x[:i], y[:i]
793+
794+
795+
@njit(cache=True)
796+
def group_obs(x, y, step, nb_x):
797+
"""Get index k_box for each box, and indexes to sort"""
798+
nb = x.size
799+
i = empty(nb, dtype=numba_types.uint32)
800+
for k in range(nb):
801+
i[k] = box_index(x[k], y[k], step, nb_x)
802+
return i, i.argsort()
803+
804+
805+
@njit(cache=True)
806+
def box_index(x, y, step, nb_x):
807+
"""Return k_box index for each value"""
808+
return numba_types.uint32((x % 360) // step + nb_x * ((y + 90) // step))
809+
810+
811+
@njit(cache=True)
812+
def box_indexes(x, y, step):
813+
"""Return i_box,j_box index for each value"""
814+
return numba_types.uint32((x % 360) // step), numba_types.uint32((y + 90) // step)
815+
816+
817+
@njit(cache=True)
818+
def poly_indexs(x_p, y_p, x_c, y_c):
819+
"""
820+
Index of contour for each postion inside a contour, -1 in case of no contour
821+
822+
:param array x_p: longitude to test (must be define, no nan)
823+
:param array y_p: latitude to test (must be define, no nan)
824+
:param array x_c: longitude of contours
825+
:param array y_c: latitude of contours
826+
"""
827+
i, i_order = group_obs(x_p, y_p, 1, 360)
828+
nb_p = x_p.shape[0]
829+
nb_c = x_c.shape[0]
830+
indexs = -ones(nb_p, dtype=numba_types.int32)
831+
# Adress table to get particle bloc
832+
start_index, end_index, i_first = build_index(i[i_order])
833+
nb_bloc = end_index.size
834+
for i_contour in range(nb_c):
835+
# Build vertice and box included contour
836+
x_, y_ = reduce_size(x_c[i_contour], y_c[i_contour])
837+
x_c_min, y_c_min = x_.min(), y_.min()
838+
x_c_max, y_c_max = x_.max(), y_.max()
839+
v = create_vertice(x_, y_)
840+
i0, j0 = box_indexes(x_c_min, y_c_min, 1)
841+
i1, j1 = box_indexes(x_c_max, y_c_max, 1)
842+
# i0 could be greater than i1, (x_c is always continious) so you could have a contour over bound
843+
if i0 > i1:
844+
i1 += 360
845+
for i_x in range(i0, i1 + 1):
846+
# we force i_x in 0 360 range
847+
i_x %= 360
848+
for i_y in range(j0, j1 + 1):
849+
# Get box indices
850+
i_box = i_x + 360 * i_y - i_first
851+
# Indice must be in table range
852+
if i_box < 0 or i_box >= nb_bloc:
853+
continue
854+
for i_p_ordered in range(start_index[i_box], end_index[i_box]):
855+
i_p = i_order[i_p_ordered]
856+
if indexs[i_p] != -1:
857+
continue
858+
y = y_p[i_p]
859+
if y > y_c_max:
860+
continue
861+
if y < y_c_min:
862+
continue
863+
x = (x_p[i_p] - x_c_min + 180) % 360 + x_c_min - 180
864+
if x > x_c_max:
865+
continue
866+
if x < x_c_min:
867+
continue
868+
if winding_number_poly(x, y, v) != 0:
869+
indexs[i_p] = i_contour
870+
return indexs
871+
872+
873+
@njit(cache=True)
874+
def insidepoly(x_p, y_p, x_c, y_c):
875+
"""
876+
True for each postion inside a contour
877+
878+
:param array x_p: longitude to test
879+
:param array y_p: latitude to test
880+
:param array x_c: longitude of contours
881+
:param array y_c: latitude of contours
882+
"""
883+
# TODO must be optimize like poly_index
884+
nb_p = x_p.shape[0]
885+
nb_c = x_c.shape[0]
886+
flag = zeros(nb_p, dtype=numba_types.bool_)
887+
for i in range(nb_c):
888+
x_, y_ = reduce_size(x_c[i], y_c[i])
889+
x_c_min, y_c_min = x_.min(), y_.min()
890+
x_c_max, y_c_max = x_.max(), y_.max()
891+
v = create_vertice(x_, y_)
892+
for j in range(nb_p):
893+
if flag[j]:
894+
continue
895+
x, y = x_p[j], y_p[j]
896+
if x > x_c_min and x < x_c_max and y > y_c_min and y < y_c_max:
897+
if winding_number_poly(x, y, v) != 0:
898+
flag[j] = True
899+
return flag

0 commit comments

Comments
 (0)