Skip to content

Commit e5bbf95

Browse files
optimisation function relatives
1 parent 4159317 commit e5bbf95

File tree

1 file changed

+59
-20
lines changed

1 file changed

+59
-20
lines changed

src/py_eddy_tracker/observations/network.py

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ def sort(self, order=("track", "segment", "time")):
311311
"""
312312
sort observations
313313
314-
:param tuple order: order or sorting. Passed to `np.argsort`
314+
:param tuple order: order or sorting. Passed to :func:`numpy.argsort`
315315
"""
316316

317317
index_order = self.obs.argsort(order=order)
@@ -485,39 +485,78 @@ def segment_relative_order(self, seg_origine):
485485
d[i0:i1] = v
486486
return d
487487

488-
def relative(self, i_obs, order=2, direct=True, only_past=False, only_future=False):
488+
def relatives(self, obs, order=2):
489489
"""
490-
Extract the segments at a certain order from one observation.
490+
Extract the segments at a certain order from multiple observations.
491491
492-
:param list obs: indice of observation for relative computation
492+
:param iterable,int obs: indices of observation for relatives computation. Can be one observation (int) or collection of observations (iterable(int))
493493
:param int order: order of relatives wanted. 0 means only observations in obs, 1 means direct relatives, ...
494494
495495
:return: all segments relatives
496496
:rtype: EddiesObservations
497497
"""
498+
segment = self.segment_track_array
499+
previous_obs, next_obs = self.previous_obs, self.next_obs
498500

499-
d = self.segment_relative_order(self.segment[i_obs])
500-
m = (d <= order) * (d != -1)
501-
return self.extract_with_mask(m)
501+
segments_connexion = dict()
502502

503-
def relatives(self, obs, order=2, direct=True, only_past=False, only_future=False):
504-
"""
505-
Extract the segments at a certain order from multiple observations.
503+
for i_slice, seg, _ in self.iter_on(segment):
504+
if i_slice.start == i_slice.stop:
505+
continue
506506

507-
:param list obs: indices of observation for relatives computation
508-
:param int order: order of relatives wanted. 0 means only observations in obs, 1 means direct relatives, ...
507+
i_p, i_n = previous_obs[i_slice.start], next_obs[i_slice.stop - 1]
508+
p_seg, n_seg = segment[i_p], segment[i_n]
509509

510-
:return: all segments relatives
511-
:rtype: EddiesObservations
512-
"""
510+
# dumping slice into dict
511+
if seg not in segments_connexion:
512+
segments_connexion[seg] = [i_slice, []]
513+
else:
514+
segments_connexion[seg][0] = i_slice
513515

514-
mask = zeros(self.segment.shape, dtype=bool)
515516

516-
for i_obs in obs:
517-
d = self.segment_relative_order(self.segment[i_obs])
518-
mask += (d <= order) * (d != -1)
517+
if i_p != -1:
519518

520-
return self.extract_with_mask(mask)
519+
if p_seg not in segments_connexion:
520+
segments_connexion[p_seg] = [None, []]
521+
522+
# backward
523+
segments_connexion[seg][1].append(p_seg)
524+
segments_connexion[p_seg][1].append(seg)
525+
526+
if i_n != -1:
527+
if n_seg not in segments_connexion:
528+
segments_connexion[n_seg] = [None, []]
529+
530+
# forward
531+
segments_connexion[seg][1].append(n_seg)
532+
segments_connexion[n_seg][1].append(seg)
533+
534+
535+
i_obs = (
536+
[obs]
537+
if not hasattr(obs, "__iter__")
538+
else obs
539+
)
540+
import numpy as np
541+
542+
distance = zeros(segment.size, dtype=np.uint16) - 1
543+
544+
def loop(seg, dist=1):
545+
i_slice, links = segments_connexion[seg]
546+
d = distance[i_slice.start]
547+
548+
if dist < d and dist <= order:
549+
distance[i_slice] = dist
550+
for _seg in links:
551+
loop(_seg, dist + 1)
552+
553+
for indice in i_obs:
554+
loop(segment[indice], 0)
555+
556+
return self.extract_with_mask(distance <= order)
557+
558+
# keep old names, for backward compatibility
559+
relative = relatives
521560

522561
def close_network(self, other, nb_obs_min=10, **kwargs):
523562
"""

0 commit comments

Comments
 (0)