def initialize(self):
    self.debug=self.setting['debug'] == "true"
    print "Debug: ", self.debug
    self.stream_type=self.setting['Stream type']
    # total channels for all streams
    self.channelCount = 0
    
    all_streams = self.setting['Get all streams'] == "true"
    
    self.overcomeCheck = self.setting['Overcome code check'] == "true"
     
    self.stream_name=self.setting['Stream name'] # in case !all_streams
    
    print "Looking for streams of type: " + self.stream_type
    
    streams = resolve_stream('type',self.stream_type)
    print "Nb streams: " + str( len(streams))
    
    if not all_streams:
      print "Will only select (first) stream named: " + self.stream_name
      self.nb_streams = 1
    else:
      self.nb_streams = len(streams)

    # create inlets to read from each stream
    self.inlets = []
    # retrieve also corresponding StreamInfo for future uses (eg sampling rate)
    self.infos = []
    
    # save inlets and info + build signal header
    for stream in streams:
      # do not set max_buflen because we *should not* be spammed by values
      inlet = StreamInlet(stream, max_buflen=1)
      info = inlet.info()
      name = info.name()
      print "Stream name: " + name
      # if target one stream, ignore false ones
      if not all_streams and name != self.stream_name:
        continue
      print "Nb channels: " + str(info.channel_count())
      self.channelCount += info.channel_count()
      stream_freq = info.nominal_srate()
      print "Sampling frequency: " + str(stream_freq)
      if  stream_freq != 0:
        print "WARNING: Wrong stream?"
      
      self.inlets.append(inlet)
      self.infos.append(info)
      
      # if we're still here when we target a stream, it means we foand it
      if not all_streams:
        print "Found target stream"
        break

    # we need at least one stream before we let go
    if self.channelCount <= 0:
      raise Exception("Error: no stream found.")
    
    # we append to the box output a stimulation header. This is just a header, dates are 0.
    self.output[0].append(OVStimulationHeader(0., 0.))
class BetaInlet(object):
    def __init__(self):
        print("looking for an EEG stream...")
        streams = resolve_byprop("type", "EEG")

        # create a new inlet to read from the stream
        proc_flags = proc_clocksync | proc_dejitter | proc_monotonize
        self.inlet = StreamInlet(streams[0], processing_flags=proc_flags)

        # The following is an example of how to read stream info
        stream_info = self.inlet.info()
        stream_Fs = stream_info.nominal_srate()
        stream_xml = stream_info.desc()
        chans_xml = stream_xml.child("channels")
        chan_xml_list = []
        ch = chans_xml.child("channel")
        while ch.name() == "channel":
            chan_xml_list.append(ch)
            ch = ch.next_sibling("channel")
        self.channel_names = [ch_xml.child_value("label") for ch_xml in chan_xml_list]
        print("Reading from inlet named {} with channels {} sending data at {} Hz".format(stream_info.name(),
                                                                                          self.channel_names, stream_Fs))

    def update(self):
        max_samps = 3276*2
        data = np.nan * np.ones((max_samps, len(self.channel_names)), dtype=np.float32)
        _, timestamps = self.inlet.pull_chunk(max_samples=max_samps, dest_obj=data)
        data = data[:len(timestamps), :]
        print("Beta inlet retrieved {} samples.".format(len(timestamps)))
        return data, np.asarray(timestamps)
Example #3
0
  def initialize(self):
    self.initLabel = 0
    self.debug=self.setting['debug'] == "true"
    print "Debug: ", self.debug
    self.stream_type=self.setting['Stream type']
    self.stream_name=self.setting['Stream name'] 
    # total channels for all streams
    self.channelCount = 0
    #self.stream_name=self.setting['Stream name'] # in case !all_streams
    print "Looking for streams of type: " + self.stream_type
    streams = resolve_stream('type',self.stream_type)
    print "Nb streams: " + str( len(streams))
    self.nb_streams = len(streams)
    if self.nb_streams == 0:
      raise Exception("Error: no stream found.")
    self.inlet = StreamInlet(streams[0], max_buflen=1)
    self.info = self.inlet.info()
    self.channelCount = self.info.channel_count()
    print "Stream name: " + self.info.name()
    stream_freq = self.info.nominal_srate()
    if stream_freq != 0:
	  raise Exception("Error: no irregular stream found.")
    # we append to the box output a stimulation header. This is just a header, dates are 0.
    self.output[0].append(OVStimulationHeader(0., 0.))
    self.init = False
Example #4
0
class LSLInlet:
    def __init__(self, name=LSL_STREAM_NAMES[2], max_chunklen=8, n_channels=20):
        streams = resolve_byprop('name', name, timeout=LSL_RESOLVE_TIMEOUT)
        self.inlet = None
        self.dtype = 'float64'
        if len(streams) > 0:
            self.inlet = StreamInlet(streams[0], max_buflen=1, max_chunklen=max_chunklen)
            # self.dtype = fmt2string[self.inlet.info().channel_format()]
            print(self.dtype)
        self.n_channels = n_channels if n_channels else self.inlet.info().channel_count()

    def get_next_chunk(self):
        # get next chunk
        chunk, timestamp = self.inlet.pull_chunk()
        # convert to numpy array
        chunk = np.array(chunk, dtype=self.dtype)
        # return first n_channels channels or None if empty chunk
        return chunk[:, :self.n_channels] if chunk.shape[0] > 0 else None

    def update_action(self):
        pass

    def save_info(self, file):
        with open(file, 'w') as f:
            f.write(self.inlet.info().as_xml())

    def get_frequency(self):
        return self.inlet.info().nominal_srate()

    def get_n_channels(self):
        return self.n_channels

    def get_channels_labels_bad(self):
        time.sleep(0.001)
        labels = []
        ch = self.inlet.info().desc().child("channels").child("channel")
        for k in range(self.get_n_channels()):
            labels.append(ch.child_value("label"))
            ch = ch.next_sibling()
        return

    def get_channels_labels(self):
        return ch_names[:self.n_channels]

    def disconnect(self):
        del self.inlet
        self.inlet = None
Example #5
0
 def __init__(self, name=LSL_STREAM_NAMES[2], max_chunklen=8, n_channels=20):
     streams = resolve_byprop('name', name, timeout=LSL_RESOLVE_TIMEOUT)
     self.inlet = None
     self.dtype = 'float64'
     if len(streams) > 0:
         self.inlet = StreamInlet(streams[0], max_buflen=1, max_chunklen=max_chunklen)
         # self.dtype = fmt2string[self.inlet.info().channel_format()]
         print(self.dtype)
     self.n_channels = n_channels if n_channels else self.inlet.info().channel_count()
Example #6
0
	def __init__(self):
		app.Canvas.__init__(self, title='Use your wheel to zoom!',
							keys='interactive')

		
		# first resolve an EEG stream on the lab network
		print("looking for an EEG stream...")
		streams = resolve_stream('name', 'RandomSpehricalData')
		streamInfo = streams[0]
		# create a new inlet to read from the stream
		self.inlet = StreamInlet(streamInfo)
		# Number of cols and rows in the table.
		self.nrows = streamInfo.channel_count()
		
		n = streamInfo.nominal_srate()
		ncols = 1

		# Number of signals.
		m = self.nrows*ncols

		# Various signal amplitudes.
		amplitudes = .1 + .2 * np.random.rand(m, 1).astype(np.float32)

		# Generate the signals as a (m, n) array.
		self.y = amplitudes * np.random.randn(m, n).astype(np.float32)
		
		color = np.repeat(np.random.uniform(size=(m, 3), low=.5, high=.9),
						  n, axis=0).astype(np.float32)


		# Signal 2D index of each vertex (row and col) and x-index (sample index
		# within each signal).
		index = np.c_[np.repeat(np.repeat(np.arange(ncols), self.nrows), n),
					  np.repeat(np.tile(np.arange(self.nrows), ncols), n),
					  np.tile(np.arange(n), m)].astype(np.float32)


		self.program = gloo.Program(VERT_SHADER, FRAG_SHADER)
		self.program['a_position'] = self.y.reshape(-1, 1)
		self.program['a_color'] = color
		self.program['a_index'] = index
		self.program['u_scale'] = (1., 1.)
		self.program['u_size'] = (self.nrows, ncols)
		self.program['u_n'] = n

		gloo.set_viewport(0, 0, *self.physical_size)

		self._timer = app.Timer('auto', connect=self.on_timer, start=True)

		gloo.set_state(clear_color='black', blend=True,
					   blend_func=('src_alpha', 'one_minus_src_alpha'))
		
		self.sampleFromLSL = None
		
		self.show()
Example #7
0
  def __init__(self, stream_type='PPG', stream_id=None, buflen=5):
    """
    stream_type: LSL type of the stream to check
    stream_id: will select specifically one stream based on its name "[stream_type]_[stream_id]"
    """
    # first resolve said stream type on the network
    streams = resolve_stream('type',stream_type)
    self.nb_streams = 0
    
    if len(streams) < 1:
      raise NameError('LSLTypeNotFound')
      
    print "Detecting", len(streams), stream_type, "streams"
    
    # create inlets to read from each stream
    self.inlets = []
    # retrieve also corresponding StreamInfo for future uses (eg sampling rate)
    self.infos = []
    
    for stream in streams:
      inlet = StreamInlet(stream, max_buflen=buflen)
      info = inlet.info()
      # if an ID is specified, will look only for it, otherwise add everything
      if stream_id is not None:
	if info.name() == stream_type + "_" + str(stream_id):
	  # check that there is a unique stream with this name to stop right there any ambiguity
	  if self.nb_streams > 0:
	    raise NameError('LSLDuplicateStreamName')
	  else:
	    self.inlets.append(inlet)
	    self.infos.append(info)
	    self.nb_streams = self.nb_streams + 1
      else:
	self.inlets.append(inlet)
	self.infos.append(info)
	self.nb_streams = self.nb_streams + 1
    
    if stream_id and self.nb_streams < 1:
      raise NameError('LSLStreamNameNotFound')
    
    # init list of samples
    self.samples = [] * self.nb_streams
class MarkerInlet(object):
    def __init__(self):
        self.task = {'phase':'precue', 'class':1, 'target':1}
        print("Looking for stream with type Markers")
        streams = resolve_bypred("type='Markers'", minimum=1)
        proc_flags = 0  # Marker events are relatively rare. No need to post-process.
        self.inlet = StreamInlet(streams[0], processing_flags=proc_flags)
        # The following is an example of how to read stream info
        stream_info = self.inlet.info()
        stream_Fs = stream_info.nominal_srate()
        stream_xml = stream_info.desc()
        chans_xml = stream_xml.child("channels")
        chan_xml_list = []
        ch = chans_xml.child("channel")
        while ch.name() == "channel":
            chan_xml_list.append(ch)
            ch = ch.next_sibling("channel")
        stream_ch_names = [ch_xml.child_value("label") for ch_xml in chan_xml_list]
        print("Reading from inlet named {} with channels {}".format(stream_info.name(), stream_ch_names))

    def update(self):
        marker_samples, marker_timestamps = self.inlet.pull_chunk(timeout=0.0)
        if (marker_timestamps):
            [phase_str, class_str, targ_str] = marker_samples[-1][0].split(', ')
            if phase_str in ['TargetCue']:
                self.task['phase'] = 'cue'
            elif phase_str in ['GoCue']:
                self.task['phase'] = 'go'
            elif phase_str in ['Miss', 'Hit']:
                self.task['phase'] = 'evaluate'
            elif phase_str[:8] == 'NewTrial':
                self.task['phase'] = 'precue'
            else:
                print(phase_str)
            self.task['class'] = int(class_str.split(' ')[1])
            self.task['target'] = int(targ_str.split(' ')[1])
            print("Marker inlet updated with task {}".format(self.task))
 def __init__(self):
     self.task = {'phase':'precue', 'class':1, 'target':1}
     print("Looking for stream with type Markers")
     streams = resolve_bypred("type='Markers'", minimum=1)
     proc_flags = 0  # Marker events are relatively rare. No need to post-process.
     self.inlet = StreamInlet(streams[0], processing_flags=proc_flags)
     # The following is an example of how to read stream info
     stream_info = self.inlet.info()
     stream_Fs = stream_info.nominal_srate()
     stream_xml = stream_info.desc()
     chans_xml = stream_xml.child("channels")
     chan_xml_list = []
     ch = chans_xml.child("channel")
     while ch.name() == "channel":
         chan_xml_list.append(ch)
         ch = ch.next_sibling("channel")
     stream_ch_names = [ch_xml.child_value("label") for ch_xml in chan_xml_list]
     print("Reading from inlet named {} with channels {}".format(stream_info.name(), stream_ch_names))
    def __init__(self):
        print("looking for an EEG stream...")
        streams = resolve_byprop("type", "EEG")

        # create a new inlet to read from the stream
        proc_flags = proc_clocksync | proc_dejitter | proc_monotonize
        self.inlet = StreamInlet(streams[0], processing_flags=proc_flags)

        # The following is an example of how to read stream info
        stream_info = self.inlet.info()
        stream_Fs = stream_info.nominal_srate()
        stream_xml = stream_info.desc()
        chans_xml = stream_xml.child("channels")
        chan_xml_list = []
        ch = chans_xml.child("channel")
        while ch.name() == "channel":
            chan_xml_list.append(ch)
            ch = ch.next_sibling("channel")
        self.channel_names = [ch_xml.child_value("label") for ch_xml in chan_xml_list]
        print("Reading from inlet named {} with channels {} sending data at {} Hz".format(stream_info.name(),
                                                                                          self.channel_names, stream_Fs))
Example #11
0
import sys
sys.path.append('..')
from pylsl import StreamInlet, resolve_stream

# first resolve a marker stream on the lab network
print("looking for a marker stream...")
streams = resolve_stream('type', 'Markers')

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])

while True:
        # get a new sample (you can also omit the timestamp part if you're not interested in it)
        sample, timestamp = inlet.pull_sample()
        print("Event: ", sample[0], " at time: ", timestamp)
Example #12
0
class EEGStateAdapter:

    # n_timepoints
    def __init__(self,
                 n_freq=30,
                 n_chan=8,
                 eeg_feed_rate=250,
                 samples_per_output=1,
                 spectrogram_timespan=10,
                 n_spectrogram_timepoints=10):
        self.num_channels = n_chan
        self.num_freqs = n_freq
        self.n_spectrogram_timepoints = n_spectrogram_timepoints
        self.eeg_fifo_len = spectrogram_timespan * eeg_feed_rate  #assuming spectrogram_timespan is in seconds

        # Verify this is an int, then cast to int
        assert self.eeg_fifo_len.is_integer(), "Spectrogram timespan (" + str(
            spectrogram_timespan) + ") * SPS (" + str(
                eeg_feed_rate) + ") must be an integer, is: " + str(
                    self.eeg_fifo_len)
        self.eeg_fifo_len = int(self.eeg_fifo_len)

        self.cache_interval = int(samples_per_output)
        self.eeg_thread_event = Event()
        self.eeg_data_cache = list()
        self.eeg_fifo = deque([], maxlen=self.eeg_fifo_len)

        # Init other adapters
        self.imprintAdapter = ImprintAdapter(dbg=False)
        self.rpvAdapter = RewardPunishAdapter(dbg=False)

        self.rpv_data_dict = dict()
        self.imprint_data_dict = dict()

    def sync_state_labels(self):
        '''
        Grab all available labels data from imprint and rpv adapters and sync 
        timestamps.
        '''
        '''
        syncing data is basically a matter of comparing timestamps and associating the 
        closest ones. This should be easy if we are storing lots of data...
        
        we can collect it all to be able to associate the closest, then we can 
        clear cache after a second or so.
        '''

        # Sync rpv data
        self.rpv_data_dict = self.sync_data(self.eeg_data_cache,
                                            self.rpvAdapter.get_data())

        # Sync Imprint data
        self.imprint_data_dict = self.sync_data(self.eeg_data_cache,
                                                self.imprintAdapter.get_data())

    def retrieve_latest_data(self):
        '''
        For V,F - T,F - V,B - PI,B
        '''
        if len(self.eeg_data_cache) > 0:

            #==============================================================================
            #             data = (
            #              np.asarray([d[0] for d in self.eeg_data_cache]),
            #              np.ones((1,1,10,240)), #np.empty(0),#[], #
            #              np.asarray([(1,0)]),# np.empty(0),#[], #np.ones((1,1,10,240)),
            #              np.ones((1,1,10,240)),#np.empty(0),#[], #np.ones((1,1,10,240)),
            #              np.asarray([44])
            #                      #np.empty(0)#[]
            #              )
            #             self.clear_caches()
            #             return data
            #==============================================================================

            # Sync timestamps
            self.sync_state_labels()

            # remove timestamps from eeg data
            eeg_data = np.asarray([d[0] for d in self.eeg_data_cache])

            # setup structure for tensorflow model

            rpv_inputs = np.asarray(self.rpv_data_dict['inputs'])
            rpv_labels = np.asarray(self.rpv_data_dict['labels'])

            assert rpv_inputs.shape[0] == rpv_labels.shape[
                0]  #TODO error string here

            imp_inputs = np.asarray(self.imprint_data_dict['inputs'])
            imp_labels = np.asarray(
                self.imprint_data_dict['labels'])  #TODO error

            assert imp_inputs.shape[0] == imp_labels.shape[0]

            data = eeg_data, rpv_inputs, rpv_labels, imp_inputs, imp_labels

            # clear caches
            self.clear_caches()

            return data
        else:
            return ([], [], [], [], [])

    def launch_eeg_adapter(self, manual_stream_select=True):

        self.imprintAdapter.launch_imprint_adapter()
        self.rpvAdapter.launch_rpv_adapter()

        print("Resolving EEG marker stream...")
        streams = resolve_stream('type', 'PERIODO')
        snum = 0
        if manual_stream_select:
            for i, s in enumerate(streams):
                print(i, s.name())
            snum = input("Select EEGStateAdapter stream: ")
        self.inlet = StreamInlet(streams[int(snum)])
        # launch thread
        self.eeg_thread_event.set()
        thread = Thread(target=self.eeg_rx_thread)
        thread.start()

    def stop_eeg_thread(self):
        self.imprintAdapter.stop_imprint_thread()
        self.rpvAdapter.stop_rpv_thread()
        self.eeg_thread_event.clear()

    def clear_caches(self, clear_subadapters=False):
        self.rpv_data_dict = dict()
        self.imprint_data_dict = dict()
        self.eeg_data_cache = list()
        if clear_subadapters:
            self.rpvAdapter.get_data()
            self.imprintAdapter.get_data()

    def eeg_rx_thread(self):
        '''
        Receiver will need to select correct stream, then continuously accept and 
        process commands as they arrive.
        '''

        rx_counter = 0
        fifo_idx = np.linspace(0, self.eeg_fifo_len - 1,
                               self.n_spectrogram_timepoints).astype(int)
        while self.eeg_thread_event.isSet():

            # get command
            eeg_periodo, timestamp = self.inlet.pull_sample(timeout=1)
            if eeg_periodo == None:
                continue  #if timed out, check if thread is sitll alive

            assert len(
                eeg_periodo
            ) == self.num_channels * self.num_freqs  #lsl output is flattened periodo

            # add new periodogram to fifo
            self.eeg_fifo.append(eeg_periodo)

            # inc rx count
            rx_counter += 1

            # cache if apt.
            if (len(self.eeg_fifo)
                    == self.eeg_fifo_len) and (rx_counter % self.cache_interval
                                               == 0):
                self.eeg_data_cache += [
                    (np.asarray(self.eeg_fifo)[fifo_idx, :], timestamp)
                ]

    def sync_data(self, _inputs, labels):
        '''
        assume inputs and labels both lists of tuples with first val value, second val timestamp.
        
        assume we have many more inputs than labels
        
        strategy is to search for the closest label for each input, also we can only,
        use one input per label so if the next closest is further than a removed one 
        then we would like to collect statistics on that.
        
        '''

        ts_diffs = []
        synced_inputs = []
        synced_outputs = []

        # copy inputs
        inputs = list(_inputs)
        previously_used = list()

        # loop over labels to find closest input
        for label in labels:

            # extract timestamps to array
            inputs_ts = np.asarray([i[1] for i in inputs])

            # extract label ts
            label_ts = label[1]

            # find nearest input to label
            inputs_ts = abs(inputs_ts - label_ts)
            amin = np.argmin(inputs_ts)

            # check if the value at this index has been used before; if so, skip the label (undefined behaviour)
            if amin in previously_used: continue
            previously_used.append(amin)

            closest_input = inputs[amin][0]

            # collect metrics
            ts_diffs += [inputs_ts[amin]]

            # add pair
            #synced_pairs += [(closest_input, label[0])]
            synced_inputs += [closest_input]
            synced_outputs += [label[0]]

            # delete used input


