Example #1
0
    def create_stream(self):
        logging.info('Looking for LSL stream...')
        available_streams = resolve_streams(5)

        if len(available_streams) > 0:
            self.stream_reader = StreamInlet(available_streams[0],
                                             max_chunklen=self.chunk_len,
                                             recover=False)

            # Extract stream info
            id = self.stream_reader.info().session_id()
            self.fs = int(self.stream_reader.info().nominal_srate())
            self.n_channels = int(self.stream_reader.info().channel_count())
            logging.info(f'Stream {id} found at {self.fs} Hz '
                         f'with {self.n_channels} channels')

            # Fetching channel names
            ch = self.stream_reader.info().desc().child('channels').first_child()
            self.ch_names = []
            for i in range(self.n_channels):
                self.ch_names.append(ch.child_value('label'))
                ch = ch.next_sibling()
            logging.info(f"Channel names: {self.ch_names}")
        else:
            logging.error('No stream found !')
            raise Exception
Example #2
0
    def setup_streams(self):
        # Outlets
        # Start/stop markers
        stream_name = self.outlet_names[0]
        info = StreamInfo(stream_name, 'Markers', 1, 0, 'string', 'UiOutput1')
        self.outlets[stream_name] = StreamOutlet(info)

        # StreamInlets
        # See also: resolve_byprop, resolve_pypred
        print('Searching for stream inlets...')
        while len(self.inlets) < len(self.inlet_names):
            # Iterate over LSL streams and connect them to an outlet
            streams = resolve_streams(wait_time=1.0)
            for stream in streams:
                if stream.name() in self.inlet_names and stream.name(
                ) not in self.inlets.keys():
                    self.inlets[stream.name()] = StreamInlet(stream)

            # Check which streams are missing and let user know
            missing_streams = [
                n for n in self.inlet_names if n not in self.inlets.keys()
            ]
            if any(missing_streams):
                print('Waiting for stream(s): {}'.format(missing_streams))

        print('''\nUI connected to streams:\n\tInlets: {}\n\tOutlets: {}'''.
              format(list(self.inlets.keys()), list(self.outlets.keys())))
Example #3
0
 def get_live_streams():
   live_streams = pylsl.resolve_streams()
   return {
     'command': 'live_streams',
     'data': {'streams': [*map(RelayMode.gen_stream_info_dict, live_streams)]},
     'error': None
   }
Example #4
0
    def connect_streams(self):
        '''
		Creates streamOutlets for sending commands to the UI. Then looks for
		streamInlets corresponding to the names given in the config file.
		Check infinitely until all streams are connected and prints out the
		names of the stream that are still not connected.

		LSL DOCS/CODE: https://github.com/chkothe/pylsl/blob/master/pylsl/pylsl.py
		# For selecting streamInlets, see also: resolve_byprop, resolve_pypred
		'''

        stream_name = self.outlet_names[0]
        info = StreamInfo(stream_name, 'Commands', 1, 0, 'int8', 'com1')
        self.outlets[stream_name] = StreamOutlet(info)

        # StreamInlets
        print('Searching for stream inlets...')
        while len(self.inlets) < len(self.inlet_names):
            # Iterate over LSL streams and connect them to an outlet
            streams = resolve_streams(wait_time=1.0)
            for stream in streams:
                if stream.name() in self.inlet_names and stream.name(
                ) not in self.inlets.keys():
                    self.inlets[stream.name()] = StreamInlet(stream)

            # Check which streams are missing and let user know
            missing_streams = [
                n for n in self.inlet_names if n not in self.inlets.keys()
            ]
            if any(missing_streams):
                print('Waiting for stream(s): {}'.format(missing_streams))

        print(
            '''\nDecoder connected to streams:\n\tInlets: {}\n\tOutlets: {}'''.
            format(list(self.inlets.keys()), list(self.outlets.keys())))
