@@ -144,6 +144,61 @@ def scale_timings(timelist, input_units, output_units, time_repetition):
144
144
timelist = [np .max ([0. , _scalefactor * t ]) for t in timelist ]
145
145
return timelist
146
146
147
+ def bids_gen_info (bids_event_files ,
148
+ condition_column = 'trial_type' ,
149
+ amplitude_column = None ,
150
+ time_repetition = False ,
151
+ ):
152
+ """Generate subject_info structure from a list of BIDS .tsv event files.
153
+
154
+ Parameters
155
+ ----------
156
+
157
+ bids_event_files : list of str
158
+ Filenames of BIDS .tsv event files containing columns including:
159
+ 'onset', 'duration', and 'trial_type' or the `condition_column` value.
160
+ condition_column : str
161
+ Column of files in `bids_event_files` based on the values of which
162
+ events will be sorted into different regressors
163
+ amplitude_column : str
164
+ Column of files in `bids_event_files` based on the values of which
165
+ to apply amplitudes to events. If unspecified, all events will be
166
+ represented with an amplitude of 1.
167
+
168
+ Returns
169
+ -------
170
+
171
+ list of Bunch
172
+ """
173
+ info = []
174
+ for bids_event_file in bids_event_files :
175
+ with open (bids_event_file ) as f :
176
+ f_events = csv .DictReader (f , skipinitialspace = True , delimiter = '\t ' )
177
+ events = [{k : v for k , v in row .items ()} for row in f_events ]
178
+ conditions = list (set ([i [condition_column ] for i in events ]))
179
+ runinfo = Bunch (conditions = [], onsets = [], durations = [], amplitudes = [])
180
+ for condition in conditions :
181
+ selected_events = [i for i in events if i [condition_column ]== condition ]
182
+ onsets = [float (i ['onset' ]) for i in selected_events ]
183
+ durations = [float (i ['duration' ]) for i in selected_events ]
184
+ if time_repetition :
185
+ decimals = math .ceil (- math .log10 (time_repetition ))
186
+ onsets = [np .round (i , decimals ) for i in onsets ]
187
+ durations = [np .round (i ,decimals ) for i in durations ]
188
+ if condition :
189
+ runinfo .conditions .append (condition )
190
+ else :
191
+ runinfo .conditions .append ('e0' )
192
+ runinfo .onsets .append (onsets )
193
+ runinfo .durations .append (durations )
194
+ try :
195
+ amplitudes = [float (i [amplitude_column ]) for i in selected_events ]
196
+ runinfo .amplitudes .append (amplitudes )
197
+ except KeyError :
198
+ runinfo .amplitudes .append ([1 ] * len (onsets ))
199
+ info .append (runinfo )
200
+ return info
201
+
147
202
148
203
def gen_info (run_event_files ):
149
204
"""Generate subject_info structure from a list of event files
@@ -190,6 +245,23 @@ class SpecifyModelInputSpec(BaseInterfaceInputSpec):
190
245
desc = 'List of event description files 1, 2 or 3 '
191
246
'column format corresponding to onsets, '
192
247
'durations and amplitudes' )
248
+ bids_event_file = InputMultiPath (
249
+ File (exists = True ),
250
+ mandatory = True ,
251
+ xor = ['subject_info' , 'event_files' , 'bids_event_file' ],
252
+ desc = 'TSV event file containing common BIDS fields: `onset`,'
253
+ '`duration`, and categorization and amplitude columns' )
254
+ bids_condition_column = traits .Str (exists = True ,
255
+ mandatory = False ,
256
+ default_value = 'trial_type' ,
257
+ usedefault = True ,
258
+ desc = 'Column of the file passed to `bids_event_file` to the '
259
+ 'unique values of which events will be assigned'
260
+ 'to regressors' )
261
+ bids_amplitude_column = traits .Str (exists = True ,
262
+ mandatory = False ,
263
+ desc = 'Column of the file passed to `bids_event_file` '
264
+ 'according to which to assign amplitudes to events' )
193
265
realignment_parameters = InputMultiPath (
194
266
File (exists = True ),
195
267
desc = 'Realignment parameters returned '
@@ -432,8 +504,15 @@ def _generate_design(self, infolist=None):
432
504
if infolist is None :
433
505
if isdefined (self .inputs .subject_info ):
434
506
infolist = self .inputs .subject_info
435
- else :
507
+ elif isdefined ( self . inputs . event_files ) :
436
508
infolist = gen_info (self .inputs .event_files )
509
+ elif isdefined (self .inputs .bids_event_file ):
510
+ infolist = bids_gen_info (
511
+ self .inputs .bids_event_file ,
512
+ self .inputs .bids_condition_column ,
513
+ self .inputs .bids_amplitude_column ,
514
+ self .inputs .time_repetition ,
515
+ )
437
516
self ._sessinfo = self ._generate_standard_design (
438
517
infolist ,
439
518
functional_runs = self .inputs .functional_runs ,
0 commit comments