def _loop_once(): '''Run the main loop once This uses the global variables from setup and start, and adds a set of global variables ''' global parser, args, config, r, response, patch, monitor, debug, ft_host, ft_port, ft_input, ft_output global timeout, hdr_input, start, window, downsample, differentiate, integrate, rectify, smoothing, reference, default_scale, scale_lowpass, scale_highpass, scale_notchfilter, offset_lowpass, offset_highpass, offset_notchfilter, scale_filterorder, scale_notchquality, offset_filterorder, offset_notchquality, previous, differentiate_zi, integrate_zi, begsample, endsample global dat_input, dat_output, highpassfilter, lowpassfilter, filterorder, change, b, a, zi, notchfilter, notchquality, nb, na, nzi, window_new, t global montage_in, montage_out monitor.loop() # determine when we start polling for available data start = time.time() while endsample > hdr_input.nSamples - 1: # wait until there is enough data time.sleep(patch.getfloat('general', 'delay')) hdr_input = ft_input.getHeader() if (hdr_input.nSamples - 1) < (endsample - window): raise RuntimeError("buffer reset detected") if (time.time() - start) > timeout: raise RuntimeError("timeout while waiting for data") # determine the start of the actual processing start = time.time() dat_input = ft_input.getData([begsample, endsample]).astype(np.float32) dat_output = dat_input monitor.trace( "------------------------------------------------------------") monitor.trace("read " + str(window) + " samples in " + str((time.time() - start) * 1000) + " ms") # Online bandpass filtering highpassfilter = patch.getfloat('processing', 'highpassfilter', default=None) if highpassfilter != None: highpassfilter = EEGsynth.rescale(highpassfilter, slope=scale_highpass, offset=offset_highpass) lowpassfilter = patch.getfloat('processing', 'lowpassfilter', default=None) if lowpassfilter != None: lowpassfilter = EEGsynth.rescale(lowpassfilter, slope=scale_lowpass, offset=offset_lowpass) filterorder = patch.getfloat('processing', 'filterorder', default=int(2 * hdr_input.fSample)) if filterorder != None: filterorder = EEGsynth.rescale(filterorder, slope=scale_filterorder, offset=offset_filterorder) change = False change = monitor.update('highpassfilter', highpassfilter) or change change = monitor.update('lowpassfilter', lowpassfilter) or change change = monitor.update('filterorder', filterorder) or change if change: # update the filter parameters filterorder = int(filterorder) # ensure it is an integer filterorder = filterorder + (filterorder % 2 == 0) # ensure it is odd b, a, zi = EEGsynth.initialize_online_filter(hdr_input.fSample, highpassfilter, lowpassfilter, filterorder, dat_output, axis=0) if not (highpassfilter is None) or not (lowpassfilter is None): # apply the filter to the data dat_output, zi = EEGsynth.online_filter(b, a, dat_output, axis=0, zi=zi) monitor.debug("filtered ", window, "samples in", (time.time() - start) * 1000, "ms") # Online notch filtering notchfilter = patch.getfloat('processing', 'notchfilter', default=None) if notchfilter != None: notchfilter = EEGsynth.rescale(notchfilter, slope=scale_notchfilter, offset=offset_notchfilter) notchquality = patch.getfloat('processing', 'notchquality', default=25) if notchquality != None: notchquality = EEGsynth.rescale(notchquality, slope=scale_notchquality, offset=offset_notchquality) change = False change = monitor.update('notchfilter', notchfilter) or change change = monitor.update('notchquality', notchquality) or change if change: # update the filter parameters nb, na, nzi = EEGsynth.initialize_online_notchfilter(hdr_input.fSample, notchfilter, notchquality, dat_output, axis=0) if not (notchfilter is None): # apply the filter to the data dat_output, nzi = EEGsynth.online_filter(nb, na, dat_output, axis=0, zi=nzi) monitor.debug("notched ", window, "samples in", (time.time() - start) * 1000, "ms") # Differentiate if differentiate: dat_output, d_zi = EEGsynth.online_filter([1, -1], 1, dat_output, axis=0, zi=differentiate_zi) # Integrate if integrate: dat_output, i_zi = EEGsynth.online_filter(1, [1, -1], dat_output, axis=0, zi=integrate_zi) # Rectifying if rectify: dat_output = np.absolute(dat_output) # Smoothing if not (smoothing is None): for t in range(window): dat_output[t, :] = smoothing * dat_output[t, :] + ( 1. - smoothing) * previous previous = copy(dat_output[t, :]) monitor.debug("smoothed ", window_new, "samples in", (time.time() - start) * 1000, "ms") # Downsampling if not (downsample is None): # do not apply an anti aliassing filter, the data segment is probably too short for that dat_output = decimate(dat_output, downsample, n=0, ftype='iir', axis=0, zero_phase=True) window_new = int(window / downsample) monitor.debug("downsampled ", window, "samples in", (time.time() - start) * 1000, "ms") else: window_new = window # Re-referencing if reference == 'median': dat_output -= repmat(np.nanmedian(dat_output, axis=1), dat_output.shape[1], 1).T monitor.debug("rereferenced (median)", window_new, "samples in", (time.time() - start) * 1000, "ms") elif reference == 'average': dat_output -= repmat(np.nanmean(dat_output, axis=1), dat_output.shape[1], 1).T monitor.debug("rereferenced (average)", window_new, "samples in", (time.time() - start) * 1000, "ms") elif reference == 'montage': monitor.debug("applying montage") for i, name in enumerate(montage_out): montage_in[i] = patch.getfloat('montage', name, multiple=True) dat_output = np.matmul(dat_output, np.transpose(np.array(montage_in), (1, 0))) print("Data dimensions after montage:", dat_output.shape) else: monitor.debug("No rereferencing or montage applied") # write the data to the output buffer ft_output.putData(dat_output.astype(np.float32)) monitor.info("preprocessed " + str(window_new) + " samples in " + str((time.time() - start) * 1000) + " ms") monitor.trace("wrote " + str(window_new) + " samples in " + str((time.time() - start) * 1000) + " ms") # increment the counters for the next loop begsample += window endsample += window
def _loop_once(): '''Run the main loop once This uses the global variables from setup and start, and adds a set of global variables ''' global parser, args, config, r, response, patch, monitor, debug, ft_host, ft_port, ft_input, ft_output global timeout, hdr_input, start, sample_rate, f_shift, f_offset, f_order, window, sideband, left, right, scaling, scaling_method, scale_scaling, offset_scaling, default_scale, scale_lowpass, scale_highpass, offset_lowpass, offset_highpass, scale_filterorder, offset_filterorder, hdr_output, nInput, nOutput, begsample, endsample, dat_output, left_f, left_b, left_a, left_zi, right_f, right_b, right_a, right_zi, i, highpass, lowpass global dat_input, begtime, endtime, tim_input, tim_output, chan, vec_output, highpassfilter, lowpassfilter, filterorder, change, b, a, zi, duration, desired monitor.loop() # determine when we start polling for available data start = time.time() while endsample > hdr_input.nSamples - 1: # wait until there is enough data time.sleep(patch.getfloat('general', 'delay')) hdr_input = ft_input.getHeader() if hdr_input.nSamples < begsample: raise RuntimeError("buffer reset detected") if (time.time() - start) > timeout: raise RuntimeError("timeout while waiting for data") # get the input data dat_input = ft_input.getData([begsample, endsample]).astype(np.double) dat_output = np.zeros((nOutput, hdr_output.nChannels)) # construct a time vector for input and output begtime = float(begsample) / hdr_input.fSample endtime = float(endsample + 1) / hdr_input.fSample tim_input = np.linspace(begtime, endtime, nInput, endpoint=False) tim_output = np.linspace(begtime, endtime, nOutput, endpoint=False) for chan, i in zip(left, list(range(len(left)))): # interpolate each channel onto the output sampling rate vec_output = np.interp(tim_output, tim_input, dat_input[:, chan - 1]) # multiply with the modulating signal vec_output *= np.cos(tim_output * left_f[i] * 2 * np.pi) if highpass != None or lowpass != None: # apply the filter to remove one sideband vec_output, left_zi[i] = EEGsynth.online_filter(left_b[i], left_a[i], vec_output, zi=left_zi[i]) # add it to the left-channel output dat_output[:, 0] += vec_output for chan, i in zip(right, list(range(len(right)))): # interpolate each channel onto the output sampling rate vec_output = np.interp(tim_output, tim_input, dat_input[:, chan - 1]) # multiply with the modulating signal vec_output *= np.cos(tim_output * right_f[i] * 2 * np.pi) if highpass != None or lowpass != None: # apply the filter to remove one sideband vec_output, right_zi[i] = EEGsynth.online_filter(right_b[i], right_a[i], vec_output, zi=right_zi[i]) # add it to the right-channel output dat_output[:, 1] += vec_output # Online filtering highpassfilter = patch.getfloat('processing', 'highpassfilter', default=None) if highpassfilter != None: highpassfilter = EEGsynth.rescale(highpassfilter, slope=scale_highpass, offset=offset_highpass) lowpassfilter = patch.getfloat('processing', 'lowpassfilter', default=None) if lowpassfilter != None: lowpassfilter = EEGsynth.rescale(lowpassfilter, slope=scale_lowpass, offset=offset_lowpass) filterorder = patch.getfloat('processing', 'filterorder', default=int(2 * hdr_input.fSample)) if filterorder != None: filterorder = EEGsynth.rescale(filterorder, slope=scale_filterorder, offset=offset_filterorder) change = False change = monitor.update('highpassfilter', highpassfilter) or change change = monitor.update('lowpassfilter', lowpassfilter) or change change = monitor.update('filterorder', filterorder) or change if change: # update the filter parameters filterorder = int(filterorder) # ensure it is an integer filterorder = filterorder + (filterorder % 2 == 0) # ensure it is odd b, a, zi = EEGsynth.initialize_online_filter(hdr_input.fSample, highpassfilter, lowpassfilter, filterorder, dat_output, axis=0) if not (highpassfilter is None) or not (lowpassfilter is None): # apply the filter to the data dat_output, zi = EEGsynth.online_filter(b, a, dat_output, axis=0, zi=zi) # normalize for the number of channels dat_output /= hdr_input.nChannels scaling = patch.getfloat('signal', 'scaling', default=1) scaling = EEGsynth.rescale(scaling, slope=scale_scaling, offset=offset_scaling) if scaling_method == 'multiply': dat_output *= scaling elif scaling_method == 'divide': dat_output /= scaling elif scaling_method == 'db': dat_output *= np.power(10, scaling / 20) # write the data to the output buffer ft_output.putData(dat_output.astype(np.float32)) # compute the duration and desired number of output samples duration = time.time() - start desired = duration * sample_rate # update the number of output samples for the next iteration # if nOutput > desired: # nOutput /= 1.002 # elif nOutput < desired: # nOutput *= 1.002 # nOutput = int(round(nOutput)) monitor.info("wrote", nInput, "->", nOutput, "samples in", duration * 1000, "ms") # shift to the next block of data begsample += nInput endsample += nInput # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
dat_input = ft_input.getData([begsample, endsample]) dat_output = np.zeros((nOutput,hdr_output.nChannels)) # construct a time vector for input and output begtime = float(begsample ) / hdr_input.fSample endtime = float(endsample+1) / hdr_input.fSample tim_input = np.linspace(begtime, endtime, nInput, endpoint=False) tim_output = np.linspace(begtime, endtime, nOutput, endpoint=False) for chan, i in zip(left, list(range(len(left)))): # interpolate each channel onto the output sampling rate vec_output = np.interp(tim_output, tim_input, dat_input[:, chan-1]) # multiply with the modulating signal vec_output *= np.cos(tim_output * left_f[i] * 2 * np.pi) # apply the filter to remove one sideband vec_output, left_zi[i] = EEGsynth.online_filter(left_b[i], left_a[i], vec_output, zi=left_zi[i]) # add it to the output dat_output[:,0] += vec_output for chan, i in zip(right, list(range(len(right)))): # interpolate each channel onto the output sampling rate vec_output = np.interp(tim_output, tim_input, dat_input[:, chan-1]) # multiply with the modulating signal vec_output *= np.cos(tim_output * right_f[i] * 2 * np.pi) # apply the filter to remove one sideband vec_output, right_zi[i] = EEGsynth.online_filter(right_b[i], right_a[i], vec_output, zi=right_zi[i]) # add it to the output dat_output[:,1] += vec_output # normalize for the number of channels dat_output /= hdr_input.nChannels
dat_input = ft_input.getData([begsample, endsample]) dat_output = np.zeros((nOutput,hdr_output.nChannels)) # construct a time vector for input and output begtime = float(begsample ) / hdr_input.fSample endtime = float(endsample+1) / hdr_input.fSample tim_input = np.linspace(begtime, endtime, nInput, endpoint=False) tim_output = np.linspace(begtime, endtime, nOutput, endpoint=False) for chan, i in zip(left, range(len(left))): # interpolate each channel onto the output sampling rate vec_output = np.interp(tim_output, tim_input, dat_input[:, chan-1]) # multiply with the modulating signal vec_output *= np.cos(tim_output * left_f[i] * 2 * np.pi) # apply the filter to remove one sideband vec_output, left_zi[i] = EEGsynth.online_filter(left_b[i], left_a[i], vec_output, zi=left_zi[i]) # add it to the output dat_output[:,0] += vec_output for chan, i in zip(right, range(len(right))): # interpolate each channel onto the output sampling rate vec_output = np.interp(tim_output, tim_input, dat_input[:, chan-1]) # multiply with the modulating signal vec_output *= np.cos(tim_output * right_f[i] * 2 * np.pi) # apply the filter to remove one sideband vec_output, right_zi[i] = EEGsynth.online_filter(right_b[i], right_a[i], vec_output, zi=right_zi[i]) # add it to the output dat_output[:,1] += vec_output # normalize for the number of channels dat_output /= hdr_input.nChannels
# construct a time vector for input and output begtime = float(begsample) / hdr_input.fSample endtime = float(endsample + 1) / hdr_input.fSample tim_input = np.linspace(begtime, endtime, nInput, endpoint=False) tim_output = np.linspace(begtime, endtime, nOutput, endpoint=False) for chan, i in zip(left, list(range(len(left)))): # interpolate each channel onto the output sampling rate vec_output = np.interp(tim_output, tim_input, dat_input[:, chan - 1]) # multiply with the modulating signal vec_output *= np.cos(tim_output * left_f[i] * 2 * np.pi) if highpass != None or lowpass != None: # apply the filter to remove one sideband vec_output, left_zi[i] = EEGsynth.online_filter(left_b[i], left_a[i], vec_output, zi=left_zi[i]) # add it to the left-channel output dat_output[:, 0] += vec_output for chan, i in zip(right, list(range(len(right)))): # interpolate each channel onto the output sampling rate vec_output = np.interp(tim_output, tim_input, dat_input[:, chan - 1]) # multiply with the modulating signal vec_output *= np.cos(tim_output * right_f[i] * 2 * np.pi) if highpass != None or lowpass != None: # apply the filter to remove one sideband vec_output, right_zi[i] = EEGsynth.online_filter(right_b[i], right_a[i], vec_output, zi=right_zi[i])
if highpassfilter != None: highpassfilter = EEGsynth.rescale(highpassfilter, slope=scale_highpass, offset=offset_highpass) lowpassfilter = patch.getfloat('processing', 'lowpassfilter', default=None) if lowpassfilter != None: lowpassfilter = EEGsynth.rescale(lowpassfilter, slope=scale_lowpass, offset=offset_lowpass) change = False change = show_change('highpassfilter', highpassfilter) or change change = show_change('lowpassfilter', lowpassfilter) or change if change: # update the filter parameters b, a, zi = EEGsynth.initialize_online_filter(hdr_input.fSample, highpassfilter, lowpassfilter, filterorder, dat_output, axis=0) if not(highpassfilter is None) or not(lowpassfilter is None): # apply the filter to the data dat_output, zi = EEGsynth.online_filter(b, a, dat_output, axis=0, zi=zi) if debug>1: print("filtered ", window, "samples in", (time.time()-start)*1000, "ms") # Downsampling if not(downsample is None): dat_output = decimate(dat_output, downsample, ftype='iir', axis=0, zero_phase=True) window_new = int(window / downsample) if debug>1: print("downsampled ", window, "samples in", (time.time()-start)*1000, "ms") else: window_new = window # Smoothing if not(smoothing is None): for t in range(window):
if change: # update the filter parameters filterorder = int(filterorder) # ensure it is an integer filterorder = filterorder + (filterorder % 2 == 0) # ensure it is odd b, a, zi = EEGsynth.initialize_online_filter(hdr_input.fSample, highpassfilter, lowpassfilter, filterorder, dat_output, axis=0) if not (highpassfilter is None) or not (lowpassfilter is None): # apply the filter to the data dat_output, zi = EEGsynth.online_filter(b, a, dat_output, axis=0, zi=zi) if debug > 1: print("filtered ", window, "samples in", (time.time() - start) * 1000, "ms") # Online notch filtering notchfilter = patch.getfloat('processing', 'notchfilter', default=None) if notchfilter != None: notchfilter = EEGsynth.rescale(notchfilter, slope=scale_notchfilter, offset=offset_notchfilter) notchquality = patch.getfloat('processing', 'notchquality', default=25) if notchquality != None: notchquality = EEGsynth.rescale(notchquality,