#            del inputs[amin]

        return {
            'inputs': synced_inputs,
            'labels': synced_outputs,
            'diffs': ts_diffs
        }
import numpy as np
from pylsl import StreamInlet, resolve_stream, local_clock
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui


plot_duration = 2.0


# first resolve an EEG stream on the lab network
print("looking for an EEG stream...")
streams = resolve_stream('type', 'EEG')

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])

# Create the pyqtgraph window
win = pg.GraphicsWindow()
win.setWindowTitle('LSL Plot ' + inlet.info().name())
plt = win.addPlot()
plt.setLimits(xMin=0.0, xMax=plot_duration, yMin=-1.0 * (inlet.channel_count - 1), yMax=1.0)

t0 = [local_clock()] * inlet.channel_count
curves = []
for ch_ix in range(inlet.channel_count):
    curves += [plt.plot()]


def update():
    global inlet, curves, t0
class Recorder():
    def __init__(self,
                 config,
                 maxbuffer_size,
                 q_from_display_to_recorder=None):

        # initialize basic configuration
        self.config = config
        self.maxbuffer_size = maxbuffer_size
        self.q_from_display_to_recorder = q_from_display_to_recorder
        #self.q_from_recorder_to_decoder = Queue()

        # private variables, changed by commands form q
        self.inlet_state = False
        # patient states:
        # -1 - none (not recording)
        # 0 - rest
        # 1 - objects
        # 2 - actions
        self.patient_state = 0
        # picture state:
        # 0 - none
        # 1 - start
        # 2 - stop
        self.picture_state = 0
        self.pause = 0
        self.patient_state_paused = -1
        self.picture_pause = 0

        # initialize configuration based on saving method (though buffer or without it)
        self.memory = [[], [], []]
        self.picture_indices = [[], [], []]
        self.pause_mark = False

        self.index_picture_start = -1
        self.index_picture_stop = -1
        self.index_pause = -1
        self.picture_end = False

        # resolve lsl stream
        stream_name = self.config['general']['lsl_stream_name']
        streams = resolve_stream('name', stream_name)
        self._printm('Resolving stream \'{}\', {} streams found'.format(
            stream_name, len(streams)))
        self.inlet = StreamInlet(streams[0], self.maxbuffer_size)
        self._printm('Stream resolved')

    # not used
    def record(self):
        self._printm(
            'Start recording, if \'Recording...\' progress bar is not filling, check lsl input stream'
        )

        self._resolve_q()
        with Bar('Recording...', max=1000) as bar:
            while self.inlet_state:
                self._resolve_q()
                sample, timestamp = self.inlet.pull_sample(timeout=0.0)
                if bar.index < 999:
                    bar.next()
                elif bar.index == 999:
                    bar.next()
                    bar.finish()

                # if patient state is 'none' - skip
                if self.patient_state == -1:
                    continue
                elif self.pause:
                    self.pause_mark = True
                    continue

                # if timestamp exists, concatenate sample with previous data
                if timestamp:
                    sample_index = len(self.memory[self.patient_state])
                    if self.picture_state == 1:
                        self.index_picture_start = (sample_index,
                                                    self.picture_state)
                    elif self.picture_state == 2:
                        self.index_picture_stop = (sample_index,
                                                   self.picture_state)
                        self.picture_end = True
                    if self.pause_mark:
                        self.index_pause = (sample_index - 1,
                                            self.picture_state)
                        self.pause_mark = False

                    sample = np.reshape(np.asarray(sample), (1, 69))
                    timestamp = np.array([[timestamp]])
                    picture_type_array = np.array([[self.patient_state]])
                    picture_state = np.array([[self.picture_state]])
                    self.picture_state = 0
                    picture_pause = np.array([[self.picture_pause]])
                    self.picture_pause = 0
                    big_sample = np.concatenate(
                        (sample, timestamp, picture_type_array, picture_pause,
                         picture_state),
                        axis=1)
                    self.memory[self.patient_state].append(big_sample)

                    if self.picture_end:
                        if self._good_picture():
                            self.picture_indices.append(
                                (self.index_picture_start,
                                 self.index_picture_stop))
                            #ecog_picture = np.vstack(self.memory[self.patient_state][self.indx_picture_begining:])

        self._printm('Stop recording')
        t1 = time.time()
        self._save()
        t2 = time.time()
        self._printm('Data saved: {}s:'.format(t2 - t1))

    def _good_picture(self):
        same_patient_state = self.index_picture_start[
            1] == self.index_picture_stop[1]
        pause_not_inside_picture = not (self.index_picture_start[1] == self.index_pause[1] and \
                                self.index_picture_start[0] <= self.index_pause[0])
        return same_patient_state and pause_not_inside_picture

    # not used
    def _save(self):
        experiment_data_path = Path(
            self.config['paths']['experiment_data_path'])
        dataset_width = self.config['recorder'].getint('dataset_width')
        groups = self.config['recorder']['group_names'].split(' ')
        with h5py.File(experiment_data_path, 'a') as file:
            for i in range(len(self.memory)):
                if len(self.memory[i]) > 0:
                    stacked_data = np.vstack(self.memory[i])
                    stacked_indices = np.vstack(self.picture_indices[i])
                    file[groups[i] + '/raw_data'] = stacked_data
                    file[groups[i] + '/picture_indices'] = stacked_indices
                    self.memory[i] = []
                    self.picture_indices[i] = []
                    self._printm('Saved {}, {}, {} pictures'.format(
                        groups[i], stacked_data.shape,
                        stacked_indices.shape[0]))
                else:
                    empty_shape = (0, dataset_width)
                    file.create_dataset(groups[i] + '/raw_data', empty_shape)
                    file.create_dataset(groups[i] + '/picture_indices', (0, 2))
                    self._printm('Saved {}, {}'.format(groups[i], empty_shape))
            file.create_dataset('fs',
                                data=np.array(
                                    self.config['recorder'].getint('fs')))

    # resolve commands from Display object to navigate recording of data
    def _resolve_q(self):
        while not self.q_from_display_to_recorder.empty():
            key, value = self.q_from_display_to_recorder.get()
            if self.config['general'].getboolean('debug_mode'):
                pass
                #self._printm('key: {}, value: {}'.format(key, value))
            if key == 'inlet_state':
                self.inlet_state = value
            elif key == 'patient_state':
                self.patient_state = value
            elif key == 'picture_state':
                self.picture_state = value
            elif key == 'pause':
                self.pause = value
            else:
                self._printm('wrong key in queue: {}'.format(key))

    def _printm(self, message):
        print('{} {}: '.format(time.strftime('%H:%M:%S'),
                               type(self).__name__) + message)
import sys

sys.path.append(
    '..')  # help python find pylsl relative to this example program
from pylsl import StreamInlet, resolve_stream

# first resolve an EEG stream on the lab network
print("looking for an ECG stream...")
streams = resolve_stream('type', 'ECG')

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])

while True:
    # get a new sample (you can also omit the timestamp part if you're not interested in it)
    chunk, timestamps = inlet.pull_chunk()
    if timestamps:
        print(timestamps, chunk)
Example #16
0
exptime = 900
dt_rate = 0.1

# allocating buffers
received_data_buf = np.zeros((numch, exptime*srate*1.2))
states_predicted_buf = np.zeros((1, exptime*srate*1.2))
pos = 0
pos_pred = 0


# first resolve an EEG stream on the lab network
print("looking for an EEG stream...")
streams = resolve_stream('type', 'Data')

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])

globalstart = time.time()

while (time.time() - globalstart < exptime):
    
    startwhile = time.time()

    chunk, timestamp = inlet.pull_chunk()
    np_ar_chunk = np.asarray(chunk)
    chunk_size = np_ar_chunk.shape[0]
    
    if chunk_size > 0:
        
        data_chunk_test = np_ar_chunk.T
        
cap.append_child_value("size", "54")
cap.append_child_value("labelscheme", "10-20")

# create outlet for the stream
outlet = StreamOutlet(info)

# (...normally here one might start sending data into the outlet...)

# === the following could run on another computer ===

# first we resolve a stream whose name is MetaTester (note that there are
# other ways to query a stream, too - for instance by content-type)
results = resolve_stream("name", "MetaTester")

# open an inlet so we can read the stream's data (and meta-data)
inlet = StreamInlet(results[0])

# get the full stream info (including custom meta-data) and dissect it
info = inlet.info()
print("The stream's XML meta-data is: ")
print(info.as_xml())
print("The manufacturer is: %s" % info.desc().child_value("manufacturer"))
print("Cap circumference is: %s" % info.desc().child("cap").child_value("size"))
print("The channel labels are as follows:")
ch = info.desc().child("channels").child("channel")
for k in range(info.channel_count()):
    print("  " + ch.child_value("label"))
    ch = ch.next_sibling()

time.sleep(3)
from pylsl import StreamInlet, resolve_stream
import time

numStreams = 3
# first resolve an EEG stream on the lab network
print("looking for an EEG stream...")
stream1 = resolve_stream('type', 'EEG')
stream2 = resolve_stream('type', 'AUX')
stream3 = resolve_stream('type', 'FFT')

# create a new inlet to read from the stream
inlet = StreamInlet(stream1[0])
inlet2 = StreamInlet(stream2[0])
inlet3 = StreamInlet(stream3[0])


def testLSLSamplingRates():
    print("Testing Sampling Rates...")
    start = time.time()
    numSamples1 = 0
    numSamples2 = 0
    numSamples3 = 0
    while time.time() < start + 5:
        # get a new sample (you can also omit the timestamp part if you're not
        # interested in it)
        for i in range(numStreams):
            if i == 0:
                chunk, timestamps = inlet.pull_chunk()
                if timestamps:
                    numSamples1 += 1
            elif i == 1:
Example #19
0
# first create a new stream info (here we set the name to BioSemi,
# the content-type to EEG, 8 channels, 100 Hz, and float-valued data) The
# last value would be the serial number of the device or some other more or
# less locally unique identifier for the stream as far as available (you
# could also omit it but interrupted connections wouldn't auto-recover)
fs = 1000
info = StreamInfo('python', 'EEG', 2)

# next make an outlet
outlet = StreamOutlet(info)

from pylsl import StreamInlet, resolve_stream
print('resolving stream')
streams = resolve_stream('name', 'matlab')
# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])
print('resolved')

t = 0
mean_time = 0
while True:
    #time.sleep(0.002)
    t += 1
    clock = local_clock()
    outlet.push_sample([0, 1])
    sample, timestamp = inlet.pull_sample(timeout=1)
    dt = local_clock() - clock
    mean_time += dt
    print(mean_time / t, dt)
    #time.sleep(0.001)
import bci_workshop_tools as BCIw  # Our own functions for the workshop


if __name__ == "__main__":

    """ 1. CONNECT TO EEG STREAM """

    # Search for active LSL stream
    print('Looking for an EEG stream...')
    streams = resolve_byprop('type', 'EEG', timeout=2)
    if len(streams) == 0:
        raise RuntimeError('Can\'t find EEG stream.')

    # Set active EEG stream to inlet and apply time correction
    print("Start acquiring data")
    inlet = StreamInlet(streams[0], max_chunklen=12)
    eeg_time_correction = inlet.time_correction()

    # Get the stream info, description, sampling frequency, number of channels
    info = inlet.info()
    description = info.desc()
    fs = int(info.nominal_srate())
    n_channels = info.channel_count()

    # Get names of all channels
    ch = description.child('channels').first_child()
    ch_names = [ch.child_value('label')]
    for i in range(1, n_channels):
        ch = ch.next_sibling()
        ch_names.append(ch.child_value('label'))
Example #21
0
   def initialize(self):           
      # settings are retrieved in the dictionary
      try:
        self.samplingFrequency = int(self.setting['Sampling frequency'])
      except:
        print "Sampling frequency not set or error while parsing."
        self.samplingFrequency = 0
      print "Sampling frequency: " + str(self.samplingFrequency)
      self.epochSampleCount = int(self.setting['Generated epoch sample count'])
      self.stream_type=self.setting['Stream type']
      # total channels for all streams
      self.channelCount = 0
      
      all_streams = self.setting['Get all streams'] == "true"
      self.stream_name=self.setting['Stream name'] # in case !all_streams
      
      print "Looking for streams of type: " + self.stream_type
      
      streams = resolve_stream('type',self.stream_type)
      print "Nb streams: " + str( len(streams))
      
      if not all_streams:
        print "Will only select (first) stream named: " + self.stream_name
        self.nb_streams = 1
      else:
        self.nb_streams = len(streams)

      # create inlets to read from each stream
      self.inlets = []
      # retrieve also corresponding StreamInfo for future uses (eg sampling rate)
      self.infos = []
      
      # save inlets and info + build signal header
      for stream in streams:
        inlet = StreamInlet(stream)
        info = inlet.info()
        name = info.name()
        print "Stream name: " + name
        # if target one stream, ignore false ones
        if not all_streams and name != self.stream_name:
          continue
        print "Nb channels: " + str(info.channel_count())
        self.channelCount += info.channel_count()
        stream_freq = info.nominal_srate()
        print "Sampling frequency: " + str(stream_freq)
        if self.samplingFrequency == 0:
          print "Set sampling frequency to:" + str(stream_freq)
          self.samplingFrequency = stream_freq
        elif self.samplingFrequency != stream_freq:
          print "WARNING: sampling frequency of current stream (" + str(stream_freq) + ") differs from option set to box (" + str(self.samplingFrequency) + ")."
        for i in range(info.channel_count()):
          self.dimensionLabels.append(name + ":" + str(i))
          
        # We must delay real inlet/info init because we may know the defifitive sampling frequency
        # limit buflen just to what we need to fill each chuck, kinda drift correction
        # TODO: not a very pretty code...
        buffer_length = int(ceil(float(self.epochSampleCount) / self.samplingFrequency))
        print "LSL buffer length: " + str(buffer_length)
        inlet = StreamInlet(stream, max_buflen=buffer_length)
        info = inlet.info()
        self.inlets.append(inlet)
        self.infos.append(info)
        
        # if we're still here when we target a stream, it means we foand it
        if not all_streams:
          print "Found target stream"
          break
 
      # we need at least one stream before we let go
      if self.channelCount <= 0:
        raise Exception("Error: no stream found.")
      
      # backup last values pulled in case pull(timeout=0) return None later
      self.last_values =  self.channelCount*[0]
      
      self.dimensionLabels += self.epochSampleCount*['']
      self.dimensionSizes = [self.channelCount, self.epochSampleCount]
      self.signalHeader = OVSignalHeader(0., 0., self.dimensionSizes, self.dimensionLabels, self.samplingFrequency)
      self.output[0].append(self.signalHeader)

      #creation of the first signal chunk
      self.endTime = 1.*self.epochSampleCount/self.samplingFrequency
      self.signalBuffer = numpy.zeros((self.channelCount, self.epochSampleCount))
      self.updateTimeBuffer()
      self.updateSignalBuffer()
