Skip to content

Commit b5c3101

Browse files
corrections for merge request
move particle_candidate in groups add default values for shift_files mistake with get_uv_quad correction still in comments change delta_t to n_days correct whitespaces
1 parent 13177b6 commit b5c3101

File tree

4 files changed

+127
-196
lines changed

4 files changed

+127
-196
lines changed

examples/16_network/pet_follow_particle.py

Lines changed: 3 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from py_eddy_tracker.data import get_demo_path
1818
from py_eddy_tracker.dataset.grid import GridCollection
1919
from py_eddy_tracker.observations.network import NetworkObservations
20+
from py_eddy_tracker.observations.groups import particle_candidate
2021
from py_eddy_tracker.poly import group_obs
2122

2223
start_logger().setLevel("ERROR")
@@ -124,81 +125,6 @@ def update(frame):
124125
ani = VideoAnimation(a.fig, update, frames=arange(20200, 20269, step), interval=200)
125126

126127

127-
# %%
128-
# In which observations are the particle
129-
# --------------------------------------
130-
def advect(x, y, c, t0, delta_t):
131-
"""
132-
Advect particle from t0 to t0 + delta_t, with data cube.
133-
"""
134-
kw = dict(nb_step=6, time_step=86400 / 6)
135-
if delta_t < 0:
136-
kw["backward"] = True
137-
delta_t = -delta_t
138-
p = c.advect(x, y, "u", "v", t_init=t0, **kw)
139-
for _ in range(delta_t):
140-
t, x, y = p.__next__()
141-
return t, x, y
142-
143-
144-
def particle_candidate(x, y, c, eddies, t_start, i_target, pct, **kwargs):
145-
# Obs from initial time
146-
m_start = eddies.time == t_start
147-
e = eddies.extract_with_mask(m_start)
148-
# to be able to get global index
149-
translate_start = where(m_start)[0]
150-
# Identify particle in eddies (only in core)
151-
i_start = e.contains(x, y, intern=True)
152-
m = i_start != -1
153-
x, y, i_start = x[m], y[m], i_start[m]
154-
# Advect
155-
t_end, x, y = advect(x, y, c, t_start, **kwargs)
156-
# eddies at last date
157-
m_end = eddies.time == t_end / 86400
158-
e_end = eddies.extract_with_mask(m_end)
159-
# to be able to get global index
160-
translate_end = where(m_end)[0]
161-
# Id eddies for each alive particle (in core and extern)
162-
i_end = e_end.contains(x, y)
163-
# compute matrix and fill target array
164-
get_matrix(i_start, i_end, translate_start, translate_end, i_target, pct)
165-
166-
167-
@njit(cache=True)
168-
def get_matrix(i_start, i_end, translate_start, translate_end, i_target, pct):
169-
nb_start, nb_end = translate_start.size, translate_end.size
170-
# Matrix which will store count for every couple
171-
count = zeros((nb_start, nb_end), dtype=nb_types.int32)
172-
# Number of particles in each origin observation
173-
ref = zeros(nb_start, dtype=nb_types.int32)
174-
# For each particle
175-
for i in range(i_start.size):
176-
i_end_ = i_end[i]
177-
i_start_ = i_start[i]
178-
if i_end_ != -1:
179-
count[i_start_, i_end_] += 1
180-
ref[i_start_] += 1
181-
for i in range(nb_start):
182-
for j in range(nb_end):
183-
pct_ = count[i, j]
184-
# If there are particles from i to j
185-
if pct_ != 0:
186-
# Get percent
187-
pct_ = pct_ / ref[i] * 100.0
188-
# Get indices in full dataset
189-
i_, j_ = translate_start[i], translate_end[j]
190-
pct_0 = pct[i_, 0]
191-
if pct_ > pct_0:
192-
pct[i_, 1] = pct_0
193-
pct[i_, 0] = pct_
194-
i_target[i_, 1] = i_target[i_, 0]
195-
i_target[i_, 0] = j_
196-
elif pct_ > pct[i_, 1]:
197-
pct[i_, 1] = pct_
198-
i_target[i_, 1] = j_
199-
return i_target, pct
200-
201-
202128
# %%
203129
# Particle advection
204130
# ^^^^^^^^^^^^^^^^^^
@@ -217,12 +143,12 @@ def get_matrix(i_start, i_end, translate_start, translate_end, i_target, pct):
217143
# Forward run
218144
i_target_f, pct_target_f = -ones(shape, dtype="i4"), zeros(shape, dtype="i1")
219145
for t in range(t_start, t_end - dt):
220-
particle_candidate(x0, y0, c, n, t, i_target_f, pct_target_f, delta_t=dt)
146+
particle_candidate(x0, y0, c, n, t, i_target_f, pct_target_f, n_days=dt)
221147

