@@ -25,6 +25,7 @@ def wrapper(*args, **kwargs):
25
25
"time_unit" : (str ,),
26
26
"align" : (str ,),
27
27
"padding_value" : (Number ,),
28
+ "num_bin" : (int ,)
28
29
}
29
30
for param , param_type in parameters_type .items ():
30
31
if param in kwargs :
@@ -39,25 +40,35 @@ def wrapper(*args, **kwargs):
39
40
return wrapper
40
41
41
42
42
- def _build_tensor_from_tsgroup (input , ep , binsize , align , padding_value ):
43
+ def _build_tensor_from_tsgroup (input , ep , binsize , align , padding_value , time_unit ):
43
44
# Determine size of tensor
45
+ binsize = float (nap .TsIndex .format_timestamps (np .array ([binsize ]), time_unit )[0 ])
44
46
n_t = int (np .max (np .ceil ((ep .end + binsize - ep .start ) / binsize )))
45
- output = np .ones (shape = (len (input ), len (ep ), n_t )) * padding_value
46
47
count = input .count (bin_size = binsize , ep = ep )
47
48
49
+ if len (count .shape ) == 1 :
50
+ output = np .ones (shape = (1 , len (ep ), n_t )) * padding_value
51
+ else :
52
+ output = np .ones (shape = (count .shape [1 ], len (ep ), n_t )) * padding_value
53
+
54
+ n_ep = np .zeros (len (ep ), dtype = "int" ) # To trim to the minimum length
55
+
48
56
if align == "start" :
49
57
for i in range (len (ep )):
50
58
tmp = count .get (ep .start [i ], ep .end [i ]).values
59
+ n_ep [i ] = tmp .shape [0 ]
51
60
output [:, i , 0 : tmp .shape [0 ]] = np .transpose (tmp )
52
- if np .all (np .isnan (output [:, :, - 1 ])):
53
- output = output [:, :, 0 :- 1 ]
61
+ output = output [:, :, 0 : np .max (n_ep )]
54
62
55
63
if align == "end" :
56
64
for i in range (len (ep )):
57
65
tmp = count .get (ep .start [i ], ep .end [i ]).values
66
+ n_ep [i ] = tmp .shape [0 ]
58
67
output [:, i , - tmp .shape [0 ] :] = np .transpose (tmp )
59
- if np .all (np .isnan (output [:, :, 0 ])):
60
- output = output [:, :, 1 :]
68
+ output = output [:, :, - np .max (n_ep ) :]
69
+
70
+ if len (count .shape ) == 1 : # Removing first axis if Ts.
71
+ output = output [0 ]
61
72
62
73
return output
63
74
@@ -100,7 +111,7 @@ def build_tensor(
100
111
101
112
Parameters
102
113
----------
103
- input : Tsd, TsdFrame, TsdTensor or TsGroup
114
+ input : Ts, Tsd, TsdFrame, TsdTensor or TsGroup
104
115
Input to slice and align to the trials within the `ep` parameter.
105
116
ep : IntervalSet
106
117
Epochs holding the trials. Each interval can be of unequal size.
@@ -121,65 +132,96 @@ def build_tensor(
121
132
RuntimeError
122
133
If `time_unit` not in ["s", "ms", "us"]
123
134
124
-
125
135
Examples
126
136
--------
127
-
128
-
137
+ >>> import pynapple as nap
138
+ >>> import numpy as np
139
+ >>> group = nap.TsGroup({0:nap.Ts(t=np.arange(0, 100))})
140
+ >>> ep = nap.IntervalSet(start=np.arange(20, 100, 20), end=np.arange(20, 100, 20) + np.arange(2, 10, 2))
141
+ >>> print(ep)
142
+ index start end
143
+ 0 20 22
144
+ 1 40 44
145
+ 2 60 66
146
+ 3 80 88
147
+ shape: (4, 2), time unit: sec.
148
+
149
+ Create a trial-based tensor by counting events within 1 second bin for each interval of `ep`.
150
+
151
+ >>> tensor = nap.build_tensor(group, ep, binsize=1)
152
+ >>> tensor
153
+ array([[[ 1., 1., nan, nan, nan, nan, nan, nan],
154
+ [ 1., 1., 1., 1., nan, nan, nan, nan],
155
+ [ 1., 1., 1., 1., 1., 1., nan, nan],
156
+ [ 1., 1., 1., 1., 1., 1., 1., 1.]]])
157
+
158
+ By default, the time series are aligned to the start of the epochs. The parameter `align` control this behavior.
159
+
160
+ >>> tensor = nap.build_tensor(group, ep, binsize=1, align="end")
161
+ >>> tensor
162
+ array([[[nan, nan, nan, nan, nan, nan, 1., 1.],
163
+ [nan, nan, nan, nan, 1., 1., 1., 1.],
164
+ [nan, nan, 1., 1., 1., 1., 1., 1.],
165
+ [ 1., 1., 1., 1., 1., 1., 1., 1.]]])
166
+
167
+ This function works for any time series.
168
+
169
+ >>> tsdframe = nap.TsdFrame(t=np.arange(100), d=np.arange(200).reshape(2,100).T)
170
+ >>> tensor = nap.build_tensor(tsdframe, ep)
171
+ >>> tensor
172
+ array([[[ 20., 21., 22., nan, nan, nan, nan, nan, nan],
173
+ [ 40., 41., 42., 43., 44., nan, nan, nan, nan],
174
+ [ 60., 61., 62., 63., 64., 65., 66., nan, nan],
175
+ [ 80., 81., 82., 83., 84., 85., 86., 87., 88.]],
176
+ [[120., 121., 122., nan, nan, nan, nan, nan, nan],
177
+ [140., 141., 142., 143., 144., nan, nan, nan, nan],
178
+ [160., 161., 162., 163., 164., 165., 166., nan, nan],
179
+ [180., 181., 182., 183., 184., 185., 186., 187., 188.]]])
129
180
130
181
"""
131
182
if time_unit not in ["s" , "ms" , "us" ]:
132
183
raise RuntimeError ("time_unit should be 's', 'ms' or 'us'" )
133
184
if align not in ["start" , "end" ]:
134
185
raise RuntimeError ("align should be 'start' or 'end'" )
135
186
136
- if isinstance (input , nap .TsGroup ):
187
+ if isinstance (input , ( nap .TsGroup , nap . Ts ) ):
137
188
if not isinstance (binsize , Number ):
138
- raise RuntimeError ("When input is a TsGroup, binsize should be specified" )
139
- return _build_tensor_from_tsgroup (input , ep , binsize , align , padding_value )
140
-
141
- if isinstance (input , (nap .Tsd , nap .TsdFrame , nap .TsdTensor )):
189
+ raise RuntimeError (
190
+ "When input is a TsGroup or Ts object, binsize should be specified"
191
+ )
192
+ return _build_tensor_from_tsgroup (
193
+ input , ep , binsize , align , padding_value , time_unit
194
+ )
195
+ else :
142
196
return _build_tensor_from_tsd (input , ep , align , padding_value )
143
197
144
198
145
199
@_validate_warping_inputs
146
- def warp_tensor (input , ep , num_bin = None , align = "start" ):
200
+ def warp_tensor (input , ep , num_bin = None ):
147
201
"""
148
- Return time-warped trial-based tensor from an IntervalSet object.
202
+ Return linearly time-warped trial-based tensor from an IntervalSet object.
149
203
150
- - If `input` is a `TsGroup`, returns a numpy array of shape (number of group element, number of trial, number of time bins). The `binsize` parameter determines the number of time bins .
204
+ - If `input` is a `TsGroup`, returns a numpy array of shape (number of group element, number of trial, `num_bin`) .
151
205
152
- - If `input` is `Tsd`, `TsdFrame` or `TsdTensor`, returns a numpy array of shape (shape of time series, number of trial, number of time points ).
206
+ - If `input` is `Tsd`, `TsdFrame` or `TsdTensor`, returns a numpy array of shape (shape of time series, number of trial, `num_bin` ).
153
207
154
208
155
209
Parameters
156
210
----------
157
- input : Tsd, TsdFrame, TsdTensor or TsGroup
158
- Returns a numpy array.
211
+ input : Ts, Tsd, TsdFrame, TsdTensor or TsGroup
212
+ Input object
159
213
ep : IntervalSet
160
214
Epochs holding the trials. Each interval can be of unequal size.
161
- binsize : Number, optional
162
- align: str, optional
163
- How to align the time series ('start' [default], 'end')
164
- padding_value: Number, optional
165
- How to pad the array if unequal intervals. Default is np.nan.
166
- time_unit : str, optional
167
- Time units of the binsize parameter ('s' [default], 'ms', 'us').
215
+ num_bin : int
168
216
169
217
Returns
170
218
-------
171
219
numpy.ndarray
172
220
173
- Raises
174
- ------
175
- RuntimeError
176
- If `time_unit` not in ["s", "ms", "us"]
177
-
178
-
179
221
Examples
180
222
--------
181
223
182
224
183
225
184
226
"""
185
- pass
227
+
0 commit comments