Example #22
0
    ch.append_child_value("label",label)
    ch.append_child_value("unit","microvolts")
    ch.append_child_value("type","EEG")
info.desc().append_child_value("manufacturer","SCCN")
cap = info.desc().append_child("cap")
cap.append_child_value("name","EasyCap")
cap.append_child_value("size","54")
cap.append_child_value("labelscheme","10-20")

# create outlet for the stream
outlet = StreamOutlet(info)


# === the following could run on another computer ===

# resolve the stream and open an inlet
results = resolve_stream("name","MetaTester")
inlet = StreamInlet(results[0])
# get the full stream info (including custom meta-data) and dissect it
inf = inlet.info()
print "The stream's XML meta-data is: "
print inf.as_xml()
print "The manufacturer is: " + inf.desc().child_value("manufacturer")
print "The cap circumference is: " + inf.desc().child("cap").child_value("size")
print "The channel labels are as follows:" 
ch = inf.desc().child("channels").child("channel")
for k in range(info.channel_count()):
    print "  " + ch.child_value("label")
    ch = ch.next_sibling()

time.sleep(3)
Example #23
0
class LSLViewer():
    def __init__(self, stream, fig, axes, window, scale, dejitter=True):
        """Init"""
        self.stream = stream
        self.window = window
        self.scale = scale
        self.dejitter = dejitter
        self.inlet = StreamInlet(stream, max_chunklen=buf)
        self.filt = True

        info = self.inlet.info()
        description = info.desc()

        self.sfreq = info.nominal_srate()
        self.n_samples = int(self.sfreq * self.window)
        self.n_chan = info.channel_count()

        ch = description.child('channels').first_child()
        ch_names = [ch.child_value('label')]

        for i in range(self.n_chan):
            ch = ch.next_sibling()
            ch_names.append(ch.child_value('label'))

        self.ch_names = ch_names

        fig.canvas.mpl_connect('key_press_event', self.OnKeypress)
        fig.canvas.mpl_connect('button_press_event', self.onclick)

        self.fig = fig
        self.axes = axes

        sns.despine(left=True)

        self.data = np.zeros((self.n_samples, self.n_chan))
        self.times = np.arange(-self.window, 0, 1. / self.sfreq)
        impedances = np.std(self.data, axis=0)
        lines = []

        for ii in range(self.n_chan):
            line, = axes.plot(self.times[::subsample],
                              self.data[::subsample, ii] - ii,
                              lw=1)
            lines.append(line)
        self.lines = lines

        axes.set_ylim(-self.n_chan + 0.5, 0.5)
        ticks = np.arange(0, -self.n_chan, -1)

        axes.set_xlabel('Time (s)')
        axes.xaxis.grid(False)
        axes.set_yticks(ticks)

        ticks_labels = [
            '%s - %.1f' % (ch_names[ii], impedances[ii])
            for ii in range(self.n_chan)
        ]
        axes.set_yticklabels(ticks_labels)

        self.display_every = int(0.2 / (12 / self.sfreq))

        # self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
        #                          'bandpass')

        self.bf = firwin(32,
                         np.array([1, 40]) / (self.sfreq / 2.),
                         width=0.05,
                         pass_zero=False)
        self.af = [1.0]

        zi = lfilter_zi(self.bf, self.af)
        self.filt_state = np.tile(zi, (self.n_chan, 1)).transpose()
        self.data_f = np.zeros((self.n_samples, self.n_chan))

    def update_plot(self):
        k = 0
        while self.started:
            samples, timestamps = self.inlet.pull_chunk(timeout=1.0,
                                                        max_samples=12)
            if timestamps:
                if self.dejitter:
                    timestamps = np.float64(np.arange(len(timestamps)))
                    timestamps /= self.sfreq
                    timestamps += self.times[-1] + 1. / self.sfreq
                self.times = np.concatenate([self.times, timestamps])
                self.n_samples = int(self.sfreq * self.window)
                self.times = self.times[-self.n_samples:]
                self.data = np.vstack([self.data, samples])
                self.data = self.data[-self.n_samples:]
                #filt_samples, self.filt_state = lfilter(
                #    self.bf, self.af,
                #    samples,
                #    axis=0, zi=self.filt_state)
                filt_samples = mne.filter.filter_data(self.data,
                                                      256,
                                                      8,
                                                      12,
                                                      fir_design='firwin')
                #filt_samples = [math.sqrt(part.real**2 + part.imag**2) for part in filt_samples]
                self.data_f = np.vstack([self.data_f, filt_samples])
                self.data_f = self.data_f[-self.n_samples:]
                k += 1
                if k == self.display_every:

                    if self.filt:
                        plot_data = self.data_f
                    elif not self.filt:
                        plot_data = self.data - self.data.mean(axis=0)
                    for ii in range(self.n_chan):
                        self.lines[ii].set_xdata(self.times[::subsample] -
                                                 self.times[-1])
                        self.lines[ii].set_ydata(plot_data[::subsample, ii] /
                                                 self.scale - ii)
                        impedances = np.std(plot_data, axis=0)

                    ticks_labels = [
                        '%s - %.2f' % (self.ch_names[ii], impedances[ii])
                        for ii in range(self.n_chan)
                    ]
                    self.axes.set_yticklabels(ticks_labels)
                    self.axes.set_xlim(-self.window, 0)
                    self.fig.canvas.draw()
                    k = 0
            else:
                sleep(0.2)

    def onclick(self, event):
        print((event.button, event.x, event.y, event.xdata, event.ydata))

    def OnKeypress(self, event):
        if event.key == '/':
            self.scale *= 1.2
        elif event.key == '*':
            self.scale /= 1.2
        elif event.key == '+':
            self.window += 1
        elif event.key == '-':
            if self.window > 1:
                self.window -= 1
        elif event.key == 'd':
            self.filt = not (self.filt)

    def start(self):
        self.started = True
        self.thread = Thread(target=self.update_plot)
        self.thread.daemon = True
        self.thread.start()

    def stop(self):
        self.started = False
Example #24
0
print("looking for an EEG stream...")
streams = resolve_byprop('type', 'EEG', timeout=2)

if len(streams) == 0:
    print("No EEG stream running yet. Trying to start the Muse EEG stream ...")
    eeg_stream = subprocess.Popen([currentpath + "/bci-stream"])
    sleep(muse_connect_timout)
    streams = resolve_byprop('type', 'EEG', timeout=2)

if len(streams) == 0:
    raise (RuntimeError, "Cant find EEG stream")
else:
    print("Success: found Muse EEG stream")

print("Start aquiring data")
inlet = StreamInlet(streams[0], max_chunklen=12)
eeg_time_correction = inlet.time_correction()

inlet_marker = False
#print("looking for a Markers stream...")
#marker_streams = resolve_byprop('type', 'Markers', timeout=2)
#if marker_streams:
#    inlet_marker = StreamInlet(marker_streams[0])
#    marker_time_correction = inlet_marker.time_correction()
#else:
#    inlet_marker = False
#    print("Cant find Markers stream")

info = inlet.info()
description = info.desc()
def record(
    duration: int,
    filename=None,
    dejitter=False,
    data_source="EEG",
    continuous: bool = True,
) -> None:
    chunk_length = LSL_EEG_CHUNK
    if data_source == "PPG":
        chunk_length = LSL_PPG_CHUNK
    if data_source == "ACC":
        chunk_length = LSL_ACC_CHUNK
    if data_source == "GYRO":
        chunk_length = LSL_GYRO_CHUNK

    if not filename:
        filename = os.path.join(
            os.getcwd(), "%s_recording_%s.csv" %
            (data_source, strftime('%Y-%m-%d-%H.%M.%S', gmtime())))

    channel_idx = 1
    num_of_data = 178
    existing = pd.DataFrame()
    model = load_model(
        "/home/pi/.virtualenvs/muse_lsl_env/lib/python3.7/site-packages/muselsl/Epilepsy.h5"
    )
    print("Initialized Variables")

    print("Looking for a %s stream..." % (data_source))
    streams = resolve_byprop('type', data_source, timeout=LSL_SCAN_TIMEOUT)

    if len(streams) == 0:
        print("Can't find %s stream." % (data_source))
        return

    print("Started acquiring data.")
    inlet = StreamInlet(streams[0], max_chunklen=chunk_length)
    # eeg_time_correction = inlet.time_correction()

    print("Looking for a Markers stream...")
    marker_streams = resolve_byprop('name',
                                    'Markers',
                                    timeout=LSL_SCAN_TIMEOUT)

    if marker_streams:
        inlet_marker = StreamInlet(marker_streams[0])
    else:
        inlet_marker = False
        print("Can't find Markers stream.")

    info = inlet.info()
    description = info.desc()

    Nchan = info.channel_count()

    ch = description.child('channels').first_child()
    ch_names = [ch.child_value('label')]
    for i in range(1, Nchan):
        ch = ch.next_sibling()
        ch_names.append(ch.child_value('label'))

    res = []
    timestamps = []
    markers = []
    t_init = time()
    time_correction = inlet.time_correction()
    last_written_timestamp = None
    print('Start recording at time t=%.3f' % t_init)
    print('Time correction: ', time_correction)
    while (time() - t_init) < duration:
        try:
            data, timestamp = inlet.pull_chunk(timeout=1.0,
                                               max_samples=chunk_length)

            if timestamp:
                # print("Data: " + str(data))
                new_arr = pd.DataFrame(data)
                combine = [existing, new_arr]
                existing = pd.concat(combine).reset_index(drop=True)
                # print(len(existing))

                if len(existing) >= num_of_data:
                    row = existing[0:num_of_data]
                    row = row[channel_idx]
                    row = row.values.reshape(-1, 178, 1)
                    existing.drop(existing.index[0:178], inplace=True)
                    existing = existing.reset_index(drop=True)
                    predictions = model.predict(
                        (row[:, ::4] - row.mean()) / row.std())
                    result = np.argmax(predictions[0]) + 1
                    print("Result: " + str(result))
                res.append(data)
                timestamps.extend(timestamp)
                tr = time()
            if inlet_marker:
                marker, timestamp = inlet_marker.pull_sample(timeout=0.0)
                if timestamp:
                    markers.append([marker, timestamp])

            # Save every 5s
            if continuous and (last_written_timestamp is None
                               or last_written_timestamp + 5 < timestamps[-1]):
                _save(
                    filename,
                    res,
                    timestamps,
                    time_correction,
                    dejitter,
                    inlet_marker,
                    markers,
                    ch_names,
                    last_written_timestamp=last_written_timestamp,
                )
                last_written_timestamp = timestamps[-1]

        except KeyboardInterrupt:
            break

    time_correction = inlet.time_correction()
    print("Time correction: ", time_correction)

    _save(
        filename,
        res,
        timestamps,
        time_correction,
        dejitter,
        inlet_marker,
        markers,
        ch_names,
    )

    print("Done - wrote file: {}".format(filename))
Example #26
0
class lsl_inlet(po):
    def __init__(self, info, block_size=4, processing_flags=0, cb=None):
        self.inlet = StreamInlet(info,
                                 max_buflen=block_size,
                                 max_chunklen=block_size,
                                 processing_flags=processing_flags)
        self.info = self.inlet.info()
        po.__init__(self, self.info.nominal_srate(), self.info.channel_count(),
                    block_size)
        self.internal_data_buffer = data_buffer(self.inlet.channel_count,
                                                block_size=block_size,
                                                block_cnt=4)
        self.internal_time_stamp_buffer = data_buffer(1,
                                                      block_size=block_size,
                                                      block_cnt=4)
        self.external_data_buffer = data_buffer(self.inlet.channel_count,
                                                block_size=block_size)
        self.external_time_stamp_buffer = data_buffer(1, block_size=block_size)
        self.thread = None
        self.running = False
        self._lock = threading.Lock()
        self.new_samples = 0
        self.cb = None
        self.wrt_ptr = 0
        self.rd_ptr = 0
        self.new_chunk_sz = 0
        self.cb = cb

    def __del__(self):
        self.kill_listener()

    def kill_listener(self):
        if self.running is True:
            self.running = False
            self.thread.join()

    def pull_frames(self):
        while self.running is True:
            chunk, timestamps = self.inlet.pull_chunk()
            if (len(chunk) != 0):
                self._lock.acquire()
                self.internal_data_buffer.write_raw(np.array(chunk))
                self.internal_time_stamp_buffer.write_raw(
                    np.array([timestamps]))
                self.new_samples += len(chunk)
                self.new_chunk_sz = len(chunk)
                self.wrt_ptr = self.internal_data_buffer.wrt_ptr
                self.rd_ptr = self.rd_ptr - self.block_size
                # todo: safety check if rd_ptr < -block_size, we are in trouble...
                if self.rd_ptr < 0:
                    self.rd_ptr += self.block_size

                while self.new_samples >= self.external_data_buffer.frame_cnt:
                    frames = self.internal_data_buffer.read(
                        self.external_data_buffer)
                    self.cb(frames)
                    #self.external_data_buffer = self.internal_data_buffer.read(self.external_data_buffer)
                    #self.external_time_stamp_buffer = self.internal_time_stamp_buffer.read(self.external_time_stamp_buffer)
                    self.new_samples -= self.external_data_buffer.frame_cnt

                self._lock.release()
            else:
                time.sleep(.01)

    def launch_listener(self):
        self.running = True
        self.thread = threading.Thread(target=self.pull_frames)
        self.thread.start()

    def process(self, frames):
        #self._lock.acquire()
        frames = self.internal_data_buffer.read(frames)
        #self._lock.release()
        return frames
import time;
import numpy as np
from pylsl import StreamInlet, resolve_stream

#Input:
#1: Number of secs for test
#2: Datetime
#3: Sample id
channel_len = 8
ignore_first_secs = 0.01
ignore_last_secs = 0.01

# first resolve an EEG stream on the lab network
print("Looking for an EEG stream")
streams = resolve_stream("type","EEG",)
inlet = StreamInlet(streams[0])
print("Stream Found")


datastream = []
time.sleep(ignore_first_secs);
timeout = time.time() + float(sys.argv[2]) - ignore_last_secs
while True:
  if time.time() > timeout:
    break
  #sample[0] has the data, sample[1] has a timestamp
  sample = inlet.pull_sample()
  datastream.append(sample[0])

