Skip to content

Commit ca51754

Browse files
committed
Add a loess smother
1 parent b8d066d commit ca51754

File tree

1 file changed

+58
-5
lines changed

1 file changed

+58
-5
lines changed

src/py_eddy_tracker/observations/tracking.py

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -223,18 +223,29 @@ def extract_ids(self, tracks):
223223

224224
def extract_with_length(self, bounds):
225225
b0, b1 = bounds
226-
if b0 >= 0 and b1 >=0:
226+
if b0 >= 0 and b1 >= 0:
227227
track_mask = (self.nb_obs_by_track >= b0) * (self.nb_obs_by_track <= b1)
228228
elif b0 < 0 and b1 >= 0:
229229
track_mask = self.nb_obs_by_track <= b1
230230
elif b0 >= 0 and b1 < 0:
231231
track_mask = self.nb_obs_by_track > b0
232232
else:
233-
logging.warning('No valid value for bounds')
234-
raise Exception('One bounds must be positiv')
233+
logging.warning("No valid value for bounds")
234+
raise Exception("One bounds must be positiv")
235235
return self.__extract_with_mask(track_mask.repeat(self.nb_obs_by_track))
236236

237-
def __extract_with_mask(self, mask, full_path=False, remove_incomplete=False, compress_id=False):
237+
def loess_filter(self, window, xfield, yfield, inplace=True):
238+
track = self.obs["track"]
239+
x = self.obs[xfield]
240+
y = self.obs[yfield]
241+
window = window
242+
result = track_loess_filter(window, x, y, track)
243+
if inplace:
244+
self.obs[yfield] = result
245+
246+
def __extract_with_mask(
247+
self, mask, full_path=False, remove_incomplete=False, compress_id=False
248+
):
238249
"""
239250
Extract a subset of observations
240251
Args:
@@ -297,4 +308,46 @@ def compute_index(tracks, index, number):
297308
@njit(cache=True)
298309
def compute_mask_from_id(tracks, first_index, number_of_obs, mask):
299310
for track in tracks:
300-
mask[first_index[track]:first_index[track] + number_of_obs[track]] = True
311+
mask[first_index[track] : first_index[track] + number_of_obs[track]] = True
312+
313+
314+
@njit(cache=True)
315+
def track_loess_filter(window, x, y, track):
316+
"""
317+
Apply a loess filter on y field
318+
Args:
319+
window: parameter of smoother
320+
x: must be growing for each track but could be irregular
321+
y: field to smooth
322+
track: field which allow to separate path
323+
324+
Returns:
325+
326+
"""
327+
nb = y.shape[0]
328+
last = nb - 1
329+
y_new = empty(y.shape, dtype=y.dtype)
330+
for i in range(nb):
331+
cur_track = track[i]
332+
y_sum = y[i]
333+
w_sum = 1
334+
if i != 0:
335+
i_previous = i - 1
336+
dx = x[i] - x[i_previous]
337+
while dx < window and i_previous != 0 and cur_track == track[i_previous]:
338+
w = (1 - (dx / window) ** 3) ** 3
339+
y_sum += y[i_previous] * w
340+
w_sum += w
341+
i_previous -= 1
342+
dx = x[i] - x[i_previous]
343+
if i != last:
344+
i_next = i + 1
345+
dx = x[i_next] - x[i]
346+
while dx < window and i_next != last and cur_track == track[i_next]:
347+
w = (1 - (dx / window) ** 3) ** 3
348+
y_sum += y[i_next] * w
349+
w_sum += w
350+
i_next += 1
351+
dx = x[i_next] - x[i]
352+
y_new[i] = y_sum / w_sum
353+
return y_new

0 commit comments

Comments
 (0)