Example #5
0
def main():
    # firstly resolve all streams that could be shown
    inlets: List[Inlet] = []
    print("looking for streams")
    streams = pylsl.resolve_streams()

    # Create the pyqtgraph window
    pw = pg.plot(title='LSL Plot')
    plt = pw.getPlotItem()
    plt.enableAutoRange(x=False, y=True)

    # iterate over found streams, creating specialized inlet objects that will
    # handle plotting the data
    for info in streams:
        if info.type() == 'Markers':
            if info.nominal_srate() != pylsl.IRREGULAR_RATE \
                    or info.channel_format() != pylsl.cf_string:
                print('Invalid marker stream ' + info.name())
            print('Adding marker inlet: ' + info.name())
            inlets.append(MarkerInlet(info))
        elif info.nominal_srate() != pylsl.IRREGULAR_RATE \
                and info.channel_format() != pylsl.cf_string:
            print('Adding data inlet: ' + info.name())
            inlets.append(DataInlet(info, plt))
        else:
            print('Don\'t know what to do with stream ' + info.name())

    def scroll():
        """Move the view so the data appears to scroll"""
        # We show data only up to a timepoint shortly before the current time
        # so new data doesn't suddenly appear in the middle of the plot
        fudge_factor = pull_interval * .002
        plot_time = pylsl.local_clock()
        pw.setXRange(plot_time - plot_duration + fudge_factor,
                     plot_time - fudge_factor)

    def update():
        # Read data from the inlet. Use a timeout of 0.0 so we don't block GUI interaction.
        mintime = pylsl.local_clock() - plot_duration
        # call pull_and_plot for each inlet.
        # Special handling of inlet types (markers, continuous data) is done in
        # the different inlet classes.
        for inlet in inlets:
            inlet.pull_and_plot(mintime, plt)

    # create a timer that will move the view every update_interval ms
    update_timer = QtCore.QTimer()
    update_timer.timeout.connect(scroll)
    update_timer.start(update_interval)

    # create a timer that will pull and add new data occasionally
    pull_timer = QtCore.QTimer()
    pull_timer.timeout.connect(update)
    pull_timer.start(pull_interval)

    import sys

    # Start Qt event loop unless running in interactive mode or using pyside.
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()
    def getAvailableStreams(self):
        self.isAvailable = False  # Resets availability of streams -> Always false unless stream is found
        self.lslobj.clear(
        )  # Clears container of lsl inlets for new batch of inlets

        streams = pylsl.resolve_streams(
            wait_time=1.0
        )  # Contains information about all available lsl inlets

        # If streams list is empty, no streams are available
        # Clear the channelLayout of all previously listed channels, since no streams are available
        if len(streams) == 0:
            print("No streams available.")
            self.clearChannels()

        else:
            self.isAvailable = True
            print("Got all available streams. Starting streams now.....")

            for s in streams:
                lsl_inlet = pylsl.StreamInlet(s, max_buflen=4)
                lsl_inlet.open_stream()
                lsl = LSLRINGBUFFER(lsl_type=lsl_inlet.info().type(), name=lsl_inlet.info().name(), inlet=lsl_inlet,\
                        fs=lsl_inlet.info().nominal_srate(), buffer_duration=4.0, \
                        num_channels=lsl_inlet.info().channel_count(), uid=lsl_inlet.info().uid(),\
                        hostname=lsl_inlet.info().hostname(), channel_format='float64')
                self.lslobj[lsl_inlet.info().name()] = lsl
    def update_streams(self):
        if not self.streams:
            self.streams = pylsl.resolve_streams(wait_time=1.0)
            for k, stream in enumerate(self.streams):
                n = stream.name()
                stream_params = copy.deepcopy(self.def_stream_parms)
                stream_params['metadata'].update({
                    "name": n,
                    "ch_count": stream.channel_count(),
                    "ch_format": stream.channel_format(),
                    "srate": stream.nominal_srate()
                })
                # ch = stream.desc().child("channels").child("channel")
                # for ch_ix in range(stream.channel_count()):
                #     print("  " + ch.child_value("label"))
                #     ch = ch.next_sibling()

                stream_params['inlet'] = pylsl.StreamInlet(stream)
                stream_params['is_marker'] = stream.channel_format() in ["String", pylsl.cf_string]\
                                             and stream.nominal_srate() == pylsl.IRREGULAR_RATE
                if not stream_params['is_marker']:
                    if self.sig_strm_idx < 0:
                        self.sig_strm_idx = k
                    srate = stream.nominal_srate()
                    stream_params['downSampling'] = srate > 1000
                    stream_params['chunkSize'] = round(srate / self.chunksPerScreen * self.seconds_per_screen)
                    if stream_params['downSampling']:
                        stream_params['downSamplingFactor'] = round(srate / 1000)
                        n_buff = round(stream_params['chunkSize'] / stream_params['downSamplingFactor'])
                        stream_params['downSamplingBuffer'] = [[0] * int(stream.channel_count())] * n_buff
                self.stream_params.append(stream_params)

            self.updateStreamNames.emit([_['metadata'] for _ in self.stream_params], self.sig_strm_idx)
            self.start()