#Build folder structure
zpad = 6
Example #28
0
class P300Window(object):
    def __init__(self, master: Tk):
        self.master = master
        master.title('P300 speller')

        #Parameters
        self.imagesize = 125
        self.images_folder_path = '../utils/images/'  #use utils/char_generator to generate any image you want
        self.flash_image_path = '../utils/images/flash_images/einstein.jpg'
        self.number_of_rows = 6
        self.number_of_columns = 6  #make sure you have 6 x 6 amount of images in the images_folder_path
        self.flash_mode = 2  #single element  #1 for columns and rows; currently is NOT working yet; if I have time, will revisit
        self.flash_duration = 100  #soa
        self.break_duration = 125  #iti

        self.trials = 6  #number of letters
        self.delay = 2500  #interval between trial
        self.letter_idx = 0

        #did not include numbers yet!
        self.random_letter = random.choices(
            string.ascii_lowercase,
            k=self.trials)  #randomize [self.trials] number letters
        self.word = ''.join(self.random_letter)

        # Variables
        self.usable_images = []
        self.image_labels = []
        self.flash_sequence = []
        self.flash_image = None
        self.sequence_number = 0
        self.lsl_output = None

        self.running = 0  #for pause

        self.image_frame = Frame(self.master)
        self.image_frame.grid(row=0,
                              column=0,
                              rowspan=self.number_of_rows,
                              columnspan=self.number_of_columns)

        self.start_btn_text = StringVar()
        self.start_btn_text.set('Start')
        self.start_btn = Button(self.master,
                                textvariable=self.start_btn_text,
                                command=self.start)
        self.start_btn.grid(row=self.number_of_rows + 3,
                            column=self.number_of_columns - 1)

        self.pause_btn = Button(self.master, text='Pause', command=self.pause)
        self.pause_btn.grid(row=self.number_of_rows + 3,
                            column=self.number_of_columns - 4)  #-4 for center
        self.pause_btn.configure(state='disabled')

        self.close_btn = Button(self.master, text='Close', command=master.quit)
        self.close_btn.grid(row=self.number_of_rows + 3, column=0)

        fontStyle = tkFont.Font(family="Courier", size=40)

        self.output = Text(root, height=1, font=fontStyle)
        self.output.tag_configure("red", foreground="red")
        self.output.tag_configure("green", foreground="green")
        self.output.configure(width=10)
        self.output.insert("end", "  ")
        self.output.grid(row=self.number_of_rows + 2,
                         column=self.number_of_columns - 4)

        self.outputlabel = Label(root, text="Output: ", font=fontStyle)
        self.outputlabel.grid(row=self.number_of_rows + 2,
                              column=self.number_of_columns - 5)

        self.targetlabel = Label(root, text="Target: ", font=fontStyle)
        self.targetlabel.grid(row=self.number_of_rows + 1,
                              column=self.number_of_columns - 5)

        self.show_highlight_letter(0)

        # Initialization
        self.show_images()
        self.create_flash_sequence()
        self.lsl_output = self.create_lsl_output()

    def open_images(self):
        self.usable_images = []
        self.highlight_letter_images = []

        letter_images = sorted(
            glob.glob(
                os.path.join(self.images_folder_path, 'letter_images/*.png')))

        #currently, still did not flash number yet!
        number_images = sorted(
            glob.glob(
                os.path.join(self.images_folder_path, 'number_images/*.png')))
        letter_highlight_images = sorted(
            glob.glob(
                os.path.join(self.images_folder_path,
                             'letter_highlight_images/*.png')))
        number_highlight_images = sorted(
            glob.glob(
                os.path.join(self.images_folder_path,
                             'number_highlight_images/*.png')))

        for number_image in number_images:
            letter_images.append(number_image)
        #print("Paths: ", letter_images)
        min_number_of_images = self.number_of_columns * self.number_of_rows
        if len(letter_images) < min_number_of_images:
            print('To few images in folder: ' + self.images_folder_path)
            return

        # Convert and resize images
        for image_path in letter_images:
            image = Image.open(image_path)
            resized = image.resize((self.imagesize, self.imagesize),
                                   Image.BICUBIC)
            Tkimage = ImageTk.PhotoImage(resized)
            self.usable_images.append(Tkimage)

        # Convert and resize images
        for image_path in letter_highlight_images:
            image = Image.open(image_path)
            resized = image.resize((self.imagesize, self.imagesize),
                                   Image.BICUBIC)
            Tkimage = ImageTk.PhotoImage(resized)
            self.highlight_letter_images.append(Tkimage)

        flash_img = Image.open(self.flash_image_path)
        flash_img_res = flash_img.resize((self.imagesize, self.imagesize),
                                         Image.BICUBIC)
        self.flash_image = ImageTk.PhotoImage(flash_img_res)

    def show_images(self):
        self.open_images()

        if self.usable_images == []:
            print('No images opened')
            return

        num_rows = self.number_of_rows
        num_cols = self.number_of_columns

        # Arrange images
        for r in range(0, num_rows):
            for c in range(0, num_cols):
                current_image = self.usable_images[r * num_cols + c]
                label = Label(self.image_frame, image=current_image)
                label.image = current_image
                label.grid(row=r, column=c)
                self.image_labels.append(label)

    def create_lsl_output(self):
        """Creates an LSL Stream outlet"""
        info = StreamInfo(name='LetterMarkerStream',
                          type='LetterFlashMarkers',
                          channel_count=1,
                          channel_format='int8',
                          nominal_srate=IRREGULAR_RATE,
                          source_id='lettermarker_stream',
                          handle=None)

        return StreamOutlet(info)  #for sending the predicted classes

    def create_flash_sequence(self):
        self.flash_sequence = []
        num_rows = self.number_of_rows
        num_cols = self.number_of_columns
        maximum_number = num_rows * num_cols

        flash_sequence = []

        for i in range(10000):
            seq = list(range(maximum_number))  #generate 0 to maximum_number
            random.shuffle(seq)  #shuffle
            flash_sequence.extend(seq)

        self.flash_sequence = flash_sequence

    def start(self):
        self.read_lsl_marker()
        self.running = 1
        letter = self.word[0]
        image_index = string.ascii_lowercase.index(letter)
        self.highlight_image(image_index)
        self.start_btn.configure(state='disabled')
        self.pause_btn.configure(state='normal')

    def pause(self):
        self.running = 0
        self.start_btn_text.set('Resume')
        self.start_btn.configure(state='normal')
        self.pause_btn.configure(state='disabled')

    def start_flashing(self):
        if self.sequence_number == len(
                self.flash_sequence
        ):  #stop flashing if all generated sequence number runs out
            print('All elements had flashed - run out of juice')
            self.running = 0
            self.sequence_number = 0
            return

        if self.running == 0:
            print('Flashing paused at sequence number ' +
                  str(self.sequence_number))
            return

        result = self.marker_result()
        if (result):
            print("Marker received: ", result[0][0])
            receive = result[0][0]
        else:
            receive = 0

        element_to_flash = self.flash_sequence[self.sequence_number]
        letter = self.word[self.letter_idx]
        image_index = string.ascii_lowercase.index(letter)

        #pushed markers to LSL stream
        timestamp = local_clock()
        print("Letter: ", image_index, " Element flash: ",
              [element_to_flash + 1], timestamp)
        self.lsl_output.push_sample([element_to_flash + 1],
                                    timestamp)  # add 1 to prevent 0 in markers
        self.flash_single_element(element_to_flash)

        if not (receive):
            self.master.after(self.break_duration, self.start_flashing)
        else:
            if ((image_index + 1) == receive):
                self.output.insert("end", self.pos_to_char(receive), "green")
            else:
                self.output.insert("end", self.pos_to_char(receive), "red")

            self.letter_idx += 1
            if (self.letter_idx == len(self.word)):
                return
            letter = self.word[self.letter_idx]
            image_index = string.ascii_lowercase.index(letter)
            self.master.after(self.break_duration, self.highlight_target,
                              image_index)

        self.sequence_number = self.sequence_number + 1  #change flash position

    def pos_to_char(self, pos):
        return chr(pos - 1 + 97)

    def highlight_target(self, image_index):
        self.show_highlight_letter(self.letter_idx)
        self.highlight_image(image_index)

    def change_image(self, label, img):
        label.configure(image=img)
        label.image = img

    def highlight_image(self, element_no):
        self.change_image(self.image_labels[element_no],
                          self.highlight_letter_images[element_no])
        self.master.after(self.delay, self.unhighlight_image, element_no)

    def unhighlight_image(self, element_no):
        self.change_image(self.image_labels[element_no],
                          self.usable_images[element_no])
        self.master.after(self.flash_duration, self.start_flashing)

    def show_highlight_letter(self, pos):

        fontStyle = tkFont.Font(family="Courier", size=40)
        fontStyleBold = tkFont.Font(family="Courier bold", size=40)

        text = Text(root, height=1, font=fontStyle)
        text.tag_configure("bold", font=fontStyleBold)
        text.tag_configure("center", justify='center')

        for i in range(0, len(self.word)):
            if (i != pos):
                text.insert("end", self.word[i])
            else:
                text.insert("end", self.word[i], "bold")

        text.configure(state="disabled", width=10)
        text.tag_add("center", "1.0", "end")

        text.grid(row=self.number_of_rows + 1,
                  column=self.number_of_columns - 4)

    def flash_row_or_col(self, rc_number):
        num_rows = self.number_of_rows
        num_cols = self.number_of_columns

        if rc_number < num_rows:
            for c in range(0, num_cols):  #flash row
                cur_idx = rc_number * num_cols + c
                self.change_image(self.image_labels[cur_idx], self.flash_image)
        else:
            current_column = rc_number - num_rows
            for r in range(0, num_rows):  #flash column
                cur_idx = current_column + r * num_cols
                self.change_image(self.image_labels[cur_idx], self.flash_image)

        self.master.after(self.flash_duration, self.unflash_row_or_col,
                          rc_number)

    def unflash_row_or_col(self, rc_number):
        num_rows = self.number_of_rows
        num_cols = self.number_of_columns
        if rc_number < num_rows:
            for c in range(0, num_cols):  #flash row
                cur_idx = rc_number * num_cols + c
                self.change_image(self.image_labels[cur_idx],
                                  self.usable_images[cur_idx])
        else:
            current_column = rc_number - num_rows
            for r in range(0, num_rows):  #flash column
                cur_idx = current_column + r * num_cols
                self.change_image(self.image_labels[cur_idx],
                                  self.usable_images[cur_idx])

    def flash_single_element(self, element_no):
        self.change_image(self.image_labels[element_no], self.flash_image)
        self.master.after(self.flash_duration, self.unflash_single_element,
                          element_no)

    def unflash_single_element(self, element_no):
        self.change_image(self.image_labels[element_no],
                          self.usable_images[element_no])

    def marker_result(self):
        marker, timestamp = self.inlet_marker.pull_chunk()
        return marker

    def read_lsl_marker(self):
        print("looking for a Markers stream...")
        marker_streams = resolve_byprop('name', 'ResultMarkerStream')
        if marker_streams:
            self.inlet_marker = StreamInlet(marker_streams[0])
            marker_time_correction = self.inlet_marker.time_correction()
            print("Found Markers stream")
Example #29
0
T = np.linspace(0, epoch_length, num=int(sampling_rate * epoch_length))
reference1 = signalReference(T, Fre[0], harmonic)
reference2 = signalReference(T, Fre[1], harmonic)
reference3 = signalReference(T, Fre[2], harmonic)

# the send results streams
info = StreamInfo('ResultMarker', 'Markers', 1, 0, 'string',
                  'myuniquesourceid24445')
outlet = StreamOutlet(info)

# first resolve an EEG stream on the lab network
streams_data = resolve_stream('type', 'EEG')
streams_marker = resolve_stream('name', 'SSVEPMarkerStream')

# create a new inlet to read from the stream
inlet_data = StreamInlet(streams_data[0])
inlet_marker = StreamInlet(streams_marker[0])

time.sleep(2)
print('Please start MATLAB .....')

while True:
    start_time = 0.0
    corr = [0] * len(Fre)
    Corr = [0] * len(Fre)
    OUT = 0

    markers, timestamp_marker = inlet_marker.pull_chunk()
    data, timestamp_data = inlet_data.pull_chunk()  # pull_chunk
    data = np.array(data)
Example #30
0
class MyOVBox(OVBox):
  def __init__(self):
    OVBox.__init__(self)

    
  # the initialize method reads settings and outputs the first header
  def initialize(self):
    self.initLabel = 0
    self.debug=self.setting['debug'] == "true"
    print "Debug: ", self.debug
    self.stream_type=self.setting['Stream type']
    self.stream_name=self.setting['Stream name'] 
    # total channels for all streams
    self.channelCount = 0
    #self.stream_name=self.setting['Stream name'] # in case !all_streams
    print "Looking for streams of type: " + self.stream_type
    streams = resolve_stream('type',self.stream_type)
    print "Nb streams: " + str( len(streams))
    self.nb_streams = len(streams)
    if self.nb_streams == 0:
      raise Exception("Error: no stream found.")
    self.inlet = StreamInlet(streams[0], max_buflen=1)
    self.info = self.inlet.info()
    self.channelCount = self.info.channel_count()
    print "Stream name: " + self.info.name()
    stream_freq = self.info.nominal_srate()
    if stream_freq != 0:
	  raise Exception("Error: no irregular stream found.")
    # we append to the box output a stimulation header. This is just a header, dates are 0.
    self.output[0].append(OVStimulationHeader(0., 0.))
    self.init = False
  # The process method will be called by openvibe on every clock tick
  def process(self):
    # A stimulation set is a chunk which starts at current time and end time is the time step between two calls
    # init here and filled within triger()
    self.stimSet = OVStimulationSet(self.getCurrentTime(), self.getCurrentTime()+1./self.getClock())
    if self.init == False :
     local_time = local_clock()
     initSecond=int(local_time) 
     initMillis=int((local_time-initSecond)*1000)
     self.stimSet.append(OVStimulation(self.initLabel, self.getCurrentTime(), 0.))
     self.stimSet.append(OVStimulation(initSecond, self.getCurrentTime(), 0.))
     self.stimSet.append(OVStimulation(initMillis, self.getCurrentTime(), 0.))
     self.init=True
	# read all available stream
    samples=[]
    sample,timestamp = self.inlet.pull_sample(0)
    while sample != None:
     samples += sample
     sample,timestamp = self.inlet.pull_sample(0)
     # every value will be converted to openvibe code and a stim will be create
    for label in samples: 
      label = str(label)
      if self.debug:
        print "Got label: ", label
      self.stimSet.append(OVStimulation(float(label), self.getCurrentTime(), 0.))	
    # even if it's empty we have to send stim list to keep the rest in sync
    self.output[0].append(self.stimSet)

  def uninitialize(self):
    # we send a stream end.
    end = self.getCurrentTime()
    self.output[0].append(OVStimulationEnd(end, end))
    self.inlet.close_stream()
    assert len(sys.argv) > 0, 'No experiment name provided'
    filename = sys.argv[1]
    timequant = 0.100 #s

    print("looking for device stream")
    device = OpenBCI8
    bci_info = resolve_byprop('source_id', device.source_id, timeout=1)[0]
    print("Device stream discovered")
    print('Looking for GUI source')
    experiment_info = resolve_byprop('source_id', Experiment.source_id,
                                       timeout=100)[0]
    print('GUI source discovered')

    #print(experiment_info, bci_info)

    experiment_inlet = StreamInlet(experiment_info)
    bci_inlet = StreamInlet(bci_info)

    bci_results = [[], []]
    experiment_results = [[], []]

    print('Recording')
    while True:
        # get a new sample (you can also omit the timestamp part if you're not
        # interested in it)
        bci_values, bci_timestamps = bci_inlet.pull_chunk(max_samples=device.sfreq * 60 *6)
        bci_results[0].extend(bci_values)
        bci_results[1].extend(bci_timestamps)

        experiment_values, experiment_timestamps = experiment_inlet.pull_chunk()
        experiment_results[0].extend(experiment_values)
Example #32
0
def record(duration, filename=None, dejitter=False, data_source="EEG"):
    chunk_length = LSL_EEG_CHUNK
    if data_source == "PPG":
        chunk_length = LSL_PPG_CHUNK
    if data_source == "ACC":
        chunk_length = LSL_ACC_CHUNK
    if data_source == "GYRO":
        chunk_length = LSL_GYRO_CHUNK

    if not filename:
        filename = os.path.join(
            os.getcwd(),
            "%s_recording_%s.csv" %
            (data_source, strftime("%Y-%m-%d-%H.%M.%S", gmtime())),
        )

    print("Looking for a %s stream..." % (data_source))
    streams = resolve_byprop("type", data_source, timeout=LSL_SCAN_TIMEOUT)

    if len(streams) == 0:
        print("Can't find %s stream." % (data_source))
        return

    print("Started acquiring data.")
    inlet = StreamInlet(streams[0], max_chunklen=chunk_length)
    # eeg_time_correction = inlet.time_correction()

    print("Looking for a Markers stream...")
    marker_streams = resolve_byprop("name",
                                    "Markers",
                                    timeout=LSL_SCAN_TIMEOUT)

    if marker_streams:
        inlet_marker = StreamInlet(marker_streams[0])
    else:
        inlet_marker = False
        print("Can't find Markers stream.")

    info = inlet.info()
    description = info.desc()

    Nchan = info.channel_count()

    ch = description.child("channels").first_child()
    ch_names = [ch.child_value("label")]
    for i in range(1, Nchan):
        ch = ch.next_sibling()
        ch_names.append(ch.child_value("label"))

    res = []
    timestamps = []
    markers = []
    t_init = time()
    time_correction = inlet.time_correction()
    print("Start recording at time t=%.3f" % t_init)
    print("Time correction: ", time_correction)
    while (time() - t_init) < duration:
        try:
            data, timestamp = inlet.pull_chunk(timeout=1.0,
                                               max_samples=chunk_length)

            if timestamp:
                res.append(data)
                timestamps.extend(timestamp)
            if inlet_marker:
                marker, timestamp = inlet_marker.pull_sample(timeout=0.0)
                if timestamp:
                    markers.append([marker, timestamp])
        except KeyboardInterrupt:
            break

    time_correction = inlet.time_correction()
    print("Time correction: ", time_correction)

    res = np.concatenate(res, axis=0)
    timestamps = np.array(timestamps) + time_correction

    if dejitter:
        y = timestamps
        X = np.atleast_2d(np.arange(0, len(y))).T
        lr = LinearRegression()
        lr.fit(X, y)
        timestamps = lr.predict(X)

    res = np.c_[timestamps, res]
    data = pd.DataFrame(data=res, columns=["timestamps"] + ch_names)

    if inlet_marker and markers:
        n_markers = len(markers[0][0])
        for ii in range(n_markers):
            data["Marker%d" % ii] = 0
        # process markers:
        for marker in markers:
            # find index of markers
            ix = np.argmin(np.abs(marker[1] - timestamps))
            for ii in range(n_markers):
                data.loc[ix, "Marker%d" % ii] = marker[0][ii]

    directory = os.path.dirname(filename)
    if not os.path.exists(directory):
        os.makedirs(directory)

    data.to_csv(filename, float_format="%.3f", index=False)

    print("Done - wrote file: " + filename + ".")
Example #33
0
        default=[0, 1, 2, 3],
        help='channel number to use. If not specified, all the channels are used')

    args = parser.parse_args()

    """ 1. CONNECT TO EEG STREAM """

    # Search for active LSL stream
    print('Looking for an EEG stream...')
    streams = resolve_byprop('type', 'EEG', timeout=2)
    if len(streams) == 0:
        raise RuntimeError('Can\'t find EEG stream.')

    # Set active EEG stream to inlet and apply time correction
    print("Start acquiring data")
    inlet = StreamInlet(streams[0], max_chunklen=12)
    eeg_time_correction = inlet.time_correction()

    # Get the stream info, description, sampling frequency, number of channels
    info = inlet.info()
    description = info.desc()
    fs = int(info.nominal_srate())
    n_channels = info.channel_count()

    # Get names of all channels
    ch = description.child('channels').first_child()
    ch_names = [ch.child_value('label')]
    for i in range(1, n_channels):
        ch = ch.next_sibling()
        ch_names.append(ch.child_value('label'))
