@@ -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