Example #8
0
def print_available_streams():
    """prints all available streams in their xml form
    
    Example::

        import liesl
        liesl.print_available_streams()
    """
    available_streams = pylsl.resolve_streams()
    for a in available_streams:
        print(a.as_xml())
Example #9
0
def net_streams():
    net_streams = resolve_streams(wait_time=1.0)
    if len(net_streams) > 1:
        for i in range(len(net_streams)):
            print('Net Stream: ', i + 1, net_streams[i])
        return 'Many Streams.'
    elif len(net_streams) == 1:
        print('Single Network Stream: ', net_streams)
        return 'Single Stream.'
    elif len(net_streams) is None:
        print('No streams on network..')
Example #10
0
def search_lsl(ignore_markers=False):
    import time

    # look for LSL servers
    amp_list = []
    amp_list_backup = []
    while True:
        streamInfos = pylsl.resolve_streams()
        if len(streamInfos) > 0:
            for index, si in enumerate(streamInfos):
                # LSL XML parser has a bug which crashes so do not use for now
                #desc = pylsl.StreamInlet(si).info().desc()
                #amp_serial = desc.child('acquisition').child_value('serial_number').strip()
                amp_serial = 'N/A'  # serial number not supported yet
                amp_name = si.name()
                if 'Markers' in amp_name:
                    amp_list_backup.append((index, amp_name, amp_serial))
                else:
                    amp_list.append((index, amp_name, amp_serial))
            break
        print('No server available yet on the network...')
        time.sleep(1)

    if ignore_markers is False:
        amp_list += amp_list_backup

    qc.print_c('-- List of servers --', 'W')
    for i, (index, amp_name, amp_serial) in enumerate(amp_list):
        if amp_serial == '':
            amp_ser = 'N/A'
        else:
            amp_ser = amp_serial
        qc.print_c('%d: %s (Serial %s)' % (i, amp_name, amp_ser), 'W')

    if len(amp_list) == 1:
        index = 0
    else:
        index = input(
            'Amp index? Hit enter without index to select the first server.\n>> '
        )
        if index.strip() == '':
            index = 0
        else:
            index = int(index.strip())
    amp_index, amp_name, amp_serial = amp_list[index]
    si = streamInfos[amp_index]
    assert amp_name == si.name()
    # LSL XML parser has a bug which crashes so do not use for now
    #assert amp_serial == pylsl.StreamInlet(si).info().desc().child('acquisition').child_value('serial_number').strip()
    print('Selected %s (Serial: %s)' % (amp_name, amp_serial))

    return amp_name, amp_serial
Example #11
0
def search_lsl(ignore_markers=False):
    import pylsl, time

    # look for LSL servers
    amp_list = []
    amp_list_backup = []
    while True:
        streamInfos = pylsl.resolve_streams()
        if len(streamInfos) > 0:
            for index, si in enumerate(streamInfos):
                amp_serial = pylsl.StreamInlet(si).info().desc().child(
                    'acquisition').child_value('serial_number').strip()
                amp_name = si.name()
                if 'Markers' in amp_name:
                    amp_list_backup.append((index, amp_name, amp_serial))
                else:
                    amp_list.append((index, amp_name, amp_serial))
            break
        print('No server available yet on the network...')
        time.sleep(1)

    if ignore_markers is False:
        amp_list += amp_list_backup

    qc.print_c('-- List of servers --', 'W')
    for i, (index, amp_name, amp_serial) in enumerate(amp_list):
        if amp_serial == '': amp_ser = 'N/A'
        else: amp_ser = amp_serial
        qc.print_c('%d: %s (Serial %s)' % (i, amp_name, amp_ser), 'W')

    if len(amp_list) == 1:
        index = 0
        dong = 0
    else:
        dong = 1
        index = raw_input(
            'Amp index? Hit enter without index to select the first server.\n>> '
        ).strip()
        index = int(index)  # dong
        #amp_index, amp_name, amp_serial= [(0, u'g.USBamp-1',u'UB-2010.06.31')]
    #qc.shell()
    amp_index, amp_name, amp_serial = amp_list[index]
    #if dong == 1:
    #amp_index = 0
    #print('!!!!!!!!!!!!!!!')
    si = streamInfos[amp_index]
    assert amp_name == si.name()
    assert amp_serial == pylsl.StreamInlet(si).info().desc().child(
        'acquisition').child_value('serial_number').strip()
    print('Selected %s (Serial: %s)' % (amp_name, amp_serial))

    return amp_name, amp_serial