Example #34
0
class P300Window(object):
    def __init__(self, master: Tk):
        self.master = master
        master.title('P300 speller')

        #Parameters
        self.imagesize = 125
        self.images_folder_path = '../utils/images/'  #use utils/char_generator to generate any image you want
        self.flash_image_path = '../utils/images/flash_images/einstein.jpg'
        self.number_of_rows = 6
        self.number_of_columns = 6  #make sure you have 6 x 6 amount of images in the images_folder_path
        self.flash_mode = 2  #single element  #1 for columns and rows; currently is NOT working yet; if I have time, will revisit
        self.flash_duration = 100  #flash duration
        self.break_duration = 150  #isi

        self.trials = 6  #number of letters
        self.delay = 1000  #interval between trial
        self.letter_idx = 0

        # Param for creating sequence
        self.num_sequence = 100

        #Parameter for random
        # self.number_of_symbols =36
        # self.fashed_per_iteration = 2
        # self.number_of_iterations = 6
        # self.stimuli_per_iteration = self.number_of_symbols * self.fashed_per_iteration / self.number_of_iterations

        #did not include numbers yet!
        self.random_letter = random.choices(
            string.ascii_lowercase,
            k=self.trials)  #randomize [self.trials] number letters
        self.word = ''.join(self.random_letter)

        # Variables
        self.usable_images = []
        self.image_labels = []
        self.flash_sequence = []
        self.flash_image = None
        self.sequence_number = 0
        self.lsl_output = None

        # self.running = 0  #for pause

        self.image_frame = Frame(self.master)
        self.image_frame.grid(row=0,
                              column=0,
                              rowspan=self.number_of_rows,
                              columnspan=self.number_of_columns)

        self.start_btn_text = StringVar()
        self.start_btn_text.set('Start')
        self.start_btn = Button(self.master,
                                textvariable=self.start_btn_text,
                                command=self.start)
        self.start_btn.grid(row=self.number_of_rows + 3,
                            column=self.number_of_columns - 1)

        # self.pause_btn = Button(self.master, text='Pause', command=self.pause)
        # self.pause_btn.grid(row=self.number_of_rows + 3, column=self.number_of_columns - 4)  #-4 for center
        # self.pause_btn.configure(state='disabled')

        self.close_btn = Button(self.master, text='Close', command=master.quit)
        self.close_btn.grid(row=self.number_of_rows + 3, column=0)

        fontStyle = tkFont.Font(family="Courier", size=40)

        self.output = Text(root, height=1, font=fontStyle)
        self.output.tag_configure("red", foreground="red")
        self.output.tag_configure("green", foreground="green")
        self.output.configure(width=10)
        self.output.insert("end", "  ")
        self.output.grid(row=self.number_of_rows + 2,
                         column=self.number_of_columns - 4)

        self.outputlabel = Label(root, text="Output: ", font=fontStyle)
        self.outputlabel.grid(row=self.number_of_rows + 2,
                              column=self.number_of_columns - 5)

        self.targetlabel = Label(root, text="Target: ", font=fontStyle)
        self.targetlabel.grid(row=self.number_of_rows + 1,
                              column=self.number_of_columns - 5)

        self.show_highlight_letter(0)

        # Initialization
        self.show_images()
        self.create_flash_sequence()
        self.lsl_output = self.create_lsl_output()

    def open_images(self):
        self.usable_images = []
        self.highlight_letter_images = []

        letter_images = sorted(
            glob.glob(
                os.path.join(self.images_folder_path, 'letter_images/*.png')))

        #currently, still did not flash number yet!
        number_images = sorted(
            glob.glob(
                os.path.join(self.images_folder_path, 'number_images/*.png')))
        letter_highlight_images = sorted(
            glob.glob(
                os.path.join(self.images_folder_path,
                             'letter_highlight_images/*.png')))
        number_highlight_images = sorted(
            glob.glob(
                os.path.join(self.images_folder_path,
                             'number_highlight_images/*.png')))

        for number_image in number_images:
            letter_images.append(number_image)
        #print("Paths: ", letter_images)
        min_number_of_images = self.number_of_columns * self.number_of_rows
        if len(letter_images) < min_number_of_images:
            print('To few images in folder: ' + self.images_folder_path)
            return

        # Convert and resize images
        for image_path in letter_images:
            image = Image.open(image_path)
            resized = image.resize((self.imagesize, self.imagesize),
                                   Image.BICUBIC)
            Tkimage = ImageTk.PhotoImage(resized)
            self.usable_images.append(Tkimage)

        # Convert and resize images
        for image_path in letter_highlight_images:
            image = Image.open(image_path)
            resized = image.resize((self.imagesize, self.imagesize),
                                   Image.BICUBIC)
            Tkimage = ImageTk.PhotoImage(resized)
            self.highlight_letter_images.append(Tkimage)

        flash_img = Image.open(self.flash_image_path)
        flash_img_res = flash_img.resize((self.imagesize, self.imagesize),
                                         Image.BICUBIC)
        self.flash_image = ImageTk.PhotoImage(flash_img_res)

    def show_images(self):
        self.open_images()

        if self.usable_images == []:
            print('No images opened')
            return

        num_rows = self.number_of_rows
        num_cols = self.number_of_columns

        # Arrange images
        for r in range(0, num_rows):
            for c in range(0, num_cols):
                current_image = self.usable_images[r * num_cols + c]
                label = Label(self.image_frame, image=current_image)
                label.image = current_image
                label.grid(row=r, column=c)
                self.image_labels.append(label)

    def create_lsl_output(self):
        """Creates an LSL Stream outlet"""
        info = StreamInfo(name='LetterMarkerStream',
                          type='LetterFlashMarkers',
                          channel_count=1,
                          channel_format='int8',
                          nominal_srate=IRREGULAR_RATE,
                          source_id='lettermarker_stream',
                          handle=None)

        return StreamOutlet(info)  #for sending the predicted classes

    # def create_flash_sequence_old(self):
    #     num_rows = 6
    #     num_cols = 6
    #     maximum_number = num_rows * num_cols
    #     number_count = np.array([0] * maximum_number)
    #     seq = []
    #     next_number = [random.randint(0, maximum_number)]

    #     count = 1
    #     while (len(seq) / 6 < 100):
    #         if (len(seq) > 0):
    #             neighbor_list = seq[-count:]   #the same set, with size of -1 to -6
    #             left_list = [x-1 for x in neighbor_list]   # neighbor of each neighbor in neighbor_list
    #             right_list = [x+1 for x in neighbor_list]
    #             up_list = [x-6 for x in neighbor_list]
    #             bot_list = [x+6 for x in neighbor_list]
    #             combine_list =[]
    #             combine_list.extend(left_list)
    #             combine_list.extend(right_list)
    #             combine_list.extend(up_list)
    #             combine_list.extend(bot_list)
    #             #should not be same element as previous set (*2), and should not be same element in the combine_list
    #             if (next_number not in seq[-CONCURRENT_ELEMENTS*2:] and next_number not in combine_list):
    #                 seq.extend(next_number)
    #                 count = ((count) % 6) + 1  #this count makes sure we have one set of 6
    #         else:
    #             seq.extend(next_number)
    #         left_over = np.argwhere(number_count == np.argmin(number_count))
    #         selectMax = len(left_over) - 1
    #         next_number = left_over[random.randint(0, selectMax)]
    #     self.flash_sequence = seq

    def find_replacement(self, nextelem, seq):
        length = CONCURRENT_ELEMENTS if len(
            self.flash_sequence) > CONCURRENT_ELEMENTS - 1 else len(
                self.flash_sequence)
        for i in range(1, length + 1):
            prev_seq = self.flash_sequence[-i:][0]
            for j in range(len(prev_seq)):
                previous_seq_elem = self.flash_sequence[-i:][0][j]
                prev_seq_without_prevelem = [
                    x for x in prev_seq if x != previous_seq_elem
                ]
                nl_prev = self.get_neighbors(prev_seq_without_prevelem)
                nl_current = self.get_neighbors(seq)
                if (nextelem not in prev_seq and  #a
                        nextelem not in nl_prev and  #b
                        nextelem not in self.flash_sequence[-i - 1:][0]
                        and  #c1  left consecutive
                        nextelem not in self.flash_sequence[-i + 1:][
                            0]  #c2  right consecutive
                        and previous_seq_elem not in seq and  #a
                        previous_seq_elem not in nl_current and  #b  
                        previous_seq_elem
                        not in self.flash_sequence[-1:][0]):  #c
                    self.flash_sequence[-i:][0][j] = nextelem
                    seq.append(previous_seq_elem)
                    return seq
        print("Can't swap..Restarting everything...")
        create_flash_sequence()

    def get_neighbors(self, seq):
        right = [x + 1 for x in seq]
        left = [x - 1 for x in seq]
        top = [x - 6 for x in seq]
        bottom = [x + 6 for x in seq]
        neighbors = list(chain(right, left, top, bottom))
        return neighbors

    def create_flash_sequence(self):
        num_rows = self.number_of_rows
        num_cols = self.number_of_columns
        total = num_rows * num_cols
        num_sequence = self.num_sequence

        li = list(range(total))

        while len(self.flash_sequence) < num_sequence:
            seq = []
            failcount = 0
            if not li:
                #if li is exhausted
                li = list(range(36))
            while len(seq) < CONCURRENT_ELEMENTS:
                nextelem = random.choice(li)
                if len(seq) > 0:
                    nl = self.get_neighbors(seq)
                    #prevent stuck
                    if failcount > 20:
                        seq = self.find_replacement(nextelem, seq)
                        li.remove(nextelem)
                        failcount = 0
                    elif nextelem not in nl and nextelem not in seq:
                        if len(self.flash_sequence):
                            if nextelem not in self.flash_sequence[-1:][
                                    0]:  #0 remove the outer list [[]] becomes []
                                seq.append(nextelem)
                                li.remove(nextelem)
                            else:
                                failcount += 1
                        else:
                            seq.append(nextelem)
                            li.remove(nextelem)
                    else:
                        failcount += 1
                else:  #first element, just insert
                    if len(self.flash_sequence):
                        if nextelem not in self.flash_sequence[-1:][0]:
                            seq.append(nextelem)
                            li.remove(nextelem)
                    else:
                        seq.append(nextelem)
                        li.remove(nextelem)
            self.flash_sequence.append(seq)

        self.flash_sequence = list(chain(*self.flash_sequence))

    def start(self):
        if not (TEST_UI):
            self.read_lsl_marker()
        self.running = 1
        letter = self.word[0]
        image_index = string.ascii_lowercase.index(letter)
        self.highlight_image(image_index)
        self.start_btn.configure(state='disabled')
        self.pause_btn.configure(state='normal')

    # def pause(self):
    #     self.running = 0
    #     self.start_btn_text.set('Resume')
    #     self.start_btn.configure(state='normal')
    #     self.pause_btn.configure(state='disabled')

    # def check_pause(self):
    #     if self.running == 0:
    #         print('Flashing paused at sequence number ' + str(self.sequence_number))
    #         return

    def check_sequence_end(self):
        if self.sequence_number == len(
                self.flash_sequence
        ):  #stop flashing if all generated sequence number runs out
            print('All elements had flashed - run out of juice')
            self.running = 0
            self.sequence_number = 0
            return

    def get_marker_result(self):
        result = self.marker_result()
        if (result):
            print("Marker received: ", result[0][0])
            receive = result[0][0]
        else:
            receive = 0

        return receive

    def output_letter(self, receive, image_index):
        # receive = [9,10,13]
        if not receive:
            if FLASH_CONCURRENT:
                self.master.after(self.break_duration,
                                  self.start_concurrent_flashing)
            else:
                self.master.after(self.break_duration, self.start_flashing)

        elif isinstance(receive, int):
            if (image_index + 1) == receive:
                self.output.insert("end", self.pos_to_char(receive), "green")
            else:
                self.output.insert("end", self.pos_to_char(receive), "red")

            self.letter_idx += 1
            if self.letter_idx == len(self.word):
                return
            letter = self.word[self.letter_idx]
            image_index = string.ascii_lowercase.index(letter)
            self.master.after(self.break_duration, self.highlight_target,
                              image_index)

        else:
            if FLASH_CONCURRENT:
                self.candidate_flash_sequence(receive)
                self.master.after(self.break_duration,
                                  self.start_concurrent_flashing)
            else:
                self.master.after(self.break_duration, self.start_flashing)

    def candidate_flash_sequence(self, candidates):
        print("got candidate")
        num_rows = self.number_of_rows
        num_col = self.number_of_columns
        current_elements = self.flash_sequence[self.sequence_number:self.
                                               sequence_number +
                                               CONCURRENT_ELEMENTS]
        next_elements = self.flash_sequence[self.sequence_number +
                                            CONCURRENT_ELEMENTS:self.
                                            sequence_number +
                                            CONCURRENT_ELEMENTS * 2]

        # Step 1 check if the candidate is included in the next list
        # Step 2 check if there is multiple candidate in the next list ~ else just continue
        count_contain_candidate = 0
        for target_candidate in candidates:
            if target_candidate in next_elements:
                count_contain_candidate += 1

        if count_contain_candidate > 1 or count_contain_candidate == 0:
            # Step 3 check previous i length of sequence to know lease used candidate where i = candidate length
            start_check_index = 0
            previous_flashes_count = []
            if CONCURRENT_ELEMENTS * len(candidates) > self.sequence_number:
                start_check_index = self.sequence_number - CONCURRENT_ELEMENTS * len(
                    candidates) - 1
            for target_candidate in candidates:
                previous_flashes = self.flash_sequence[start_check_index:self.
                                                       sequence_number - 1]
                previous_flashes_count.append([
                    target_candidate,
                    previous_flashes.count(target_candidate)
                ])
            least_index = np.argmin(previous_flashes_count, axis=0)[1]
            choosen_candidate = previous_flashes_count[least_index][0]

            # generate new flash_sequence
            new_sequence = [choosen_candidate]
            li = list(range(num_rows * num_col))

            print("new_sequence1 :", new_sequence)
            #generate sequence
            while len(new_sequence) < 6:
                nextelem = random.choice(li)
                print("nextelem :", nextelem)
                nl = self.get_neighbors(new_sequence)
                #random until get the flasshes sequence
                while (nextelem in nl or nextelem in current_elements
                       or nextelem in next_elements):
                    nextelem = random.choice(li)
                    print("nextelem :", nextelem)
                new_sequence.append(nextelem)
            print("new_sequence2: ", new_sequence)

            print("self.sequence_number: ", self.sequence_number)

            # update flashing sequences
            print(self.sequence_number)

            self.flash_sequence = self.flash_sequence[
                0:self.sequence_number +
                CONCURRENT_ELEMENTS] + new_sequence + self.flash_sequence[
                    self.sequence_number + CONCURRENT_ELEMENTS:]

        # Step 4 generate new list where
        #       1 no duplicate
        #       2 no multiple candidate
        #       3 no neighbors
        #       4 no previous list if possible (maybe all candidate is in the previous)
        #       5 no next list if possible (maybe all candidate is in the next)
        #       6 use the least use candidate

    def start_concurrent_flashing(self):

        self.check_sequence_end()
        # self.check_pause()
        receive = self.get_marker_result()

        element_to_flash = self.flash_sequence[self.sequence_number:self.
                                               sequence_number +
                                               CONCURRENT_ELEMENTS]
        letter = self.word[self.letter_idx]
        image_index = string.ascii_lowercase.index(letter)

        #pushed markers to LSL stream

        print("Letter: ", image_index, " Element flash: ",
              [x + 1 for x in element_to_flash])
        for e in element_to_flash:
            self.lsl_output.push_sample([e + 1
                                         ])  # add 1 to prevent 0 in markers

        self.flash_multiple_elements(element_to_flash)
        self.output_letter(receive, image_index)

        self.sequence_number = self.sequence_number + CONCURRENT_ELEMENTS  #change flash position

    def start_flashing(self):
        self.check_sequence_end()
        # self.check_pause()
        receive = self.get_marker_result()

        element_to_flash = self.flash_sequence[self.sequence_number]
        letter = self.word[self.letter_idx]
        image_index = string.ascii_lowercase.index(letter)

        #pushed markers to LSL stream

        print("Letter: ", image_index, " Element flash: ",
              [element_to_flash + 1])
        self.lsl_output.push_sample([element_to_flash + 1
                                     ])  # add 1 to prevent 0 in markers
        self.flash_single_element(element_to_flash)

        self.output_letter(receive, image_index)

        self.sequence_number = self.sequence_number + 1  #change flash position

    def pos_to_char(self, pos):
        return chr(pos + 97)

    def highlight_target(self, image_index):
        self.show_highlight_letter(self.letter_idx)
        self.highlight_image(image_index)

    def change_image(self, label, img):
        label.configure(image=img)
        label.image = img

    def highlight_image(self, element_no):
        self.change_image(self.image_labels[element_no],
                          self.highlight_letter_images[element_no])
        self.master.after(self.delay, self.unhighlight_image, element_no)

    def unhighlight_image(self, element_no):
        self.change_image(self.image_labels[element_no],
                          self.usable_images[element_no])

        if (FLASH_CONCURRENT):
            self.master.after(self.flash_duration,
                              self.start_concurrent_flashing)
        else:
            self.master.after(self.flash_duration, self.start_flashing)

    def show_highlight_letter(self, pos):

        fontStyle = tkFont.Font(family="Courier", size=40)
        fontStyleBold = tkFont.Font(family="Courier bold", size=40)

        text = Text(root, height=1, font=fontStyle)
        text.tag_configure("bold", font=fontStyleBold)
        text.tag_configure("center", justify='center')

        for i in range(0, len(self.word)):
            if (i != pos):
                text.insert("end", self.word[i])
            else:
                text.insert("end", self.word[i], "bold")

        text.configure(state="disabled", width=10)
        text.tag_add("center", "1.0", "end")

        text.grid(row=self.number_of_rows + 1,
                  column=self.number_of_columns - 4)

    def flash_row_or_col(self, rc_number):
        num_rows = self.number_of_rows
        num_cols = self.number_of_columns

        if rc_number < num_rows:
            for c in range(0, num_cols):  #flash row
                cur_idx = rc_number * num_cols + c
                self.change_image(self.image_labels[cur_idx], self.flash_image)
        else:
            current_column = rc_number - num_rows
            for r in range(0, num_rows):  #flash column
                cur_idx = current_column + r * num_cols
                self.change_image(self.image_labels[cur_idx], self.flash_image)

        self.master.after(self.flash_duration, self.unflash_row_or_col,
                          rc_number)

    def unflash_row_or_col(self, rc_number):
        num_rows = self.number_of_rows
        num_cols = self.number_of_columns
        if rc_number < num_rows:
            for c in range(0, num_cols):  #flash row
                cur_idx = rc_number * num_cols + c
                self.change_image(self.image_labels[cur_idx],
                                  self.usable_images[cur_idx])
        else:
            current_column = rc_number - num_rows
            for r in range(0, num_rows):  #flash column
                cur_idx = current_column + r * num_cols
                self.change_image(self.image_labels[cur_idx],
                                  self.usable_images[cur_idx])

    def flash_multiple_elements(self, element_array):
        for element_no in element_array:
            self.change_image(self.image_labels[element_no], self.flash_image)

        self.master.after(self.flash_duration, self.unflash_multiple_elements,
                          element_array)

    def unflash_multiple_elements(self, element_array):
        for element_no in element_array:
            self.change_image(self.image_labels[element_no],
                              self.usable_images[element_no])

    def flash_single_element(self, element_no):
        self.change_image(self.image_labels[element_no], self.flash_image)
        self.master.after(self.flash_duration, self.unflash_single_element,
                          element_no)

    def unflash_single_element(self, element_no):
        self.change_image(self.image_labels[element_no],
                          self.usable_images[element_no])

    def marker_result(self):
        if not (TEST_UI):
            marker, timestamp = self.inlet_marker.pull_chunk()
            return marker
        else:
            return 0

    def read_lsl_marker(self):
        print("looking for a Markers stream...")
        marker_streams = resolve_byprop('name', 'ResultMarkerStream')
        if marker_streams:
            self.inlet_marker = StreamInlet(marker_streams[0])
            marker_time_correction = self.inlet_marker.time_correction()
            print("Found Markers stream")