222148
# Backward run
223149
i_target_b, pct_target_b = -ones(shape, dtype="i4"), zeros(shape, dtype="i1")
224150
for t in range(t_start + dt, t_end):
225-
particle_candidate(x0, y0, c, n, t, i_target_b, pct_target_b, delta_t=-dt)
151+
particle_candidate(x0, y0, c, n, t, i_target_b, pct_target_b, n_days=-dt)
226152

227153
# %%
228154
fig = plt.figure(figsize=(10, 10))

src/py_eddy_tracker/dataset/grid.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,7 +2264,7 @@ def from_netcdf_list(cls, filenames, t, x_name, y_name, indexs=None, heigth=None
22642264
new.datasets.append((t, d))
22652265
return new
22662266

2267-
def shift_files(self, t, filename, x_name, y_name, indexs, heigth):
2267+
def shift_files(self, t, filename, x_name, y_name, indexs=None, heigth=None):
22682268
"""Add next file to the list and remove the oldest"""
22692269

22702270
self.datasets = self.datasets[1:]
@@ -2553,8 +2553,8 @@ def get_uv_quad(i0, j0, u, v, m, nb_x=0):
25532553
i1 %= nb_x
25542554
i_max, j_max = m.shape
25552555

2556-
# if i1 >= i_max or j1 >= j_max:
2557-
# return True, nan, nan, nan, nan, nan, nan, nan, nan
2556+
if i1 >= i_max or j1 >= j_max:
2557+
return True, nan, nan, nan, nan, nan, nan, nan, nan
25582558

25592559
if m[i0, j0] or m[i0, j1] or m[i1, j0] or m[i1, j1]:
25602560
return True, nan, nan, nan, nan, nan, nan, nan, nan

src/py_eddy_tracker/observations/groups.py

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import logging
22
from abc import ABC, abstractmethod
33

4-
from numba import njit
5-
from numpy import arange, int32, interp, median, zeros
4+
from numba import njit, types as nb_types
5+
from numpy import arange, int32, interp, median, zeros, where
66

77
from .observation import EddiesObservations
88

@@ -65,6 +65,111 @@ def get_missing_indices(
6565
return indices
6666

6767

68+
69+
def advect(x, y, c, t0, n_days):
70+
"""
71+
Advect particle from t0 to t0 + n_days, with data cube.
72+
73+
:param np.array(float) x: longitude of particles
74+
:param np.array(float) y: latitude of particles
75+
:param `~py_eddy_tracker.dataset.grid.GridCollection` c: GridCollection with speed for particles
76+
:param int t0: julian day of advection start
77+
:param int n_days: number of days to advect
78+
"""
79+
80+
kw = dict(nb_step=6, time_step=86400 / 6)
81+
if n_days < 0:
82+
kw["backward"] = True
83+
n_days = -n_days
84+
p = c.advect(x, y, "u", "v", t_init=t0, **kw)
85+
for _ in range(n_days):
86+
t, x, y = p.__next__()
87+
return t, x, y
88+
89+
90+
def particle_candidate(x, y, c, eddies, t_start, i_target, pct, **kwargs):
91+
"""Select particles within eddies, advect them, return target observation and associated percentages
92+
93+
:param np.array(float) x: longitude of particles
94+
:param np.array(float) y: latitude of particles
95+
:param `~py_eddy_tracker.dataset.grid.GridCollection` c: GridCollection with speed for particles
96+
:param GroupEddiesObservations eddies: GroupEddiesObservations considered
97+
:param int t_start: julian day of the advection
98+
:param np.array(int) i_target: corresponding obs where particles are advected
99+
:param np.array(int) pct: corresponding percentage of avected particles
100+
:params dict kwargs: dict of params given to `advect`
101+
102+
"""
103+
104+
# Obs from initial time
105+
m_start = eddies.time == t_start
106+
107+
e = eddies.extract_with_mask(m_start)
108+
# to be able to get global index
109+
translate_start = where(m_start)[0]
110+
# Identify particle in eddies (only in core)
111+
i_start = e.contains(x, y, intern=True)
112+
m = i_start != -1
113+
114+
x, y, i_start = x[m], y[m], i_start[m]
115+
# Advect
116+
t_end, x, y = advect(x, y, c, t_start, **kwargs)
117+
# eddies at last date
118+
m_end = eddies.time == t_end / 86400
119+
e_end = eddies.extract_with_mask(m_end)
120+
# to be able to get global index
121+
translate_end = where(m_end)[0]
122+
# Id eddies for each alive particle (in core and extern)
123+
i_end = e_end.contains(x, y)
124+
# compute matrix and fill target array
125+
get_matrix(i_start, i_end, translate_start, translate_end, i_target, pct)
126+
127+
128+
@njit(cache=True)
129+
def get_matrix(i_start, i_end, translate_start, translate_end, i_target, pct):
130+
"""Compute target observation and associated percentages
131+
132+
:param np.array(int) i_start: indices of associated contours at starting advection day
133+
:param np.array(int) i_end: indices of associated contours after advection
134+
:param np.array(int) translate_start: corresponding global indices at starting advection day
135+
:param np.array(int) translate_end: corresponding global indices after advection
136+
:param np.array(int) i_target: corresponding obs where particles are advected
137+
:param np.array(int) pct: corresponding percentage of avected particles
138+
"""
139+
140+
nb_start, nb_end = translate_start.size, translate_end.size
141+
# Matrix which will store count for every couple
142+
count = zeros((nb_start, nb_end), dtype=nb_types.int32)
143+
# Number of particles in each origin observation
144+
ref = zeros(nb_start, dtype=nb_types.int32)
145+
# For each particle
146+
for i in range(i_start.size):
147+
i_end_ = i_end[i]
148+
i_start_ = i_start[i]
149+
if i_end_ != -1:
150+
count[i_start_, i_end_] += 1
151+
ref[i_start_] += 1
152+
for i in range(nb_start):
153+
for j in range(nb_end):
154+
pct_ = count[i, j]
155+
# If there are particles from i to j
156+
if pct_ != 0:
157+
# Get percent
158+
pct_ = pct_ / ref[i] * 100.0
159+
# Get indices in full dataset
160+
i_, j_ = translate_start[i], translate_end[j]
161+
pct_0 = pct[i_, 0]
162+
if pct_ > pct_0:
163+
pct[i_, 1] = pct_0
164+
pct[i_, 0] = pct_
165+
i_target[i_, 1] = i_target[i_, 0]
166+
i_target[i_, 0] = j_
167+
elif pct_ > pct[i_, 1]:
168+
pct[i_, 1] = pct_
169+
i_target[i_, 1] = j_
170+
return i_target, pct
171+
172+
68173
class GroupEddiesObservations(EddiesObservations, ABC):
69174
@abstractmethod
70175
def fix_next_previous_obs(self):

0 commit comments

Comments
 (0)