Example #12
0
def prepare_data(time):
    a = resolve_streams()
    inlet = StreamInlet(a[0])
    print(a[0].name())
    data = []
    while len(data) <= time:
        # get a new sample (you can also omit the timestamp part if you're not
        # interested in it)
        sample, timestamp = inlet.pull_sample()
        data.append(sample)

    print("prepare_data was run")
    return data
Example #13
0
 def connect(self):
     '''Connecte le stream listener au stream vérifaint streamType et streamName.
     Renvoie si un stream à été trouvé. Peut lever une NameError
     Conçu en reprenant le code du groupe de PSC précédent'''
     streams = resolve_streams()
     for stream in streams:  #cherche parmi les flux arrivant celui qui vient de NIC
         if (stream.name() == self.streamName
                 and stream.type() == self.streamType):
             self._inlet = StreamInlet(
                 stream, 3)  #garde le stream en mémoire dans "inlet"
             self.offset = time.time() - self._inlet.pull_sample()[1]
             return True
     return False
Example #14
0
 def fetch_lsl_streams(self):
     """
 This method fetches available LSL streams, and updates variables
 """
     # Set loading labels
     self.wl_selected_streams.setText(LOADING_MSG)
     # Fetch data
     self.available_streams = pylsl.resolve_streams()
     self.available_stream_labels = list(
         map(lambda x: (self.gen_stream_label(x), 3),
             self.available_streams))
     # Update labels
     self.wl_selected_streams.setText(SELECT_STREAM_MSG)
    def check_lsl():
        streams = resolve_streams(wait_time=0.5)
        marker_status = False
        eeg_status = False

        for i in range(0, len(streams)):
            stream_name = streams[i].name()

            if stream_name == config.marker_stream_name:
                marker_status = True
            if stream_name == config.eeg_stream_name:
                eeg_status = True

        return eeg_status, marker_status
Example #16
0
def print_available_streams_fields(fields: List[str]):
    """prints a specific field from all available streams
    Example::

        import liesl
        liesl.streams.finder.print_available_streams_fields()
    """
    available_streams = pylsl.resolve_streams()
    count = 0
    for a in available_streams:
        print("Stream #{0:3.0f}".format(count))
        count += 1
        for field in fields:
            value = a.__getattribute__(field)()
            print("{0} = {1}".format(field, value))
Example #17
0
    def is_available():
        """Check if an lsl stream is available on the network.

        Returns
        -------

        ok : Boolean
            True if there is a lsl stream, False otherwise

        """
        # Return True only if at least one lsl stream can be found on
        # the network
        if pylsl.resolve_streams():
            return True
        return False
Example #18
0
    def __init__(self, pipeline, **kwargs):

        kwargs['title'] = 'LSL stream'
        super().__init__(pipeline, **kwargs)

        stream_names = [info.name() for info in pylsl.resolve_streams()]
        values = [self.STREAM_NAME_PLACEHOLDER] + stream_names
        try:
            value = self.source_node.stream_name
        except AttributeError:
            value = self.STREAM_NAME_PLACEHOLDER
        stream_names_combo = parameterTypes.ListParameter(
            name=self.STREAM_NAMES_COMBO_NAME, values=values, value=value)
        stream_names_combo.sigValueChanged.connect(self._on_stream_name_picked)
        self.stream_names_combo = self.addChild(stream_names_combo)