Example #35
0
"""Example program to show how to read a multi-channel time series from LSL."""

from pylsl import StreamInlet, resolve_stream
import time

# first resolve an EEG stream on the lab network
print("looking for an EEG stream...")
# streams = resolve_stream('type', 'EEG')
streams = resolve_stream()

print(streams[0].source_id())
# print(streams[1].source_id())

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])

i=0
while True:
    # get a new sample (you can also omit the timestamp part if you're not
    # interested in it)
    sample, timestamp = inlet.pull_sample()
    timeCorr = inlet.time_correction()
    print(timestamp, '\n',sample, '\n', timeCorr, '\n')
    # if i==10:
    #     break
    # break
    i = i + 1
    time.sleep(0.01)
Example #36
0
from sklearn import preprocessing
import math
import stimuli as st
import threading
import pygame
import maze as maze
from sklearn.cross_decomposition import CCA
import serial
import util as ul

# first resolve an EEG stream on the lab network
print("looking for an EEG stream...")
streams = resolve_stream('type', 'EEG')

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])
Fs = inlet.info().nominal_srate()
runing = True


def first_buffer():
    chunk = read_data()
    chunk = np.array(chunk).transpose()
    if len(chunk) == 0:
        return False, None
    bufferdata = []
    result = False
    if (any(chunk[11, :])):
        result = True
        arr = np.array(chunk)
        index = np.where(arr > 0)
from pylsl import StreamInlet, resolve_stream
import matplotlib.pyplot as plt
import matplotlib.animation as anmt
import time

# first resolve an EEG stream on the lab network
print("looking for an EEG stream...")
streams = resolve_stream('type', 'EEG')

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])
counter = 0

fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
plt.xlabel('Time')
plt.ylabel('Micro Volts')
plt.title('EEG Channel 1')

data = []
time = []

print("pull samples...")
while True:
    # get a new sample (you can also omit the timestamp part if you're not
    # interested in it)
    sample = inlet.pull_sample()
    counter += 1

    data.append(sample[0][0])
    time.append(counter)
Example #38
0
        default=[0, 1, 2, 3],
        help=
        'channel number to use. If not specified, all the channels are used')

    args = parser.parse_args()
    """CONNECT TO EEG STREAM """

    # Search for active LSL stream
    print('Looking for an EEG stream...')
    streams = resolve_byprop('type', 'EEG', timeout=2)
    if len(streams) == 0:
        raise RuntimeError('Can\'t find EEG stream.')

    # Set active EEG stream to inlet and apply time correction
    print("Start acquiring data")
    inlet = StreamInlet(streams[0], max_chunklen=12)
    eeg_time_correction = inlet.time_correction()

    # Get the stream info, description, sampling frequency, number of channels
    info = inlet.info()
    description = info.desc()
    fs = int(info.nominal_srate())
    n_channels = info.channel_count()

    # Get names of all channels
    ch = description.child('channels').first_child()
    ch_names = [ch.child_value('label')]
    for i in range(1, n_channels):
        ch = ch.next_sibling()
        ch_names.append(ch.child_value('label'))
Example #39
0
    default=default_fname,  # 命令行参数 文件名称
    help="Name of the recording file.")

# dejitter timestamps
dejitter = False

(options, args) = parser.parse_args()

print("looking for an EEG stream...")
streams = resolve_byprop('type', 'EEG', timeout=2)

if len(streams) == 0:
    raise (RuntimeError, "Cant find EEG stream")

print("Start aquiring data")
inlet = StreamInlet(streams[0], max_chunklen=12)
eeg_time_correction = inlet.time_correction(
)  # Retrieve an estimated time correction offset for the given stream

print("looking for a Markers stream...")
marker_streams = resolve_byprop('type', 'Markers', timeout=2)

if marker_streams:
    inlet_marker = StreamInlet(marker_streams[0])
    marker_time_correction = inlet_marker.time_correction()
else:
    inlet_marker = False
    print("Cant find Markers stream")

info = inlet.info()
description = info.desc()
Example #40
0
cap.append_child_value("size", "54")
cap.append_child_value("labelscheme", "10-20")

# create outlet for the stream
outlet = StreamOutlet(info)

# (...normally here one might start sending data into the outlet...)

# === the following could run on another computer ===

# first we resolve a stream whose name is MetaTester (note that there are
# other ways to query a stream, too - for instance by content-type)
results = resolve_stream("name", "MetaTester")

# open an inlet so we can read the stream's data (and meta-data)
inlet = StreamInlet(results[0])

# get the full stream info (including custom meta-data) and dissect it
info = inlet.info()
print("The stream's XML meta-data is: ")
print(info.as_xml())
print("The manufacturer is: %s" % info.desc().child_value("manufacturer"))
print("Cap circumference is: %s" %
      info.desc().child("cap").child_value("size"))
print("The channel labels are as follows:")
ch = info.desc().child("channels").child("channel")
for k in range(info.channel_count()):
    print("  " + ch.child_value("label"))
    ch = ch.next_sibling()

time.sleep(3)
Example #41
0
    def __init__(self,
                 incoming,
                 outgoing,
                 sparseOutput=None,
                 config={},
                 device_source='Muse',
                 software_source='muselsl',
                 debug_outputs=True,
                 verbose=False):

        self.incoming = incoming
        self.outgoing = outgoing
        self.sparseOutput = sparseOutput
        self.device_source = device_source
        self.software_source = software_source
        self.debug_outputs = debug_outputs
        self.verbose = verbose
        self.eeg_chunk_length = 12

        # 1. Initialize inlet
        if isinstance(self.incoming, str):  # LSL inlet
            print('Looking for the {} stream...'.format(incoming))
            self._stream = resolve_byprop('type', incoming, timeout=2)

            if len(self._stream) == 0:
                raise (RuntimeError('Can\'t find {} stream.'.format(incoming)))
            print('Aquiring data from the \'{}\' stream...'.format(incoming))

            self._inlet = StreamInlet(self._stream[0],
                                      max_chunklen=self.eeg_chunk_length)
            self._info_in = self._inlet.info()

        else:  # OSC port
            if USE_LIBLO:
                self._osc_server = ServerThread(incoming['port'])
                print('OSC server initialized at port {}.'.format(
                    incoming['port']))
            else:
                self._dispatcher = dispatcher.Dispatcher()
                print('python-osc dispatcher initialized.')

        # 2. Initialize outlets
        if not isinstance(self.outgoing, tuple):
            self.outgoing = [self.outgoing]
        self._output_threads = []
        for out in self.outgoing:

            if isinstance(out, str):  # LSL outlet
                raise NotImplementedError

            elif isinstance(out, dict):  # OSC port
                if USE_LIBLO:
                    self._output_threads.append(
                        Address(out['address'], out['port']))
                else:
                    raise NotImplementedError
#                    self._client = udp_client.SimpleUDPClient(
#                            outgoing['address'], outgoing['port'])
                print('OSC client initialized at {}:{}.'.format(
                    out['address'], out['port']))

        if (self.sparseOutput != None):
            if not isinstance(self.sparseOutput, tuple):
                self.sparseOutput = [self.sparseOutput]
            self._sparseOutput_threads = []
            for out in self.sparseOutput:
                if isinstance(out, str):  # LSL outlet
                    raise NotImplementedError

                elif isinstance(out, dict):  # OSC port
                    if USE_LIBLO:
                        self._sparseOutput_threads.append(
                            Address(out['address'], out['port']))
                    else:
                        raise NotImplementedError
                    print('OSC sparse output client initialized at {}:{}.'.
                          format(out['address'], out['port']))

        # 3. Initialize internal buffers and variables
        self._init_processing(config)
Example #42
0
# -*- coding: utf-8 -*-
"""Example program to demonstrate how to read a multi-channel time-series
from LSL in a chunk-by-chunk manner (which is more efficient)."""

from pylsl import StreamInlet, resolve_stream
"""EEG"""
# first resolve an EEG stream on the lab network
print("looking for an EEG stream...")
streams = resolve_stream('type', 'EEG')

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])
"""MARKERS"""
# first resolve a marker stream on the lab network
print("looking for a marker stream...")
streamsMARKER = resolve_stream('type', 'Markers')

# create a new inlet to read from the stream
inletMARKER = StreamInlet(streamsMARKER[0])

while True:
    # get a new sample (you can also omit the timestamp part if you're not
    # interested in it)
    chunk, timestamps = inlet.pull_chunk()
    if timestamps:
        print('**********************INLET_DATA*******************')
        print('SAMPLE_STAMP:' + str(timestamps))
        print('SAMPLE:' + str(chunk))

    marker, timestampM = inletMARKER.pull_sample()
    if timestampM:
Example #43
0
class FFTServer():
    """Server to receive EEG data and stream classifier outputs.

    Attributes:
        See args.

    Args:
        incoming (str or dict): incoming data stream. If provided as a
            string, look for an LSL stream with the corresponding type. If
            provided as dict with fields `address` and `port`, open an OSC
            port at that address and port.
        outgoing (str or dict): outgoing data stream. If provided as a
            string, stream to an LSL stream with the corresponding type. If
            provided as dict with fields `address` and `port`, stream to an
            OSC port at that address and port.

    Keyword Args:
        config (dict): dictionary containing the configuration and
            preprocessing parameters, e.g. (these are the default values):

                config = {'fs': 256.,
                          'n_channels': 4,
                          'raw_buffer_len': 3 * fs,
                          'filt_buffer_len': 3 * fs,
                          'window_len': fs,
                          'step': int(fs / 10),
                          'filter': ([1], [1]),
                          'psd_window_len': 256.,
                          'psd_buffer_len': 10}

        device_source (str): Device from which the data is coming from.
            'muse' or 'vive'
        streaming_source (str): Software source of the data stream:
            'muselsl'
            'musedirect'
            'musemonitor'
        debug_outputs (bool): if True, send debug outputs (not used by VR
            experience)
        verbose (bool): if True, print status whenever new data is
            received or sent.

    """
    def __init__(self,
                 incoming,
                 outgoing,
                 sparseOutput=None,
                 config={},
                 device_source='Muse',
                 software_source='muselsl',
                 debug_outputs=True,
                 verbose=False):

        self.incoming = incoming
        self.outgoing = outgoing
        self.sparseOutput = sparseOutput
        self.device_source = device_source
        self.software_source = software_source
        self.debug_outputs = debug_outputs
        self.verbose = verbose
        self.eeg_chunk_length = 12

        # 1. Initialize inlet
        if isinstance(self.incoming, str):  # LSL inlet
            print('Looking for the {} stream...'.format(incoming))
            self._stream = resolve_byprop('type', incoming, timeout=2)

            if len(self._stream) == 0:
                raise (RuntimeError('Can\'t find {} stream.'.format(incoming)))
            print('Aquiring data from the \'{}\' stream...'.format(incoming))

            self._inlet = StreamInlet(self._stream[0],
                                      max_chunklen=self.eeg_chunk_length)
            self._info_in = self._inlet.info()

        else:  # OSC port
            if USE_LIBLO:
                self._osc_server = ServerThread(incoming['port'])
                print('OSC server initialized at port {}.'.format(
                    incoming['port']))
            else:
                self._dispatcher = dispatcher.Dispatcher()
                print('python-osc dispatcher initialized.')

        # 2. Initialize outlets
        if not isinstance(self.outgoing, tuple):
            self.outgoing = [self.outgoing]
        self._output_threads = []
        for out in self.outgoing:

            if isinstance(out, str):  # LSL outlet
                raise NotImplementedError

            elif isinstance(out, dict):  # OSC port
                if USE_LIBLO:
                    self._output_threads.append(
                        Address(out['address'], out['port']))
                else:
                    raise NotImplementedError
