def __init__(self, info: pylsl.StreamInfo, plt: pg.PlotItem): super().__init__(info) # calculate the size for our buffer, i.e. two times the displayed data bufsize = (2 * math.ceil(info.nominal_srate() * plot_duration), info.channel_count()) self.buffer = np.empty(bufsize, dtype=self.dtypes[info.channel_format()]) empty = np.array([]) # create one curve object for each channel/line that will handle displaying the data self.curves = [pg.PlotCurveItem(x=empty, y=empty, autoDownsample=True) for _ in range(self.channel_count)] for curve in self.curves: plt.addItem(curve)
def channel_names(stream_info: pylsl.StreamInfo) -> List[str]: """Extracts the channel names from the LSL Stream metadata.""" channels = [] if stream_info.desc().child("channels").empty(): return channels channel = stream_info.desc().child("channels").child("channel") for _ in range(stream_info.channel_count()): channel_name = channel.child_value("label") channels.append(channel_name) channel = channel.next_sibling() return channels
def __init__(self, info: pylsl.StreamInfo): # create an inlet and connect it to the outlet we found earlier. # max_buflen is set so data older the plot_duration is discarded # automatically and we only pull data new enough to show it # Also, perform online clock synchronization so all streams are in the # same time domain as the local lsl_clock() # (see https://labstreaminglayer.readthedocs.io/projects/liblsl/ref/enums.html#_CPPv414proc_clocksync) # and dejitter timestamps self.inlet = pylsl.StreamInlet(info, max_buflen=plot_duration, processing_flags=pylsl.proc_clocksync | pylsl.proc_dejitter) # store the name and channel count self.name = info.name() self.channel_count = info.channel_count()
def read_channel_labels_from_info(info: lsl.StreamInfo): channels_tag = info.desc().child('channels') if channels_tag.empty(): return None else: # TODO: this is hard to read. Write a generator for children with a given name in helpers labels = list() types = list() single_channel_tag = channels_tag.child(name="channel") for channel_id in range(info.channel_count()): labels.append(single_channel_tag.child_value(name='label')) types.append(single_channel_tag.child_value(name='type')) single_channel_tag = single_channel_tag.next_sibling( name='channel') return labels, types
def main(): # create a new StreamInfo object which shall describe our stream info = StreamInfo("MetaTester", "EEG", 8, 100, "float32", "myuid56872") # now attach some meta-data (in accordance with XDF format, # see also https://github.com/sccn/xdf/wiki/Meta-Data) chns = info.desc().append_child("channels") for label in ["C3", "C4", "Cz", "FPz", "POz", "CPz", "O1", "O2"]: ch = chns.append_child("channel") 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) # (...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)
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)
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)