Example #19
0
    def is_available():
        """Check if an lsl stream is available on the network.

        Returns
        -------

        ok : Boolean
            True if there is a lsl stream, False otherwise

        """
        # Return True only if at least one lsl stream can be found on
        # the network
        if pylsl.resolve_streams():
            return True
        return False
Example #20
0
def scan():
    """ Scan through all visible streams and check if they can be connected to
    """
    colorama.init()

    streams = pylsl.resolve_streams()

    connection_ok = []
    for stream in streams:
        # Check if stream can be connected to
        inlet = pylsl.StreamInlet(stream)
        if inlet:
            connection_ok.append(True)
        else:
            connection_ok.append(False)
    return streams, connection_ok
Example #21
0
def scan():
    """ Scan through all visible streams and check if they can be connected to
    """
    colorama.init()

    streams = pylsl.resolve_streams()

    connection_ok = []
    for stream in streams:
        # Check if stream can be connected to
        inlet = pylsl.StreamInlet(stream)
        if inlet:
            connection_ok.append(True)
        else:
            connection_ok.append(False)
    return streams, connection_ok
Example #22
0
def list_lsl_streams(ignore_markers=False,
                     logger=logger,
                     state=mp.Value('i', 1)):
    """
    List all the available outlets on LSL network.

    Parameters
    ----------
    ignore_markers : bool
        If True, ignore streams with Marker type.
    logger : logging.Logger
        The logger to output info.
    state: mp.Value
        The multiprocess sharing variable, used to stop search from another
        process.
    """

    # look for LSL servers
    stream_list = []
    stream_list_markers = []

    while state.value == 1:

        streamInfos = pylsl.resolve_streams()

        if len(streamInfos) > 0:

            for index, streamInfo in enumerate(streamInfos):
                stream_name = streamInfo.name()
                if 'Markers' in streamInfo.type():
                    stream_list_markers.append((index, stream_name))
                else:
                    stream_list.append((index, stream_name))
            break

        logger.info('No server available yet on the network...')
        time.sleep(1)

    if ignore_markers is False:
        stream_list += stream_list_markers

    logger.info('-- List of servers --')

    for i, (index, stream_name) in enumerate(stream_list):
        logger.info(f'{i}: {stream_name}')

    return stream_list, streamInfos
def list_lsl_streams(window, state=None, logger=logger, ignore_markers=False):
    """
    """
    import time
    #  GUI sharing variable to stop the process, 1 = start, 0 = stop
    if not state:
        state = mp.Value('i', 1)

    # look for LSL servers
    amp_list = []
    amp_list_backup = []

    while True:
        #  Stop if recording state (mp shared variable) is set to 0 from GUI
        if not state.value:
            sys.exit()
        streamInfos = pylsl.resolve_streams()
        if len(streamInfos) > 0:
            for index, si in enumerate(streamInfos):
                # LSL XML parser has a bug which crashes so do not use for now
                #desc = pylsl.StreamInlet(si).info().desc()
                #amp_serial = desc.child('acquisition').child_value('serial_number').strip()
                amp_serial = 'N/A' # serial number not supported yet
                amp_name = si.name()
                if 'Markers' in amp_name:
                    amp_list_backup.append((index, amp_name, amp_serial))
                else:
                    amp_list.append((index, amp_name, amp_serial))
            break
        logger.info('No server available yet on the network...')
        time.sleep(1)

    if ignore_markers is False:
        amp_list += amp_list_backup

    logger.info('-- List of servers --')
    for i, (index, amp_name, amp_serial) in enumerate(amp_list):
        if amp_serial == '':
            amp_ser = 'N/A'
        else:
            amp_ser = amp_serial
        logger.info('%d: %s (Serial %s)' % (i, amp_name, amp_ser))
        window.selector_window.textEdit_streaminfo.append('%d: %s (Serial %s)' % (i, amp_name, amp_ser))

    window.stream_selector_window.show()
    return amp_list, streamInfos