#                    self._client = udp_client.SimpleUDPClient(
#                            outgoing['address'], outgoing['port'])
                print('OSC client initialized at {}:{}.'.format(
                    out['address'], out['port']))

        if (self.sparseOutput != None):
            if not isinstance(self.sparseOutput, tuple):
                self.sparseOutput = [self.sparseOutput]
            self._sparseOutput_threads = []
            for out in self.sparseOutput:
                if isinstance(out, str):  # LSL outlet
                    raise NotImplementedError

                elif isinstance(out, dict):  # OSC port
                    if USE_LIBLO:
                        self._sparseOutput_threads.append(
                            Address(out['address'], out['port']))
                    else:
                        raise NotImplementedError
                    print('OSC sparse output client initialized at {}:{}.'.
                          format(out['address'], out['port']))

        # 3. Initialize internal buffers and variables
        self._init_processing(config)

    def _init_processing(self, config):
        """Initialize internal buffers and variables for EEG processing.

        Args:
            config (dict): dictionary containing various parameters. See
                DEFAULT_CONFIG below for default values.

                fs (float): sampling frequency
                n_channels (int): number of channels
                raw_buffer_len (int): raw data buffer length
                filt_buffer_len (int): filtered data buffer length
                window_len (int): processing window length
                step (int): number of samples between two consecutive
                    windows to process
                filter (tuple or dict): filtering parameters. If provided
                    as a tuple, the first and second elements should be
                    the `b` and `a` coefficients of a filter. If provided
                    as a dictionary, the fields `order`, `l_freq`, `h_freq`
                    and `method` are required; the function
                    pre.get_filter_coeff() will then be used to compute the
                    coefficients.
                    If None, don't use a filter (windows will be extracted
                    from the raw buffer).
                psd_window_len (int): length of the window to use for PSD
                psd_buffer_len (int): PSD buffer length
        """
        DEFAULT_CONFIG = {
            'fs': 256.,
            'n_channels': 5,
            'raw_buffer_len': 3 * 256,
            'filt_buffer_len': 3 * 256,
            'window_len': 256,
            'step': int(256 / 10),
            'filter': ([1], [1]),
            'filter_bank': {},
            'psd_window_len': 256.,
            'psd_buffer_len': 10
        }

        config = {**DEFAULT_CONFIG, **config}

        self.fs = config['fs']
        self.n_channels = config['n_channels']

        # Initialize EEG channel remapping parameters
        self.eeg_ch_remap = None
        if self.device_source.lower() == 'vive':
            self.eeg_ch_remap = [3, 1, 2, 3, 4]
            self.n_channels = 5
        if self.software_source.lower() == 'musedirect':
            self.eeg_ch_remap[-1] = 5
            self.n_channels = 5
        if self.device_source.lower() == 'leroy':
            self.eeg_ch_remap = None
            self.n_channels = 4
        if self.device_source.lower() == 'muse':
            self.eeg_ch_remap = None
            self.n_channels = 4
        if self.device_source.lower() == 'vivehr':
            self.eeg_ch_remap = [3, 1, 2, 3, 0]
            self.n_channels = 5

        # Initialize the EEG buffers
        raw_buffer_len = int(config['raw_buffer_len'])
        filt_buffer_len = int(config['filt_buffer_len'])

        self.eeg_buffer = ut.NanBuffer(raw_buffer_len, self.n_channels)
        self.filt_eeg_buffer = ut.CircularBuffer(filt_buffer_len,
                                                 self.n_channels)
        self.hpfilt_eeg_buffer = ut.CircularBuffer(filt_buffer_len,
                                                   self.n_channels)
        self.smooth_eeg_buffer = ut.CircularBuffer(filt_buffer_len,
                                                   self.n_channels)
        self.eyeH_buffer = ut.CircularBuffer(100, 1)

        # Initialize the EEG filter
        if config['filter']:
            if isinstance(config['filter'], tuple):
                b = config['filter'][0]
                a = config['filter'][1]
            elif isinstance(config['filter'], dict):
                b, a = ut.get_filter_coeff(self.fs, **config['filter'])
            zi = np.tile(signal.lfilter_zi(b, a), (self.n_channels, 1)).T
            self.bandpass_filt = {'b': b, 'a': a, 'zi': zi}
        if config['hpfilter']:
            b = config['hpfilter'][0]
            a = config['hpfilter'][1]
            zi = np.tile(signal.lfilter_zi(b, a), (self.n_channels, 1)).T
            self.hp_filt = {'b': b, 'a': a, 'zi': zi}
        if config['lpfilter']:
            b = config['lpfilter'][0]
            a = config['lpfilter'][1]
            zi = np.tile(signal.lfilter_zi(b, a), (self.n_channels, 1)).T
            self.lp_filt = {'b': b, 'a': a, 'zi': zi}

        # Initialize the filter bank
        if config['filter_bank']:
            self.filter_bank = {}
            for name, coeff in config['filter_bank'].items():
                zi = np.tile(signal.lfilter_zi(coeff[0], coeff[1]),
                             (self.n_channels, 1)).T
                self.filter_bank[name] = {
                    'b': coeff[0],
                    'a': coeff[1],
                    'zi': zi
                }

        # Initialize processing parameters
        self.window_len = int(config['window_len'])
        self.step = int(config['step'])

        # Initialize processing buffers
        psd_buffer_len = int(config['psd_buffer_len'])
        self.psd_buffer = ut.CircularBuffer(psd_buffer_len, 129,
                                            self.n_channels)

        # Initialize scoring histograms
        decayRate = 0.997
        self.hists = {
            'delta':
            ut.Histogram(1000,
                         self.n_channels,
                         bounds=(0, 50),
                         min_count=80,
                         decay=decayRate),
            'theta':
            ut.Histogram(1000,
                         self.n_channels,
                         bounds=(0, 30),
                         min_count=80,
                         decay=decayRate),
            'alpha':
            ut.Histogram(1000,
                         self.n_channels,
                         bounds=(0, 20),
                         min_count=80,
                         decay=decayRate),
            'beta':
            ut.Histogram(1000,
                         self.n_channels,
                         bounds=(0, 10),
                         min_count=80,
                         decay=decayRate),
            'gamma':
            ut.Histogram(1000,
                         self.n_channels,
                         bounds=(0, 10),
                         min_count=80,
                         decay=decayRate)
        }
        self.eyeH_hist = ut.Histogram(500,
                                      1,
                                      bounds=(0, 10000),
                                      min_count=80,
                                      decay=decayRate)
        self.emg_hist = ut.Histogram(500,
                                     1,
                                     bounds=(0, 10),
                                     min_count=80,
                                     decay=decayRate)
        self.blinkwait = 0
        self.blink = 0
        self.firstWindowProc = True
        self.band_names = 0
        self.band_powers = 0
        self.ratio_powers = 0
        self.ratio_names = 0

        # Used for calm score
        self.slow_calm_score = 0
        self.slow_alpha_score = 0
        self.eye_mov_percent_buffer = ut.CircularBuffer(256, 1)
        self.slow_calm_score_buffer = ut.CircularBuffer(512, 1)
        self.increments_buffer = ut.CircularBuffer(512, 1)
        self.low_freq_chs_buffer = ut.CircularBuffer(150, 2)
        self.low_freq_chs_std = 1

        ######################################################################
        # BODY Motion Processing,  Accelerometer, Gyro

        raw_buffer_len = 150
        filt_buffer_len = 150
        self.acc_window_len = 50
        self.acc_buffer = ut.NanBuffer(raw_buffer_len, 3)
        self.filt0_buffer = ut.CircularBuffer(filt_buffer_len, 3)
        self.heart_buffer = ut.CircularBuffer(150, 1)
        self.breath_buffer = ut.CircularBuffer(500, 1)

        # Initialize the Body Filters
        if config['filter0']:
            b = config['filter0'][0]
            a = config['filter0'][1]
            zi = np.tile(signal.lfilter_zi(b, a), (3, 1)).T
            self.filter0 = {'b': b, 'a': a, 'zi': zi}
        if config['filter1']:
            b = config['filter1'][0]
            a = config['filter1'][1]
            zi = np.tile(signal.lfilter_zi(b, a), (3, 1)).T
            self.filter1 = {'b': b, 'a': a, 'zi': zi}
        if config['filter2']:
            b = config['filter2'][0]
            a = config['filter2'][1]
            zi = signal.lfilter_zi(b, a)
            self.filter2 = {'b': b, 'a': a, 'zi': zi}
        if config['filter3']:
            b = config['filter3'][0]
            a = config['filter3'][1]
            zi = np.tile(signal.lfilter_zi(b, a), (3, 1)).T
            self.filter3 = {'b': b, 'a': a, 'zi': zi}
        if config['filter4']:
            b = config['filter4'][0]
            a = config['filter4'][1]
            zi = signal.lfilter_zi(b, a)
            self.filter4 = {'b': b, 'a': a, 'zi': zi}
        if config['filter5']:
            b = config['filter5'][0]
            a = config['filter5'][1]
            zi = signal.lfilter_zi(b, a)
            self.filter5 = {'b': b, 'a': a, 'zi': zi}
        if config['filter6']:
            b = config['filter6'][0]
            a = config['filter6'][1]
            zi = signal.lfilter_zi(b, a)
            self.filter6 = {'b': b, 'a': a, 'zi': zi}
        if config['filter7']:
            b = config['filter7'][0]
            a = config['filter7'][1]
            zi = signal.lfilter_zi(b, a)
            self.filter7 = {'b': b, 'a': a, 'zi': zi}

    def _update_eeg_liblo_osc(self, path, args):
        """Collect new EEG data point(s) from pyliblo OSC and process.

        Args:
            path (str): OSC path listened to
            args (list): received values
        """
        if self.verbose:
            print('Receiving OSC packet!')
        sample = np.array(args).reshape(1, -1)
        self._process_eeg(sample[:, :self.n_channels], 0)

    def _update_eeg_python_osc(self, unused_addr, args, *chs):
        """Collect new EEG data point(s) from python-osc and process.

        Args:
            path (str): OSC path listened to
            args (list): received values
        """
        if self.verbose:
            print('Receiving OSC packet!')
        sample = np.array(chs).reshape(1, -1)
        self._process_eeg(sample[:, :self.n_channels], 0)

    def _update_acc_liblo_osc(self, path, args):
        if self.verbose:
            print('Receiving ACC packet!')
        sample = np.array(args).reshape(1, -1)
        self._process_acc(sample[:, :3], 0)

    def _update_gyro_liblo_osc(self, path, args):
        if self.verbose:
            print('Receiving GYRO packet!')
        sample = np.array(args).reshape(1, -1)
        self._process_gyro(sample[:, :3], 0)

    def _process_eeg(self, samples, timestamp):
        """Process EEG.

        Process EEG. Includes buffering, filtering, windowing and pipeline.

        Args:
            samples (numpy.ndarray): new EEG samples to process
            timestamp (float): timestamp

        Returns:
            output (scalar): output of the pipeline
        """

        # Re-map
        if self.eeg_ch_remap:
            samples = samples[:, self.eeg_ch_remap]

        self.eeg_buffer.update(samples)
        self._send_outputs(samples, timestamp, 'raw_eeg')

        # Apply filtes
        filt_samples = samples

        if config['filter']:
            filt_samples, self.bandpass_filt['zi'] = signal.lfilter(
                self.bandpass_filt['b'],
                self.bandpass_filt['a'],
                samples,
                axis=0,
                zi=self.bandpass_filt['zi'])
            # self._send_filtered_eeg(filt_samples, timestamp)
        self.filt_eeg_buffer.update(filt_samples)

        if config['hpfilter']:
            filt_samples, self.hp_filt['zi'] = signal.lfilter(
                self.hp_filt['b'],
                self.hp_filt['a'],
                filt_samples,
                axis=0,
                zi=self.hp_filt['zi'])
        self.hpfilt_eeg_buffer.update(filt_samples)

        if config['lpfilter']:
            smooth_eeg_samples, self.lp_filt['zi'] = signal.lfilter(
                self.lp_filt['b'],
                self.lp_filt['a'],
                filt_samples,
                axis=0,
                zi=self.lp_filt['zi'])
            if self.debug_outputs:
                self._send_output_vec(smooth_eeg_samples, timestamp,
                                      'smooth_eeg')
        else:
            smooth_eeg_samples = filt_samples
        self.smooth_eeg_buffer.update(smooth_eeg_samples)

        if config['filter_bank']:
            filter_bank_samples = {}
            for name, filt_dict in self.filter_bank.items():
                filter_bank_samples[name], self.filter_bank[name]['zi'] = \
                    signal.lfilter(filt_dict['b'], filt_dict['a'],
                                   filt_samples, axis=0,
                                   zi=self.filter_bank[name]['zi'])
            low_freq_chs = filter_bank_samples['delta'][0, [
                0, 2
            ]]  #+ filter_bank_samples['theta'][0, [0, 1]]

        window = self.smooth_eeg_buffer.extract(self.window_len)

        eegEarWindow = window[:, 3]  #data from right ear Channel
        #eye movement computed from the difference between two frontal channels
        eyewindow = self.smooth_eeg_buffer.extract(200)
        eegFLWindow = eyewindow[:, 1]
        eegFRWindow = eyewindow[:, 2]
        #        norm_diff_eyes = eegFLWindow[-1] - eegFRWindow[-1]*np.nanstd(eegFLWindow, axis=0)/np.nanstd(eegFRWindow, axis=0)
        #        eyeH = np.reshape([np.square(norm_diff_eyes)], (1, 1))

        #find blinks in the left eegEarWindow
        blinkVal = ut.blink_template_match(eegEarWindow)
        if (blinkVal > 100000 and self.blink == 0):
            self.blink = 50
            self.blinkwait = 350
        else:
            if (self.blinkwait > 0):
                self.blinkwait -= 1
            if (self.blink > 0):
                self.blink -= 1

        # LONGER-TERM CALM SCORE based on Saccadic Eye Movement
        eye_mov_percent = np.reshape(
            np.percentile(eegFLWindow - eegFRWindow, 90), (1, 1))
        self.eye_mov_percent_buffer.update(eye_mov_percent)
        remap_eye_mov_percent = ut.sigmoid(
            self.eye_mov_percent_buffer.extract().mean(), 0.5, -10, 0)

        max_value = 1
        incr_decr = remap_eye_mov_percent < 0.2
        inc = self.increments_buffer.extract().mean()
        dpoints_per_second = 0.0005

        if incr_decr:
            self.slow_calm_score += dpoints_per_second * inc  # 1/max([max_value - self.slow_calm_score, 1])
        else:
            self.slow_calm_score -= dpoints_per_second * inc * 4  #0.7 # (self.slow_calm_score)/1280

        self.increments_buffer.update(np.reshape(incr_decr, (1, 1)))

        if self.slow_calm_score > max_value:
            self.slow_calm_score = max_value
        elif self.slow_calm_score < 0:
            self.slow_calm_score = 0

        self.slow_calm_score_buffer.update(
            np.reshape(self.slow_calm_score, (1, 1)))

        # Send outputs at a reduced sampling rate
        if self.smooth_eeg_buffer.pts % 3 == 0:
            self._send_output_vec(smooth_eeg_samples, timestamp, 'muse/eeg')
            if (self.blink > 0):
                self._send_output(np.array([[1]]), timestamp, 'blink')
            else:
                self._send_output(np.array([[0]]), timestamp, 'blink')
            self._send_output(blinkVal / 300000, timestamp, 'blinkVal')
            self._send_output(remap_eye_mov_percent, timestamp, 'saccad')

            self._send_output(
                np.reshape(self.slow_calm_score_buffer.extract().mean(),
                           (1, 1)), timestamp, 'calm')  # slow_calm_score
            self._send_output(low_freq_chs / self.low_freq_chs_std + 0.5,
                              timestamp, 'low_freq_chs')

        # process and send output at every step.   usually about every 1/10s
        if self.eeg_buffer.pts > self.step:
            self.eeg_buffer.pts = 0

            # Get filtered EEG window
            if config['lpfilter']:
                window = self.smooth_eeg_buffer.extract(self.window_len)
            else:
                window = self.eeg_buffer.extract(self.window_len)
            psd_raw_buffer = self.eeg_buffer.extract(self.window_len)

            # Get average PSD
            psd, f = ut.fft_continuous(psd_raw_buffer,
                                       n=int(self.fs),
                                       psd=True,
                                       log='psd',
                                       fs=self.fs,
                                       window='hamming')
            self.psd_buffer.update(np.expand_dims(psd, axis=0))
            mean_psd = np.nanmean(self.psd_buffer.extract(), axis=0)

            # find variance of eegWindow  for Bad Signal detact
            eegVar = np.nanvar(window, axis=0)
            self._send_output_vec(eegVar.reshape(1, self.n_channels),
                                  timestamp, 'hsi')

            if (self.sparseOutput != None):
                #send channel varience for signal quality indication at source Raspberry Pi
                #send(Address('10.0.0.14','1234'), "/hsi", eegVar[0],eegVar[1],eegVar[2],eegVar[3])
                self._send_sparseOutput_vec(eegVar.reshape(1, self.n_channels),
                                            timestamp, 'hsi')

            # Get band powers and ratios

            bandPowers, bandNames = ut.compute_band_powers(mean_psd,
                                                           f,
                                                           relative=False)
            ratioPowers, ratioNames = ut.compute_band_ratios(bandPowers)

            if (self.firstWindowProc):
                self.band_powers = bandPowers
                self.band_names = bandNames
                self.ratio_powers = ratioPowers
                self.ratio_names = ratioNames
                self.scores = np.zeros((len(self.band_names), self.n_channels))
                self.firstWindowProc = False

            if (eegVar.mean() < 300
                    and self.blinkwait == 0):  #threshold for good data
                for i, (name, hist) in enumerate(self.hists.items()):
                    self.band_powers = bandPowers
                    self.ratio_powers = ratioPowers
                    #send good data indicator based on mean eegWindow variance and blinkwait
                    self._send_output(np.array([[1]]), timestamp,
                                      'goodData')  #good data
            else:
                self._send_output(np.array([[0]]), timestamp,
                                  'goodData')  #good data

            self._send_outputs(self.band_powers, timestamp, 'bands')
            self._send_outputs(self.ratio_powers, timestamp, 'ratios')

            mask = ((f >= 30) & (f < 50))

            self.low_freq_chs_buffer.update(np.reshape(low_freq_chs, (1, -1)))
            self.low_freq_chs_std = self.low_freq_chs_buffer.extract().std(
                axis=0)

            emg_power = np.mean(mean_psd[mask, 0],
                                axis=0)  #HF power of right ear
            self._send_output(np.array([np.sqrt(emg_power) / 2]), timestamp,
                              'emg')

    def _process_acc(self, samples, timestamp):
        self._send_output_vec(samples, 0, 'muse/acc')

        self.acc_buffer.update(samples)
        window = self.acc_buffer.extract(self.acc_window_len)

        timestamps = np.linspace(0, 1 / 50 * self.acc_window_len,
                                 self.acc_window_len)
        new_fs = 250
        timestamps_upsampled = np.arange(timestamps[0], timestamps[-1],
                                         1 / new_fs)
        f = interpolate.interp1d(timestamps,
                                 window,
                                 kind='cubic',
                                 axis=0,
                                 fill_value=np.nan,
                                 assume_sorted=True)
        window_upsampled = f(timestamps_upsampled)
        for t in range(timestamps_upsampled.size - 5,
                       timestamps_upsampled.size):
            if self.debug_outputs:
                self._send_output(window_upsampled[t], 0, 'upsamp')
            upsample = np.array(window_upsampled[t]).reshape(1, 3)
            filt_samples, self.filter0['zi'] = signal.lfilter(
                self.filter0['b'],
                self.filter0['a'],
                upsample,
                axis=0,
                zi=self.filter0['zi'])
            self.filt0_buffer.update(filt_samples)
            if self.debug_outputs:
                self._send_outputs(filt_samples, 0, 'filter0')

            filt_samples, self.filter1['zi'] = signal.lfilter(
                self.filter1['b'],
                self.filter1['a'],
                filt_samples,
                axis=0,
                zi=self.filter1['zi'])
            if self.debug_outputs:
                self._send_outputs(filt_samples, 0, 'filter1')

            filt_samples = np.sqrt(np.sum(filt_samples**2, axis=1))
            if self.debug_outputs:
                self._send_output(filt_samples, 0, 'filter1L2')

            heart_samples, self.filter2['zi'] = signal.lfilter(
                self.filter2['b'],
                self.filter2['a'],
                filt_samples,
                axis=0,
                zi=self.filter2['zi'])

            if self.debug_outputs:
                self._send_output(heart_samples, 0, 'filter2')

            breathfilt_samples, self.filter3['zi'] = signal.lfilter(
                self.filter3['b'],
                self.filter3['a'],
                upsample,
                axis=0,
                zi=self.filter3['zi'])
            if self.debug_outputs:
                self._send_outputs(breathfilt_samples, 0, 'filter3')
        self.heart_buffer.update(heart_samples.reshape(1, 1))
        heartbuf = self.heart_buffer.extract(150)
        heartbufMin = heartbuf.min()
        heartbufMax = heartbuf.max()
        heart = np.reshape(
            (heartbuf[-1] - heartbufMin) / (heartbufMax - heartbufMin), (1, 1))
        self._send_output(heart, 0, 'heart')

        breathSmooth = breathfilt_samples[0, 2].reshape(1, )
        if self.debug_outputs:
            self._send_output(breathSmooth, 0, 'breathRaw')

        breathSmooth, self.filter4['zi'] = signal.lfilter(
            self.filter4['b'],
            self.filter4['a'],
            breathSmooth,
            axis=0,
            zi=self.filter4['zi'])
        if self.debug_outputs:
            self._send_output(breathSmooth, 0, 'breathSmooth')

        breathNorm, self.filter5['zi'] = signal.lfilter(self.filter5['b'],
                                                        self.filter5['a'],
                                                        breathSmooth,
                                                        axis=0,
                                                        zi=self.filter5['zi'])

        if self.debug_outputs:
            self._send_output(breathNorm, 0, 'breathNorm')

        breathFast, self.filter6['zi'] = signal.lfilter(self.filter6['b'],
                                                        self.filter6['a'],
                                                        breathSmooth,
                                                        axis=0,
                                                        zi=self.filter6['zi'])

        if self.debug_outputs:
            self._send_output(breathFast, 0, 'breathFast')

        breathLow, self.filter7['zi'] = signal.lfilter(self.filter7['b'],
                                                       self.filter7['a'],
                                                       breathSmooth,
                                                       axis=0,
                                                       zi=self.filter7['zi'])
        if self.debug_outputs:
            self._send_output(breathLow, 0, 'breathLow')

        self.breath_buffer.update(breathLow.reshape(1, 1))
        breathbuf = self.breath_buffer.extract(1000)
        breathbufMin = breathbuf.min()
        breathbufMax = breathbuf.max()
        breath = np.reshape(
            (breathbuf[-1] - breathbufMin) / (breathbufMax - breathbufMin),
            (1, 1))
        self._send_output(breath, 0, 'breath')

    def _process_gyro(self, samples, timestamp):
        self._send_output_vec(samples, 0, 'muse/gyro')

    def _send_outputs(self, output, timestamp, name):
        """Send pipeline outputs through the LSL or OSC stream.

        Args:
            output (scalar): output of the pipeline
            timestamp (float): timestamp
        """
        for out in self._output_threads:
            if isinstance(out, str):  # LSL outlet
                self._outlet.push_sample([output], timestamp=timestamp)

            else:  # OSC output stream
                if USE_LIBLO:
                    for c in range(self.n_channels):
                        new_output = [('f', x) for x in output[:, c]]
                        message = Message('/{}{}'.format(name, c), *new_output)
                        #send(out, Bundle(timestamp, message))
                        send(out, message)
                else:
                    for c in range(self.n_channels):
                        self._client.send_message('/{}{}'.format(name, c),
                                                  output[:, c])

            if self.verbose:
                print('Output: {}'.format(output))

    def _send_output_vec(self, output, timestamp, name):
        """Send pipeline outputs through the LSL or OSC stream.

        Args:
            output (scalar): output of the pipeline
            timestamp (float): timestamp
        """
        for out in self._output_threads:
            if isinstance(out, str):  # LSL outlet
                self._outlet.push_sample([output], timestamp=timestamp)

            else:  # OSC output stream
                if USE_LIBLO:
                    new_output = [('f', x) for x in output[0, :]]
                    message = Message('/{}'.format(name), *new_output)
                    #                    send(out, Bundle(timestamp, message))
                    send(out, message)
            if self.verbose:
                print('Output: {}'.format(output))

    def _send_sparseOutput_vec(self, output, timestamp, name):
        """Send pipeline outputs through the LSL or OSC stream.

        Args:
            output (scalar): output of the pipeline
            timestamp (float): timestamp
        """
        for out in self._sparseOutput_threads:
            if isinstance(out, str):  # LSL outlet
                self._outlet.push_sample([output], timestamp=timestamp)

            else:  # OSC output stream
                if USE_LIBLO:
                    new_output = [('f', x) for x in output[0, :]]
                    message = Message('/{}'.format(name), *new_output)
                    #send(out, Bundle(timestamp, message))
                    send(out, message)
            if self.verbose:
                print('sparseOutput: {}'.format(output))

    def _send_output(self, output, timestamp, name):
        """Send pipeline outputs through the LSL or OSC stream.
        NOT PER CHANNEL
        Args:
            output (scalar): output of the pipeline
            timestamp (float): timestamp
        """
        for out in self._output_threads:
            if isinstance(out, str):  # LSL outlet
                raise NotImplementedError
                # self._outlet.push_sample([output], timestamp=timestamp)

            else:  # OSC output stream
                if USE_LIBLO:
                    if (np.array(output).size == 1):
                        new_output = [('f', np.asscalar(output))]
                        message = Message('/{}'.format(name), *new_output)
                    else:
                        new_output = [('f', x) for x in output[:]]
                        message = Message('/{}'.format(name), *new_output)
