You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Loop through new timestamps to find the closest old timestamp
52
+
# Handle timestamps outside of the segment (too young or too old) different from stamnps from within the segment
48
53
fornix, ntsinenumerate(new_timestamps):
49
-
closest= (np.abs(old_timestamps-nts)).argmin()
50
-
# remember the edge cases,
51
-
if (nts>ts_last):
54
+
ifnts>ts_last:
52
55
too_young.append((nix, nts))
53
-
elif(nts<ts_first):
54
-
too_old.append((nix,nts))
56
+
elifnts<ts_first:
57
+
too_old.append((nix,nts))
55
58
else:
56
-
closest= (np.abs(old_timestamps-nts)).argmin()
57
-
source.append(closest)
58
-
target.append(nix)
59
-
# check the edge cases,
60
-
fornix, ntsinreversed(too_old):
61
-
closest= (np.abs(old_timestamps-nts)).argmin()
62
-
if (closestnotinsource):
59
+
closest=np.abs(old_timestamps-nts).argmin()
60
+
ifclosestnotinsource: # Ensure unique mapping
61
+
source.append(closest)
62
+
target.append(nix)
63
+
else:
64
+
raiseRuntimeError(
65
+
f"Non-unique mapping. Closest old timestamp for {new_timestamps[nix]} is {old_timestamps[closest]} but that one was already assigned to {new_timestamps[source.index(closest)]}"
66
+
)
67
+
68
+
# Handle too old timestamps (those before the first old timestamp)
69
+
fornix, ntsintoo_old:
70
+
closest=0# Assign to the first timestamp
71
+
ifclosestnotinsource: # Ensure unique mapping
63
72
source.append(closest)
64
73
target.append(nix)
65
-
break
74
+
break# only one, because we only need the edge
75
+
76
+
# Handle too young timestamps (those after the last old timestamp)
66
77
fornix, ntsintoo_young:
67
-
closest=(np.abs(old_timestamps-nts)).argmin()
68
-
if(closestnotinsource):
78
+
closest=len(old_timestamps)-1# Assign to the last timestamp
79
+
ifclosestnotinsource: # Ensure unique mapping
69
80
source.append(closest)
70
81
target.append(nix)
71
-
break
72
-
73
-
iflen(set(source)) !=len(old_timestamps):
74
-
missed=len(old_timestamps)-len(set(source))
75
-
raiseRuntimeError(f"Too few new timestamps. {missed} of {len(old_timestamps)} old samples could not be assigned.")
f"Too few new timestamps. {missed} old timestamps ({old_timestamps[unassigned_old]}) found no corresponding new timestamp because it was already taken by another old timestamp. If your stream has multiple segments, this might be caused by small differences in effective srate between segments. Try different dejittering thresholds or support your own aligned_timestamps."
90
+
)
91
+
92
+
# Populate new timeseries with aligned values from old_timeseries
streams: a list of defaultdicts (i.e. streams) as returned by
111
+
streams: a list of defaultdicts (i.e. streams) as returned by
103
112
load_xdf
104
-
align_foo: a dictionary mapping streamIDs (i.e. int) to interpolation
105
-
callables. These callables must have the signature
113
+
align_foo: a dictionary mapping streamIDs (i.e. int) to interpolation
114
+
callables. These callables must have the signature
106
115
`interpolate(old_timestamps, old_timeseries, new_timestamps)` and return a np.ndarray. See `_shift_align` and `_interpolate` for examples.
107
-
aligned_timestamps (optional): a list of floats with the new
116
+
aligned_timestamps (optional): a list of floats with the new
108
117
timestamps to be used for alignment/interpolation. This list of timestamps can be irregular and have gaps.
109
-
sampling_rate (optional): a float defining the sampling rate which
118
+
sampling_rate (optional): a float defining the sampling rate which
110
119
will be used to calculate aligned_timestamps.
111
-
120
+
112
121
Return:
113
122
(aligned_timeseries, aligned_timestamps): tuple
114
123
115
124
116
-
THe user can define either aligned_timestamps or sampling_rate or neither. If neither is defined, the algorithm will take the sampling_rate of the fastest stream and create aligned_timestamps from the oldest sample of all streams to the youngest.
117
-
125
+
THe user can define either aligned_timestamps or sampling_rate or neither. If neither is defined, the algorithm will take the sampling_rate of the fastest stream and create aligned_timestamps from the oldest sample of all streams to the youngest.
# using np.linspace only differs in step if n_samples is different (as n_samples must be an integer number (see implementation below).
142
-
# therefore we stick with np.arange (in spite of possible floating point error accumulation, but to make sure that ts_last is included, we add a half-step. This therefore comes at the cost of a overshoot, but i consider this acceptable considering this stamp would only be from one stream, and not part of all other and therefore is kind of arbitray anyways.
# https://stackoverflow.com/questions/1704823/create-numpy-matrix-filled-with-nans The timings show a preference for ndarray.fill(..) as the faster alternative.
0 commit comments