Example #24
0
def test_BaseStream_record_data_indefinitely():
    """Test rteeg.base.BaseStream"""
    # Start a LabStreamingLayer stream of synthetic data.
    eeg_out = SyntheticData("EEG", 32, 100, send_data=True)
    inlet = StreamInlet(resolve_streams(wait_time=1.)[0])
    base = BaseStream()

    # Check that length of base.data increases.
    len_0 = len(base.data)
    t = threading.Thread(target=base._record_data_indefinitely, args=(inlet,))
    t.daemon = True
    t.start()
    time.sleep(2.)
    len_1 = len(base.data)
    assert len_1 > len_0, "Data not being recorded."

    # Clean up.
    base._kill_signal.set()
    eeg_out.stop()
Example #25
0
def get_lsl_streams():
    """Discover all LSL streams available on the local network.

    Returns:
        dict[str, dict[str, pylsl.StreamInfo]]: Streams mapped to source/type.
            Keys are source IDs; values are dictionaries for which the keys
            are stream types and the values are stream.

    Example:
        When EEG and accelerometer streams are found for a single Muse headset:

        >>> get_lsl_streams()
        {'Muse-00:00:00:00:00:00': {'EEG': <pylsl.pylsl.StreamInfo>,
                                    'accelerometer': <pylsl.pylsl.StreamInfo>}}
    """
    streams = [(stream.source_id(), stream.type(), stream)
               for stream in lsl.resolve_streams(wait_time=2)]
    streams_dict = streams_dict_from_streams(streams)
    return streams_dict
Example #26
0
def get_streaminfos_matching(**kwargs) -> List[StreamInfo]:
    """

    args
    ----
    **kwargs:
        keyword arguments to identify the desired stream
        
    returns
    -------
    sinfos: List[StreamInfo]
        a list of StreamInfo matching the kwargs
    
    
    Example::
    
        import liesl
        sinfos = liesl.get_streaminfos_matching(name="Liesl-Mock-EEG")

    """
    # find all available streams, check whether they are fitting with kwargs
    available_streams = pylsl.resolve_streams()
    if len(available_streams) == 0:
        return None
    fitting_streams = []
    for st in available_streams:
        for k, v in kwargs.items():
            if eval("st." + k + "()") != v:
                break
        else:
            fitting_streams.append(st)

    # either throws a timepout, returns a streaminfo or a list of streaminfos
    if len(fitting_streams) == 0:
        return None
    else:
        return fitting_streams
Example #27
0
    ft_output.connect(ftc_host, ftc_port)
    if debug > 0:
        print("Connected to output FieldTrip buffer")
except:
    raise RuntimeError("cannot connect to output FieldTrip buffer")

print("looking for an LSL stream...")
start = time.time()
selected = []
while len(selected) < 1:
    if (time.time() - start) > timeout:
        print("Error: timeout while waiting for LSL stream")
        raise SystemExit

    # find the desired stream on the lab network
    streams = lsl.resolve_streams()
    for stream in streams:
        inlet = lsl.StreamInlet(stream)
        name = inlet.info().name()
        type = inlet.info().type()
        source_id = inlet.info().source_id()
        # determine whether this stream should be further processed
        match = True
        if len(lsl_name):
            match = match and lsl_name == name
        if len(lsl_type):
            match = match and lsl_type == type
        if match:
            # select this stream for further processing
            selected.append(stream)
            print('-------- STREAM(*) ------')
Example #28
0
def enumerate():
    streams = resolve_streams()
    for stream in streams:
        print(
            f"name: {stream.name()}, type: {stream.type()}, source_id: {stream.source_id()}"
        )
Example #29
0
			if(dataPoint > state.highestAmplitude):
					state.highestAmplitude = dataPoint

			remappedValue = interp(dataPoint, [state.lowestAmplitude, state.highestAmplitude], [-0.5, 0.5])
			lslSampleSet.append( remappedValue )# demo use only one channel
			
			sample,ts = inlet.pull_sample(0.0)

		sampleSet = lslSampleSet

	if any(sampleSet):
		data[state.lastSampleOffset:state.currentSampleOffset,1] = sampleSet
	

	program['a_position'].set_data(data)
	
	c.update()


streams = resolve_streams()

if not any(streams):
	print 'No Streams found'
	exit()

inlet = StreamInlet(streams[0])

