@@ -2038,30 +2038,42 @@ def _get_event_segment_ids(self, raw_event_data, masks, spec):
20382038 # consistency check for monotone increasing time stamps
20392039 # - Use logical comparator (instead of np.diff) to avoid unsigned dtype issues.
20402040 # - Only consider handled/known event types.
2041- mask_handled = np .any ([mask for mask in masks .values ()], axis = 0 )
2042- jump_ids_handled = (
2043- np .where (
2044- raw_event_data ["timestamp" ][mask_handled ][1 :] < raw_event_data ["timestamp" ][mask_handled ][:- 1 ]
2045- )[0 ]
2046- + 1
2047- )
2048- jump_ids = np .where (mask_handled )[0 ][jump_ids_handled ] # jump ids in full set of events (incl. unhandled)
2049- overlap = np .isin (jump_ids , reset_ev_ids )
2050- if not all (overlap ):
2041+ # - Compare only packets of the same type: the file does not order packets of different
2042+ # types (e.g. a comment is stamped when the user starts typing but written when they
2043+ # finish, so it can be later than the spikes written after it).
2044+ # jumps maps the position of a packet earlier than the previous packet of its type to the
2045+ # position of that previous packet, in the full set of events (incl. unhandled).
2046+ jumps = {}
2047+ for mask in masks .values ():
2048+ ids = np .flatnonzero (mask )
2049+ ts = raw_event_data ["timestamp" ][ids ]
2050+ earlier = np .flatnonzero (ts [1 :] < ts [:- 1 ])
2051+ jumps .update (zip (ids [earlier + 1 ].tolist (), ids [earlier ].tolist ()))
2052+
2053+ # A reset sends the clock of every packet type back, so each type jumps at its first packet
2054+ # after it. Count a jump only if the packet it is compared with is in the current segment,
2055+ # so that one reset is one boundary.
2056+ reset_set = set (reset_ev_ids .tolist ())
2057+ boundaries = []
2058+ segment_start = 0
2059+ for position in sorted (reset_set | jumps .keys ()):
2060+ if position in reset_set or jumps [position ] >= segment_start :
2061+ boundaries .append (position )
2062+ segment_start = position
2063+ additional_ids = np .array ([b for b in boundaries if b not in reset_set ])
2064+ if len (additional_ids ):
20512065 # additional resets occurred without a reset event being stored
2052- additional_ids = jump_ids [np .invert (overlap )]
20532066 warnings .warn (
20542067 f"Detected { len (additional_ids )} undocumented segments within "
20552068 f"nev data after timestamps { additional_ids } ."
20562069 ""
20572070 )
2058- reset_ev_ids = sorted (np .unique (np .concatenate ((reset_ev_ids , jump_ids ))))
20592071
20602072 event_segment_ids = np .zeros (len (raw_event_data ), dtype = int )
2061- for reset_event_id in reset_ev_ids :
2062- event_segment_ids [ reset_event_id :] += 1
2073+ event_segment_ids [ boundaries ] = 1
2074+ event_segment_ids = np . cumsum ( event_segment_ids )
20632075
2064- self ._nb_segment_nev = len (reset_ev_ids ) + 1
2076+ self ._nb_segment_nev = len (boundaries ) + 1
20652077 return event_segment_ids
20662078
20672079 else :
0 commit comments