def read_chl_events(raw, times, threshold=.5): ''' Returns a list of events with the time points where there was crossing of the head movement threshold (begin and end). raw is the raw structure, times is a time vector ''' # just like the marker files, the goal here is to create events any time the CHL signal goes bad and then becomes good again (i.e. marking the bad segment) markers = [] motion = hm.get_head_motion(raw) movement = np.sqrt(np.sum(motion**2, axis=0)) # smooth the movement movement = mne.filter.low_pass_filter(movement, 300, 1) # store the sample locations where movement crosses threshold bad_segs = np.nonzero(movement >= threshold)[0] if len(bad_segs) > 0: # finding non-consecutive bad segments. We need to add one because we used diff() before start_bad_segs = np.nonzero(np.diff(bad_segs) > 1)[0] + np.ones(1) # add back the first bad segment start_bad_segs = np.concatenate(([0], start_bad_segs)) # now start_bad_segs stores the positions when the bad segments started. Following the same logic, we compute the end of each segment end_bad_segs = np.nonzero(np.diff(bad_segs) > 1)[0] end_bad_segs = np.concatenate((end_bad_segs, [len(bad_segs) - 1])) start_end = np.sort(np.concatenate((start_bad_segs, end_bad_segs))) markers = [times[bad_segs[int(i)]] for i in start_end] return markers
def crop_good_epochs(raw, window_length=13, step_length=1, threshold=4000e-13, allowed_motion=-1, verbose=1, fmin=0, fmax=np.Inf): ''' Returns an Epochs structure with what time periods to use. window_length and step_length are in seconds. Set allowed_motion to < 0 to avoid checking head position. ''' picks = mne.fiff.pick_channels_regexp(raw.info['ch_names'], 'M..-*') # pdb.set_trace() # note that we need to filter raw, so that we can pass it on later if fmin > 0 and fmax < np.Inf: # bandpass the signal accordingly for s in picks: raw[s, :] = mne.filter.band_pass_filter(raw[s, :][0], raw.info['sfreq'], fmin, fmax, l_trans_bandwidth=.25) elif fmax < np.Inf: for s in picks: raw[s, :] = mne.filter.low_pass_filter(raw[s, :][0], raw.info['sfreq'], fmax) elif fmin > 0: for s in picks: raw[s, :] = mne.filter.high_pass_filter(raw[s, :][0], raw.info['sfreq'], fmin, trans_bandwidth=.25) ''' We search for windows of the given length. If a good window is found, add it to the list and check the next window (non-overlapping). If the current window is no good, step to the next available window. ''' # # if there's no CHL, discard the subject right away # if hm.get_head_motion(raw) is None: # return None events = [] cur = 0 window_size = int(window_length * raw.info['sfreq']) step_size = int(step_length * raw.info['sfreq']) while cur + window_size < raw.n_times: chunk = raw[picks, cur:(cur + window_size)][0] peak2peak = abs(np.amax(chunk, axis=1) - np.amin(chunk, axis=1)) num_good_channels = np.sum(peak2peak < threshold, axis=0) # We can either completely disregard head position markers if allowed_motion < 0: max_motion = -np.Inf # if we're using them, check if the subject actually has them first elif hm.get_head_motion(raw) is not None: max_motion = hm.get_max_motion(raw, smin=cur, smax=(cur + window_size)) # if the subject doesn't have them, return right away else: return None # print str(max_motion) # if all channels have p2p smaller than threshold, check head movement if num_good_channels == len(picks) and max_motion < allowed_motion: events.append([cur, 0, 0]) cur += window_size else: cur += step_size print 'Found ' + str(len(events)) + ' good epochs (' + str(len(events)*window_length) + ' sec).' if len(events) > 0: events = np.array(events) epochs = mne.Epochs(raw, events, None, 0, window_length, keep_comp=True, preload=True, baseline=None, detrend=0, picks=picks) else: epochs = None return epochs