c.show()
timer.start()
app.run()
Example #30
0
def _start():
    '''Start the module
    This uses the global variables from setup and adds a set of global variables
    '''
    global parser, args, config, r, response, patch, name
    global monitor, timeout, lsl_name, lsl_type, ft_host, ft_port, ft_output, start, selected, streams, stream, inlet, type, source_id, match, lsl_id, channel_count, channel_format, nominal_srate, samples, blocksize

    # this can be used to show parameters that have changed
    monitor = EEGsynth.monitor(name=name,
                               debug=patch.getint('general', 'debug'))

    # get the options from the configuration file
    timeout = patch.getfloat('lsl', 'timeout', default=30)
    lsl_name = patch.getstring('lsl', 'name')
    lsl_type = patch.getstring('lsl', 'type')

    try:
        ft_host = patch.getstring('fieldtrip', 'hostname')
        ft_port = patch.getint('fieldtrip', 'port')
        monitor.info('Trying to connect to buffer on %s:%i ...' %
                     (ft_host, ft_port))
        ft_output = FieldTrip.Client()
        ft_output.connect(ft_host, ft_port)
        monitor.info("Connected to output FieldTrip buffer")
    except:
        raise RuntimeError("cannot connect to output FieldTrip buffer")

    monitor.success("looking for an LSL stream...")
    start = time.time()
    selected = []
    while len(selected) < 1:
        if (time.time() - start) > timeout:
            monitor.error("Error: timeout while waiting for LSL stream")
            raise SystemExit

        # find the desired stream on the lab network
        streams = lsl.resolve_streams()
        for stream in streams:
            inlet = lsl.StreamInlet(stream)
            name = inlet.info().name()
            type = inlet.info().type()
            source_id = inlet.info().source_id()
            # determine whether this stream should be further processed
            match = True
            if len(lsl_name):
                match = match and lsl_name == name
            if len(lsl_type):
                match = match and lsl_type == type
            if match:
                # select this stream for further processing
                selected.append(stream)
                monitor.success('-------- STREAM(*) ------')
            else:
                monitor.success('-------- STREAM ---------')
            monitor.info("name", name)
            monitor.info("type", type)
        monitor.success('-------------------------')

    # create a new inlet from the first (and hopefully only) selected stream
    inlet = lsl.StreamInlet(selected[0])

    # give some feedback
    lsl_name = inlet.info().name()
    lsl_type = inlet.info().type()
    lsl_id = inlet.info().source_id()
    monitor.success('connected to LSL stream %s (type = %s, id = %s)' %
                    (lsl_name, lsl_type, lsl_id))

    channel_count = inlet.info().channel_count()
    channel_format = inlet.info().channel_format()
    nominal_srate = inlet.info().nominal_srate()

    ft_output.putHeader(channel_count, nominal_srate,
                        FieldTrip.DATATYPE_FLOAT32)

    # this is used for feedback
    samples = 0
    blocksize = 1

    # there should not be any local variables in this function, they should all be global
    if len(locals()):
        print('LOCALS: ' + ', '.join(locals().keys()))
Example #31
0
def list_all_streams(wait_time=1.0):
    # todo: be a little more proactive here
    infos = resolve_streams(wait_time)
