def __init__(self, ipmarker_server=None, **kwargs): """ currently no parameter """ if usb_warning: warnings.warn("The usb_acquisition Module could not be imported!") super(EEGClientUsb, self).__init__(**kwargs) self.all_channels = ['Fp1', 'Fp2', 'F7', 'F3', 'Fz', 'F4', 'F8', 'FC5',\ 'FC1', 'FC2', 'FC6', 'T7', 'C3', 'Cz', 'C4', 'T8',\ 'TP9', 'CP5', 'CP1', 'CP2', 'CP6', 'TP10', 'P7',\ 'P3', 'Pz', 'P4', 'P8', 'PO9', 'O1', 'Oz', 'O2',\ 'PO10', 'AF7', 'AF3', 'AF4', 'AF8', 'F5', 'F1',\ 'F2', 'F6', 'FT9', 'FT7', 'FC3', 'FC4', 'FT8',\ 'FT10', 'C5', 'C1', 'C2', 'C6', 'TP7', 'CP3',\ 'CPz', 'CP4', 'TP8', 'P5', 'P1', 'P2', 'P6',\ 'PO7', 'PO3', 'POz', 'PO4', 'PO8', 'Fpz', 'F9',\ 'AFF5h', 'AFF1h', 'AFF2h', 'AFF6h', 'F10', 'FTT9h',\ 'FTT7h', 'FCC5h', 'FCC3h', 'FCC1h', 'FCC2h',\ 'FCC4h', 'FCC6h', 'FTT8h', 'FTT10h', 'TPP9h',\ 'TPP7h', 'CPP5h', 'CPP3h', 'CPP1h', 'CPP2h',\ 'CPP4h', 'CPP6h', 'TPP8h', 'TPP10h', 'POO9h',\ 'POO1', 'POO2', 'POO10h', 'Iz', 'AFp1', 'AFp2',\ 'FFT9h', 'FFT7h', 'FFC5h', 'FFC3h', 'FFC1h',\ 'FFC2h', 'FFC4h', 'FFC6h', 'FFT8h', 'FFT10h',\ 'TTP7h', 'CCP5h', 'CCP3h', 'CCP1h', 'CCP2h',\ 'CCP4h', 'CCP6h', 'TTP8h', 'P9', 'PPO9h', 'PPO5h',\ 'PPO1h', 'PPO2h', 'PPO6h', 'PPO10h', 'P10', 'I1',\ 'OI1h', 'OI2h', 'I2'] self.ipmarker_server = ipmarker_server self.ip_lastmarker = (None, None) self._dSamplingInterval = 5000 self._channelNames = None self._markerids = dict() self._markerNames = dict() self.marker_id_counter = 0 self._stdblocksize = 100 self.fmt = None self.channelids = None self.resolutions = None self.nChannels = None self.callbacks = list() self.raw_data = list() self.timestamp = 0 self.dig_lastmarker = 0 self.acquisition = BUASubprocess() self.acquisition.start() self.connect()
class EEGClientUsb(AbstractStreamReader): """ Acquire raw streamed eeg-data from usb-acquisition submodule This implementation uses the usb1 module, available from Pip/easy_install. usb1 is used to wrap calls to the libusbx c-library. """ def __init__(self, ipmarker_server=None, **kwargs): """ currently no parameter """ if usb_warning: warnings.warn("The usb_acquisition Module could not be imported!") super(EEGClientUsb, self).__init__(**kwargs) self.all_channels = ['Fp1', 'Fp2', 'F7', 'F3', 'Fz', 'F4', 'F8', 'FC5',\ 'FC1', 'FC2', 'FC6', 'T7', 'C3', 'Cz', 'C4', 'T8',\ 'TP9', 'CP5', 'CP1', 'CP2', 'CP6', 'TP10', 'P7',\ 'P3', 'Pz', 'P4', 'P8', 'PO9', 'O1', 'Oz', 'O2',\ 'PO10', 'AF7', 'AF3', 'AF4', 'AF8', 'F5', 'F1',\ 'F2', 'F6', 'FT9', 'FT7', 'FC3', 'FC4', 'FT8',\ 'FT10', 'C5', 'C1', 'C2', 'C6', 'TP7', 'CP3',\ 'CPz', 'CP4', 'TP8', 'P5', 'P1', 'P2', 'P6',\ 'PO7', 'PO3', 'POz', 'PO4', 'PO8', 'Fpz', 'F9',\ 'AFF5h', 'AFF1h', 'AFF2h', 'AFF6h', 'F10', 'FTT9h',\ 'FTT7h', 'FCC5h', 'FCC3h', 'FCC1h', 'FCC2h',\ 'FCC4h', 'FCC6h', 'FTT8h', 'FTT10h', 'TPP9h',\ 'TPP7h', 'CPP5h', 'CPP3h', 'CPP1h', 'CPP2h',\ 'CPP4h', 'CPP6h', 'TPP8h', 'TPP10h', 'POO9h',\ 'POO1', 'POO2', 'POO10h', 'Iz', 'AFp1', 'AFp2',\ 'FFT9h', 'FFT7h', 'FFC5h', 'FFC3h', 'FFC1h',\ 'FFC2h', 'FFC4h', 'FFC6h', 'FFT8h', 'FFT10h',\ 'TTP7h', 'CCP5h', 'CCP3h', 'CCP1h', 'CCP2h',\ 'CCP4h', 'CCP6h', 'TTP8h', 'P9', 'PPO9h', 'PPO5h',\ 'PPO1h', 'PPO2h', 'PPO6h', 'PPO10h', 'P10', 'I1',\ 'OI1h', 'OI2h', 'I2'] self.ipmarker_server = ipmarker_server self.ip_lastmarker = (None, None) self._dSamplingInterval = 5000 self._channelNames = None self._markerids = dict() self._markerNames = dict() self.marker_id_counter = 0 self._stdblocksize = 100 self.fmt = None self.channelids = None self.resolutions = None self.nChannels = None self.callbacks = list() self.raw_data = list() self.timestamp = 0 self.dig_lastmarker = 0 self.acquisition = BUASubprocess() self.acquisition.start() self.connect() @property def dSamplingInterval(self): return self._dSamplingInterval @property def stdblocksize(self): return self._stdblocksize @property def markerids(self): return self._markerids @property def channelNames(self): return self._channelNames @property def markerNames(self): return self._markerNames def regcallback(self, func): self.callbacks.append(func) def block_length_ms(self): return (self.stdblocksize*1000)/self.dSamplingInterval def disconnect(self): if self.ipmarker_server is not None: self.ipmarker_server.stop() self.ipmarker_server.join() self.acquisition.stop() self.acquisition.join(timeout=5) del self.acquisition def new_marker_id(self): self.marker_id_counter += 1 return self.marker_id_counter def connect(self, verbose=False): while self.acquisition.nchannels.value < 0: if not self.acquisition.is_alive(): raise IOError, "Acquisition quit early!" time.sleep(.1) self.nChannels = self.acquisition.nchannels.value if self.nChannels == 0: raise IOError, "No Amplifiers found! Switch them on?" # generate all possible marker names and ids self._markerids['null'] = 0 for s in range(1,256,1): self._markerids[str('S%d' % s)] = self.new_marker_id() for r in range(1,256,1): self._markerids[str('R%d' % r)] = self.new_marker_id() # generate reverse mapping for k,v in zip(self._markerids.iterkeys(), self._markerids.itervalues()): self._markerNames[v] = k # select channelnames self._channelNames = self.all_channels[:self.nChannels] # calculate raw-data threshold while self.acquisition.nextra_channels.value < 0 \ or self.acquisition.nall_channels < 0: time.sleep(.1) self.nextra_channels = self.acquisition.nextra_channels.value self.nall_channels = self.acquisition.nall_channels.value self.min_raw_data = self.stdblocksize * self.nall_channels def read(self, nblocks=1, verbose=False): readblocks = 0 while (readblocks < nblocks or nblocks == -1): # get enough raw data blocks self.gather_enough_data() # split data and marker in seperate arrays ndsamples, ndmarkers = self.separate() for f in self.callbacks: f(ndsamples, ndmarkers) readblocks += 1 return readblocks def gather_enough_data(self): """ gets enough data to generate a block of size stdblocksize in channel and markers """ while len(self.raw_data) < self.min_raw_data: data, timestamp = self.acquisition.read() if self.fmt is None: self.fmt = str("%dh" % (len(data)/2)) values = struct.unpack(self.fmt, data) self.raw_data.extend(values) self.timestamp = timestamp-self.block_length_ms() def separate(self): """ separates the raw-data into the data- and marker-channels """ packet = self.raw_data[0:self.min_raw_data] self.raw_data[0:self.min_raw_data] = [] # example block-layout for 32 channels: # [marker:1][reserved:4][nchannels data:32] :|| data = list() mark = list() for i in range(self.stdblocksize): mark.append(self.digital_marker(packet[0])) data.extend(packet[self.nextra_channels:self.nextra_channels+self.nChannels]) packet[0:self.nall_channels] = [] if self.ipmarker_server is not None: mark = self.insert_ip_markers(mark) ndata = numpy.array(data) ndata = ndata.reshape((self.stdblocksize,self.nChannels)) return ndata, mark def insert_ip_markers(self, mark): while True: if not None in self.ip_lastmarker: m, t = self.ip_lastmarker self.ip_lastmarker = (None, None) else: m, t = self.ipmarker_server.read() if m is None or t is None: break time_index = self.time2index(t) mark_index = self.mark2index(m) if time_index > len(mark)-1: self.ip_lastmarker = (m, t) break elif time_index >= 0 and time_index < len(mark): mark[time_index] = mark_index else: warnings.warn("Index did not fit: %d (%d, %s)" % (time_index, mark_index, self.markerNames[mark_index])) return mark def mark2index(self, m): if not self.markerids.has_key(m): new = self.new_marker_id() self.markerids[m] = new self.markerNames[new] = m # print("added new marker %s with id %d" % (m, new)) return self.markerids[m] def time2index(self, t): index = ((t-self.timestamp)*self.stdblocksize)/self.block_length_ms() # make sure its not negative! # (a negative index means that the marker was delayed!) return max(0, index) def digital_marker(self, raw_value): if raw_value == self.dig_lastmarker: value = -1 else: m = raw_value & (self.dig_lastmarker^0xffff) smarker = (m & 0xff) rmarker = (m & 0xff00) >> 8 if smarker != 0: value = self.markerids[str("S%d" % smarker)] elif rmarker != 0: value = self.markerids[str("R%d" % rmarker)] else: value = -1 self.dig_lastmarker = raw_value return value
class EEGClientUsb(AbstractStreamReader): """ Acquire raw streamed eeg-data from usb-acquisition submodule This implementation uses the usb1 module, available from Pip/easy_install. usb1 is used to wrap calls to the libusbx c-library. """ def __init__(self, ipmarker_server=None, **kwargs): """ currently no parameter """ if usb_warning: warnings.warn("The usb_acquisition Module could not be imported!") super(EEGClientUsb, self).__init__(**kwargs) self.all_channels = ['Fp1', 'Fp2', 'F7', 'F3', 'Fz', 'F4', 'F8', 'FC5',\ 'FC1', 'FC2', 'FC6', 'T7', 'C3', 'Cz', 'C4', 'T8',\ 'TP9', 'CP5', 'CP1', 'CP2', 'CP6', 'TP10', 'P7',\ 'P3', 'Pz', 'P4', 'P8', 'PO9', 'O1', 'Oz', 'O2',\ 'PO10', 'AF7', 'AF3', 'AF4', 'AF8', 'F5', 'F1',\ 'F2', 'F6', 'FT9', 'FT7', 'FC3', 'FC4', 'FT8',\ 'FT10', 'C5', 'C1', 'C2', 'C6', 'TP7', 'CP3',\ 'CPz', 'CP4', 'TP8', 'P5', 'P1', 'P2', 'P6',\ 'PO7', 'PO3', 'POz', 'PO4', 'PO8', 'Fpz', 'F9',\ 'AFF5h', 'AFF1h', 'AFF2h', 'AFF6h', 'F10', 'FTT9h',\ 'FTT7h', 'FCC5h', 'FCC3h', 'FCC1h', 'FCC2h',\ 'FCC4h', 'FCC6h', 'FTT8h', 'FTT10h', 'TPP9h',\ 'TPP7h', 'CPP5h', 'CPP3h', 'CPP1h', 'CPP2h',\ 'CPP4h', 'CPP6h', 'TPP8h', 'TPP10h', 'POO9h',\ 'POO1', 'POO2', 'POO10h', 'Iz', 'AFp1', 'AFp2',\ 'FFT9h', 'FFT7h', 'FFC5h', 'FFC3h', 'FFC1h',\ 'FFC2h', 'FFC4h', 'FFC6h', 'FFT8h', 'FFT10h',\ 'TTP7h', 'CCP5h', 'CCP3h', 'CCP1h', 'CCP2h',\ 'CCP4h', 'CCP6h', 'TTP8h', 'P9', 'PPO9h', 'PPO5h',\ 'PPO1h', 'PPO2h', 'PPO6h', 'PPO10h', 'P10', 'I1',\ 'OI1h', 'OI2h', 'I2'] self.ipmarker_server = ipmarker_server self.ip_lastmarker = (None, None) self._dSamplingInterval = 5000 self._channelNames = None self._markerids = dict() self._markerNames = dict() self.marker_id_counter = 0 self._stdblocksize = 100 self.fmt = None self.channelids = None self.resolutions = None self.nChannels = None self.callbacks = list() self.raw_data = list() self.timestamp = 0 self.dig_lastmarker = 0 self.acquisition = BUASubprocess() self.acquisition.start() self.connect() @property def dSamplingInterval(self): return self._dSamplingInterval @property def stdblocksize(self): return self._stdblocksize @property def markerids(self): return self._markerids @property def channelNames(self): return self._channelNames @property def markerNames(self): return self._markerNames def regcallback(self, func): self.callbacks.append(func) def block_length_ms(self): return (self.stdblocksize * 1000) / self.dSamplingInterval def disconnect(self): if self.ipmarker_server is not None: self.ipmarker_server.stop() self.ipmarker_server.join() self.acquisition.stop() self.acquisition.join(timeout=5) del self.acquisition def new_marker_id(self): self.marker_id_counter += 1 return self.marker_id_counter def connect(self, verbose=False): while self.acquisition.nchannels.value < 0: if not self.acquisition.is_alive(): raise IOError, "Acquisition quit early!" time.sleep(.1) self.nChannels = self.acquisition.nchannels.value if self.nChannels == 0: raise IOError, "No Amplifiers found! Switch them on?" # generate all possible marker names and ids self._markerids['null'] = 0 for s in range(1, 256, 1): self._markerids[str('S%d' % s)] = self.new_marker_id() for r in range(1, 256, 1): self._markerids[str('R%d' % r)] = self.new_marker_id() # generate reverse mapping for k, v in zip(self._markerids.iterkeys(), self._markerids.itervalues()): self._markerNames[v] = k # select channelnames self._channelNames = self.all_channels[:self.nChannels] # calculate raw-data threshold while self.acquisition.nextra_channels.value < 0 \ or self.acquisition.nall_channels < 0: time.sleep(.1) self.nextra_channels = self.acquisition.nextra_channels.value self.nall_channels = self.acquisition.nall_channels.value self.min_raw_data = self.stdblocksize * self.nall_channels def read(self, nblocks=1, verbose=False): readblocks = 0 while (readblocks < nblocks or nblocks == -1): # get enough raw data blocks self.gather_enough_data() # split data and marker in seperate arrays ndsamples, ndmarkers = self.separate() for f in self.callbacks: f(ndsamples, ndmarkers) readblocks += 1 return readblocks def gather_enough_data(self): """ gets enough data to generate a block of size stdblocksize in channel and markers """ while len(self.raw_data) < self.min_raw_data: data, timestamp = self.acquisition.read() if self.fmt is None: self.fmt = str("%dh" % (len(data) / 2)) values = struct.unpack(self.fmt, data) self.raw_data.extend(values) self.timestamp = timestamp - self.block_length_ms() def separate(self): """ separates the raw-data into the data- and marker-channels """ packet = self.raw_data[0:self.min_raw_data] self.raw_data[0:self.min_raw_data] = [] # example block-layout for 32 channels: # [marker:1][reserved:4][nchannels data:32] :|| data = list() mark = list() for i in range(self.stdblocksize): mark.append(self.digital_marker(packet[0])) data.extend(packet[self.nextra_channels:self.nextra_channels + self.nChannels]) packet[0:self.nall_channels] = [] if self.ipmarker_server is not None: mark = self.insert_ip_markers(mark) ndata = numpy.array(data) ndata = ndata.reshape((self.stdblocksize, self.nChannels)) return ndata, mark def insert_ip_markers(self, mark): while True: if not None in self.ip_lastmarker: m, t = self.ip_lastmarker self.ip_lastmarker = (None, None) else: m, t = self.ipmarker_server.read() if m is None or t is None: break time_index = self.time2index(t) mark_index = self.mark2index(m) if time_index > len(mark) - 1: self.ip_lastmarker = (m, t) break elif time_index >= 0 and time_index < len(mark): mark[time_index] = mark_index else: warnings.warn( "Index did not fit: %d (%d, %s)" % (time_index, mark_index, self.markerNames[mark_index])) return mark def mark2index(self, m): if not self.markerids.has_key(m): new = self.new_marker_id() self.markerids[m] = new self.markerNames[new] = m # print("added new marker %s with id %d" % (m, new)) return self.markerids[m] def time2index(self, t): index = ( (t - self.timestamp) * self.stdblocksize) / self.block_length_ms() # make sure its not negative! # (a negative index means that the marker was delayed!) return max(0, index) def digital_marker(self, raw_value): if raw_value == self.dig_lastmarker: value = -1 else: m = raw_value & (self.dig_lastmarker ^ 0xffff) smarker = (m & 0xff) rmarker = (m & 0xff00) >> 8 if smarker != 0: value = self.markerids[str("S%d" % smarker)] elif rmarker != 0: value = self.markerids[str("R%d" % rmarker)] else: value = -1 self.dig_lastmarker = raw_value return value