#                   send(out, Bundle(timestamp, message))
                    send(out, message)
                else:
                    raise NotImplementedError


#                    self._client.send_message(}{}'.format(name),output[:])
            if self.verbose:
                print('Output: {}'.format(output))

    def _send_sparseOutput(self, output, timestamp, name):
        for out in self._sparseOutput_threads:
            if isinstance(out, str):  # LSL outlet
                raise NotImplementedError
            else:  # OSC output stream
                if USE_LIBLO:
                    if (np.array(output).size == 1):
                        new_output = [('f', np.asscalar(output))]
                        message = Message('/{}'.format(name), *new_output)
                    else:
                        new_output = [('f', x) for x in output[:]]
                        message = Message('/{}'.format(name), *new_output)
                    #send(out, Bundle(timestamp, message))
                    send(out, message)
                else:
                    raise NotImplementedError
            if self.verbose:
                print('spareOutput: {}'.format(output))

    def start(self):
        """Start receiving and processing EEG data.
        """
        self.started = True

        if isinstance(self.incoming, str):  # LSL inlet
            self.eeg_thread = Thread(target=self._update_eeg_lsl)
            self.eeg_thread.daemon = True
            self.eeg_thread.start()
        else:  # OSC input stream
            if USE_LIBLO:
                self._osc_server.add_method('/muse/eeg', None,
                                            self._update_eeg_liblo_osc)
                self._osc_server.add_method('/muse/acc', None,
                                            self._update_acc_liblo_osc)
                self._osc_server.add_method('/muse/gyro', None,
                                            self._update_gyro_liblo_osc)
                self._osc_server.start()
            else:
                self._dispatcher.map('Person2/eeg',
                                     self._update_eeg_python_osc, 'EEG')
                self._osc_server = osc_server.ThreadingOSCUDPServer(
                    ('127.0.0.1', self.incoming['port']), self._dispatcher)
                print('OSC server initialized at port {}.'.format(
                    self.incoming['port']))
                self._server_thread = Thread(
                    target=self._osc_server.serve_forever)
                self._server_thread.start()

    def stop(self):
        """
        """
        self.started = False

        if isinstance(self.incoming, dict):
            if not USE_LIBLO:
                self._server_thread.shutdown()
Example #44
0
                  default=default_fname,
                  help="Name of the recording file.")

# dejitter timestamps
dejitter = True

(options, args) = parser.parse_args()

print("looking for an EEG stream...")
streams = resolve_byprop('type', 'EEG', timeout=2)

if len(streams) == 0:
    raise (RuntimeError, "Cant find EEG stream")

print("Start aquiring data")
inlet = StreamInlet(streams[0], max_chunklen=12)
# eeg_time_correction = inlet.time_correction()

print("looking for a Markers stream...")
marker_streams = resolve_byprop('type', 'Markers', timeout=2)

if marker_streams:
    inlet_marker = StreamInlet(marker_streams[0])
    # marker_time_correction = inlet_marker.time_correction()
else:
    inlet_marker = False
    print("Cant find Markers stream")
print("after marker")
info = inlet.info()
description = info.desc()
"""Code modified from the example program to show how to read a multi-channel time series from LSL at https://github.com/OpenBCI/OpenBCI_GUI/blob/master/Networking-Test-Kit/LSL/lslStreamTest.py."""

from pylsl import StreamInlet, resolve_stream
import time
import serial

# set up Arduino serial port - replace with the one you are using
ser = serial.Serial('COM4', 9600)

# resolve an EMG stream on the lab network and notify the user
print("Looking for an EMG stream...")
streams = resolve_stream('type', 'EEG')
inlet = StreamInlet(streams[0])
#inlet_ch2 = StreamInlet(streams[1])
print("EMG stream found!")

# initialize time threshold and variables for storing time
time_thres = 500
prev_time = 0
flex_thres = 0.7

while True:

    samples, timestamp = inlet.pull_sample(
    )  # get EMG data sample and its timestamp

    curr_time = int(round(time.time() *
                          1000))  # get current time in milliseconds

    if ((samples[0] >= flex_thres) & (curr_time - time_thres > prev_time)
        ):  # if an EMG spike is detected from the cheek muscles send 'G'
Example #46
0
 def run(self):
     streams = resolve_bypred("*", timeout=5)
     self.streams = [StreamInlet(stream).info() for stream in streams]
     self.taskFinished.emit()
#predefined variables
last_report = 0  #define variable for printing of ET data

#participant id variable
print("This script looks for LSL Eye Tracking data...")
#participant_id = raw_input('Enter participant ID:')
participant_id = sys.argv[1]  #takes the name from script argument
filename = str(participant_id) + '_ETdata.csv'

# first resolve an EEG stream on the lab network
print("looking for EyeTracking LSL stream...")
streams = resolve_stream('name', 'Tobii')

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])
print("...found. Pulling data:")

#create CSV file and write received data to it
os.chdir(os.getcwd() + "\data")  #change cd to data folder
with open(
        filename, 'wb'
) as csvfile:  #mode needs to be "wb" in python 2 to remove blank rows
    csvwriter = csv.writer(csvfile)

    #main loop
    while True:
        ETdata, timestamp = inlet.pull_sample()
        ETdata.append(
            timestamp *
            1000)  #change timestamp to ms format and add to ET data list
Example #48
0
    def __init__(self, stream, fig, axes, window, scale, dejitter=True):
        """Init"""
        self.stream = stream
        self.window = window
        self.scale = scale
        self.dejitter = dejitter
        self.inlet = StreamInlet(stream, max_chunklen=buf)
        self.filt = True

        info = self.inlet.info()
        description = info.desc()

        self.sfreq = info.nominal_srate()
        self.n_samples = int(self.sfreq * self.window)
        self.n_chan = info.channel_count()

        ch = description.child('channels').first_child()
        ch_names = [ch.child_value('label')]

        for i in range(self.n_chan):
            ch = ch.next_sibling()
            ch_names.append(ch.child_value('label'))

        self.ch_names = ch_names

        fig.canvas.mpl_connect('key_press_event', self.OnKeypress)
        fig.canvas.mpl_connect('button_press_event', self.onclick)

        self.fig = fig
        self.axes = axes

        sns.despine(left=True)

        self.data = np.zeros((self.n_samples, self.n_chan))
        self.times = np.arange(-self.window, 0, 1. / self.sfreq)
        impedances = np.std(self.data, axis=0)
        lines = []

        for ii in range(self.n_chan):
            line, = axes.plot(self.times[::subsample],
                              self.data[::subsample, ii] - ii,
                              lw=1)
            lines.append(line)
        self.lines = lines

        axes.set_ylim(-self.n_chan + 0.5, 0.5)
        ticks = np.arange(0, -self.n_chan, -1)

        axes.set_xlabel('Time (s)')
        axes.xaxis.grid(False)
        axes.set_yticks(ticks)

        ticks_labels = [
            '%s - %.1f' % (ch_names[ii], impedances[ii])
            for ii in range(self.n_chan)
        ]
        axes.set_yticklabels(ticks_labels)

        self.display_every = int(0.2 / (12 / self.sfreq))

        # self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
        #                          'bandpass')

        self.bf = firwin(32,
                         np.array([1, 40]) / (self.sfreq / 2.),
                         width=0.05,
                         pass_zero=False)
        self.af = [1.0]

        zi = lfilter_zi(self.bf, self.af)
        self.filt_state = np.tile(zi, (self.n_chan, 1)).transpose()
        self.data_f = np.zeros((self.n_samples, self.n_chan))
Example #49
0
from bokeh.io import show, output_file
from bokeh.models import ColumnDataSource, FactorRange
from bokeh.plotting import figure, curdoc
from bokeh.transform import factor_cmap
from bokeh.palettes import Spectral6
import random
from pylsl import StreamInlet, resolve_stream, StreamInfo

# first resolve an EEG stream on the lab network
print("looking for an FreqBand stream...")
streams = resolve_stream('type', 'FreqBand')

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])
info = inlet.info()
print(info.as_xml())

print("The channel labels are as follows:")
ch = info.desc().child("channels").child("channel")
for k in range(info.channel_count()):
    print("  " + ch.child_value("label"))
    ch = ch.next_sibling()

#electrodes = ['F1', 'F2', 'O1', 'O2']
electrodes = [
    "AF3", "F7", "F3", "FC5", "T7", "P7", "O1", "O2", "P8", "T8", "FC6", "F4",
    "F8", "AF4"
]
bands = ['Theta', 'Alpha', 'LowBeta', 'HighBeta', 'Gamma']

data = {
"""Example program to show how to read a marker time series from LSL."""
import sys
sys.path.append('./pylsl') # help python find pylsl relative to this example program
from pylsl import StreamInlet, resolve_stream
 

# first resolve an EEG stream on the lab network
print("looking for an BatteryStatus stream...")
streams = resolve_stream('name', 'BatteryStatus')

streamsFound = len(streams)

if (streamsFound > 0):
	print 'found ' + str(streamsFound)
else:
	print 'found none'

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])

hostName = inlet.info().hostname()

while True:
	
	sample, timestamp = inlet.pull_sample()

	if(sample):
		print(str(timestamp) + ' Battery Status of ' + hostName + ' ' + str(sample[0]) +'%')
Example #51
0
# Index of the channel(s) (electrodes) to be used
# 0 = left ear, 1 = left forehead, 2 = right forehead, 3 = right ear
INDEX_CHANNEL = [0]

if __name__ == "__main__":
    """ 1. CONNECT TO EEG STREAM """

    # Search for active LSL streams
    print('Looking for an EEG stream...')
    streams = resolve_byprop('type', 'EEG', timeout=2)
    if len(streams) == 0:
        raise RuntimeError('Can\'t find EEG stream.')

    # Set active EEG stream to inlet and apply time correction
    print("Start acquiring data")
    inlet = StreamInlet(streams[0], max_chunklen=12)
    eeg_time_correction = inlet.time_correction()

    # Get the stream info and description
    info = inlet.info()
    description = info.desc()

    # Get the sampling frequency
    # This is an important value that represents how many EEG data points are
    # collected in a second. This influences our frequency band calculation.
    # for the Muse 2016, this should always be 256
    fs = int(info.nominal_srate())
    """ 2. INITIALIZE BUFFERS """

    # Initialize raw EEG data buffer
    eeg_buffer = np.zeros((int(fs * BUFFER_LENGTH), 1))
Example #52
0
import sys; sys.path.append('..') # help python find pylsl relative to this example program
from pylsl import StreamInlet, resolve_stream

# first resolve an EEG stream on the lab network
print("looking for an EEG stream...")
streams = resolve_stream('type','EEG')

# create a new inlet to read from the stream
inlet = StreamInlet(streams[0])

while True:
	# get a new sample (you can also omit the timestamp part if you're not interested in it)
	sample,timestamp = inlet.pull_sample()
	print(timestamp, sample)
Example #53
0
class Renderer(app.Canvas):
	def __init__(self):
		app.Canvas.__init__(self, title='Use your wheel to zoom!',
							keys='interactive')

		
		# first resolve an EEG stream on the lab network
		print("looking for an EEG stream...")
		streams = resolve_stream('name', 'RandomSpehricalData')
		streamInfo = streams[0]
		# create a new inlet to read from the stream
		self.inlet = StreamInlet(streamInfo)
		# Number of cols and rows in the table.
		self.nrows = streamInfo.channel_count()
		
		n = streamInfo.nominal_srate()
		ncols = 1

		# Number of signals.
		m = self.nrows*ncols

		# Various signal amplitudes.
		amplitudes = .1 + .2 * np.random.rand(m, 1).astype(np.float32)

		# Generate the signals as a (m, n) array.
		self.y = amplitudes * np.random.randn(m, n).astype(np.float32)
		
		color = np.repeat(np.random.uniform(size=(m, 3), low=.5, high=.9),
						  n, axis=0).astype(np.float32)


		# Signal 2D index of each vertex (row and col) and x-index (sample index
		# within each signal).
		index = np.c_[np.repeat(np.repeat(np.arange(ncols), self.nrows), n),
					  np.repeat(np.tile(np.arange(self.nrows), ncols), n),
					  np.tile(np.arange(n), m)].astype(np.float32)


		self.program = gloo.Program(VERT_SHADER, FRAG_SHADER)
		self.program['a_position'] = self.y.reshape(-1, 1)
		self.program['a_color'] = color
		self.program['a_index'] = index
		self.program['u_scale'] = (1., 1.)
		self.program['u_size'] = (self.nrows, ncols)
		self.program['u_n'] = n

		gloo.set_viewport(0, 0, *self.physical_size)

		self._timer = app.Timer('auto', connect=self.on_timer, start=True)

		gloo.set_state(clear_color='black', blend=True,
					   blend_func=('src_alpha', 'one_minus_src_alpha'))
		
		self.sampleFromLSL = None
		
		self.show()

	def on_resize(self, event):
		gloo.set_viewport(0, 0, *event.physical_size)

	def on_mouse_wheel(self, event):
		dx = np.sign(event.delta[1]) * .05
		scale_x, scale_y = self.program['u_scale']
		scale_x_new, scale_y_new = (scale_x * math.exp(2.5*dx),
									scale_y * math.exp(0.0*dx))
		self.program['u_scale'] = (max(1, scale_x_new), max(1, scale_y_new))
		self.update()

	def on_timer(self, event):
		"""Add some data at the end of each signal (real-time signals)."""
		k = 0 # need to become the count of samples available on this timer call
		sampleSet = None
		sample, timestamp = self.inlet.pull_sample(0.0)  
		sample = np.array([sample])
		while sample.any():
			k = k + 1
			sample, timestamp = self.inlet.pull_sample(0.0)
			sample = np.array([sample])
			sampleSet = np.c_[ sampleSet, sample ] 

		if k > 0:
			self.y[:, :-k] = self.y[:, k:]
			#y[:, -k:] = amplitudes * np.random.randn(m, k)
			self.y[:, -k:] = sampleSet

		self.program['a_position'].set_data(self.y.ravel().astype(np.float32))
		self.update()

	def on_draw(self, event):
		gloo.clear()
		self.program.draw('line_strip')