Example #32
0
    def connect(self, bufsize=1, winsize=1, stream_name=None, eeg_only=False):
        """
        Search for the available streams on the LSL network and connect to the
        appropriate ones. If a LSL stream fullfills the requirements (name...),
        a connection is established.

        This function is called while instanciating a StreamReceiver and can be
        recall to reconnect to the LSL streams.

        Parameters
        ----------
        bufsize : int
            The buffer's size [secs]. 1-day is the maximum size.
            Large buffer may lead to a delay if not pulled frequently.
        winsize : int
            To extract the latest winsize samples from the buffer [secs].
        stream_name : list | str
            Servers' name or list of servers' name to connect to.
            None: no constraint.
        eeg_only : bool
            If true, ignore non-EEG servers.
        """
        self._streams = dict()
        self._is_connected = False
        server_found = False

        while not server_found:

            if stream_name is None:
                logger.info("Looking for available lsl streaming servers...")
            else:
                logger.info(f"Looking for server(s): '{stream_name}'...")

            streamInfos = pylsl.resolve_streams()

            if len(streamInfos) > 0:
                for streamInfo in streamInfos:

                    # EEG streaming server only?
                    if eeg_only and streamInfo.type().lower() != 'eeg':
                        logger.info(f'Stream {streamInfo.name()} skipped.')
                        continue
                    # connect to a specific amp only?
                    if isinstance(stream_name, str) and \
                            streamInfo.name() != stream_name:
                        if stream_name in streamInfo.name():
                            logger.info(f'Stream {stream_name} skipped, '
                                        f'however {streamInfo.name()} exists.')
                        continue
                    if isinstance(stream_name, (list, tuple)) and \
                            streamInfo.name() not in stream_name:
                        logger.info(f'Stream {streamInfo.name()} skipped.')
                        continue
                    # do not connect to StreamRecorderInfo
                    if streamInfo.name() == 'StreamRecorderInfo':
                        continue

                    # EEG stream
                    if streamInfo.type().lower() == "eeg":
                        self._streams[streamInfo.name()] = StreamEEG(
                            streamInfo, bufsize, winsize)
                    # Marker stream
                    elif streamInfo.nominal_srate() == 0:
                        self._streams[streamInfo.name()] = StreamMarker(
                            streamInfo, bufsize, winsize)

                    server_found = True
            time.sleep(1)

        for stream in self._streams:
            if stream not in self._acquisition_threads.keys():
                self._acquisition_threads[stream] = None

        self.show_info()
        self._is_connected = True
        logger.info('Ready to receive data from the connected streams.')
Example #33
0
def fetch(plot_duration=10, update_interval=30, pull_interval=250, fn=fn):
    """
    Receive, preprocess and plot LSL recording
    Args:
    plot_duration: int
        how many seconds of data to show
    update_interval: int
        ms between screen updates
    pull_interval: int
        ms of each pull operation
    fn: function
        preprocessing function
    """

    # Create the pyqtgraph window
    pw = pg.plot(title='LSL Plot')
    plt = pw.getPlotItem()
    plt.setAxisItems = {'bottom': TimeAxisItem(orientation='bottom')}
    plt.enableAutoRange(x=False, y=True)

    # firstly resolve all streams that could be shown
    streams = pylsl.resolve_streams()
    inlets = read_streams(streams, plot_duration, plt)

    # iterate over found streams, creating specialized inlet objects that will
    # handle plotting the data

    def scroll():
        """Move the view so the data appears to scroll"""
        # We show data only up to a timepoint shortly before the current time
        # so new data doesn't suddenly appear in the middle of the plot
        fudge_factor = pull_interval * .002
        plot_time = pylsl.local_clock()
        pw.setXRange(plot_time - plot_duration + fudge_factor,
                     plot_time - fudge_factor)

    def update():
        # Read data from the inlet.
        # Use a timeout of 0.0 so we don't block GUI interaction.
        mintime = pylsl.local_clock() - plot_duration
        # call pull_and_plot for each inlet.
        # Special handling of inlet types (markers, continuous data) is done in
        # the different inlet classes.
        if inlets:
            for inlet in inlets:
                if isinstance(inlet, DataInlet):
                    try:
                        ts, window = inlet.pull_and_plot(mintime, plt)
                        detected = fn(ts, window)
                        if detected:
                            for t in detected:
                                plt.addItem(
                                    pg.InfiniteLine(
                                        t,
                                        angle=90,
                                        movable=False,
                                        pen=pg.mkPen(color=(255, 119, 0),
                                                     style=QtCore.Qt.DotLine)))

                    except TypeError:
                        continue

                elif isinstance(inlet, MarkerInlet):
                    inlet.pull_and_plot(mintime, plt)

    # create a timer that will move the view every update_interval ms
    update_timer = QtCore.QTimer()
    update_timer.timeout.connect(scroll)
    update_timer.start(update_interval)

    # create a timer that will pull and add new data occasionally
    pull_timer = QtCore.QTimer()
    pull_timer.timeout.connect(update)
    pull_timer.start(pull_interval)

    # Start Qt event loop unless running in interactive mode or using pyside.
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        app = QtGui.QApplication.instance()
        sys.exit(app.exec_())