Open botransfer opened 7 years ago
For the EEG and fNIRS data, is there a need to send it as binary instead of using floats? You may one day want to use another provided LSL-aware app (e.g. signal viewer, or some out of the box signal processing) and it would be good if the stream were in a typical format that the app knew how to deal with. If it needs to be in binary for storing in your data file then that encoding should probably happen on the Inlet->storage end.
As for the encoded video, I don't know enough about FFmpeg to know if it makes sense to use a different format (e.g. 3 ints per pixel) or to use binary. I assume it is variable-length. If that's the case then using a string stream is the recommended way. The fact that pylsl can't handle binary data is an oversight.
I think the channel_format
(is this what you mean by specifying the 'type'?) should still be cf_string
, because the channel_format variable is integrated into so many things. Other possible solutions are to check if the sample is a string on every push (or is this what you meant?) before attempting to encode, to use a keyword argument to push_sample
to tell it not to encode strings, or to create a new member variable that is a flag determining whether or not to encode.
Before we decide, I think you'll have to make sure that your StreamInfo explains that the data are binary. This can be done with the type
variable (or is this what you meant?). Then, upon creation of the Outlet, info.type() can be parsed and if it's 'xxx/raw'
then a flag can be sent to not encode the strings to binary.
I'm not sure which of these you opted for. If the string type check is too slow then the flag that is automatically set from info.type() is probably the best way to do it. If the string type check is really fast then that would be the most robust way (e.g., user enters the wrong 'type' in StreamInfo).
This problem still exists in the latest version of pylsl from this repository but if you do make a pull request then please base it on the latest version, not the version in the pypi.
Dear Mr Boulay,
Thank you for your reply.
I know about sending data as float32 etc., and in some cases (for me, such as sending motion capture or gyro data), I'm sending data as floats. However in some cases I wanted to have the data sent in binary and have them processed later, especially when I'm using a low-power embedded system with wireless connection (I know TCP isn't suitable for such case, but anyway).
For the details, perhaps it's better to show the diff. Please find my changes below. Although my modified version is based on somewhat old version of pylsl, the diff is made with the latest master branch from github. By the way, I'm now only using push/pull_sample() so the chunk send/receive part may not be working properly.
As you suggest, perhaps it's better to check the Python data type if it's a string or bytes/bytearrays.
And lastly, I'm not familiar with github; I made an account just for posting my issue. So I would appreciate if you would use the following diff to merge, if necessary.
Best Regards,
NISHIO Shuichi
--- labstreaminglayer/LSL/liblsl-Python/pylsl/pylsl.py 2017-01-21 00:25:05.746897900 +0900 +++ pylsl_mod.py 2017-01-12 14:22:55.000000000 +0900 @@ -21,6 +21,7 @@ import struct from ctypes import CDLL, util, byref, c_char_p, c_void_p, c_double, c_int, \ c_long, c_float, c_short, c_byte, c_longlong, cast, POINTER +import ctypes
all = ['IRREGULAR_RATE', 'DEDUCED_TIMESTAMP', 'FOREVER', 'cf_float32', 'cf_double64', 'cf_string', 'cf_int32', 'cf_int16', 'cf_int8', @@ -164,7 +165,7 @@ experimenters or data analysts). Cannot be empty. type -- Content type of the stream. By convention LSL uses the content types defined in the XDF file format specification where
self.is_binary = info.type().endswith("/raw")
def del(self): """Destroy an outlet. @@ -437,6 +439,16 @@
"""
if len(x) == self.channel_count:
self.is_binary = info.type().endswith("/raw")
def del(self): """Destructor. The inlet will automatically disconnect if destroyed.""" @@ -783,6 +796,22 @@ assign_to = None
errcode = c_int()
From: Chadwick Boulay notifications@github.com Subject: Re: [sccn/labstreaminglayer] Sending binary in python (#167) Date: Fri, 20 Jan 2017 09:39:24 -0800 Message-ID: sccn/labstreaminglayer/issues/167/274132397@github.com
For the EEG and fNIRS data, is there a need to send it as binary instead of using floats? You may one day want to use another provided LSL-aware app (e.g. signal viewer, or some out of the box signal processing) and it would be good if the stream were in a typical format that the app knew how to deal with. If it needs to be in binary for storing in your data file then that encoding should probably happen on the Inlet->storage end.
As for the encoded video, I don't know enough about FFmpeg to know if it makes sense to use a different format (e.g. 3 ints per pixel) or to use binary. I assume it is variable-length. If that's the case then using a string stream is the recommended way. The fact that pylsl can't handle binary data is an oversight.
I think the
channel_format
(is this what you mean by specifying the 'type'?) should still becf_string
, because the channel_format variable is integrated into so many things. Other possible solutions are to check if the sample is a string on every push (or is this what you meant?) before attempting to encode, to use a keyword argument topush_sample
to tell it not to encode strings, or to create a new member variable that is a flag determining whether or not to encode.Before we decide, I think you'll have to make sure that your StreamInfo explains that the data are binary. This can be done with the
type
variable (or is this what you meant?). Then, upon creation of the Outlet, info.type() can be parsed and if it's'xxx/raw'
then a flag can be sent to not encode the strings to binary.I'm not sure which of these you opted for. If the string type check is too slow then the flag that is automatically set from info.type() is probably the best way to do it. If the string type check is really fast then that would be the most robust way (e.g., user enters the wrong 'type' in StreamInfo).
This problem still exists in the latest version of pylsl from this repository but if you do make a pull request then please base it on the latest version, not the version in the pypi.
-- You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub: https://github.com/sccn/labstreaminglayer/issues/167#issuecomment-274132397
Ah, this is slightly more complicated than I had hoped. I see now that the push_sample_buf[tp]
has a different signature than the other push_sample functions because it also expects a lengths
param. Therefore, we cannot use the same function pointer variable for these data as we do for any other data type.
Fixing this up and testing will take a little time. Does your current solution work for you?
Dear Mr Boulay,
Yes, it seems to be working fine. Please find attached a small sample for sending/receiving raw audio data using PyAudio.
Best Regards,
NISHIO Shuichi
From: Chadwick Boulay notifications@github.com Subject: Re: [sccn/labstreaminglayer] Sending binary in python (#167) Date: Fri, 20 Jan 2017 19:09:01 -0800 Message-ID: sccn/labstreaminglayer/issues/167/274229416@github.com
Ah, this is slightly more complicated than I had hoped. I see now that the
push_sample_buf[tp]
has a different signature than the other push_sample functions because it also expects alengths
param. Therefore, we cannot use the same function pointer variable for these data as we do for any other data type.Fixing this up and testing will take a little time. Does your current solution work for you?
-- You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub: https://github.com/sccn/labstreaminglayer/issues/167#issuecomment-274229416
Hello. Is it possible to send binary data using the Python module of LSL? If I try to send a binary data as in a script following (as 'string'), I get an error shown in the last part. Right now, I am avoiding this issue by modifying the pylsl.py code so that it does not perform the unicode conversion whenever the "type" is specified as "xxx/raw" and directly passing the data to the C library, but if there is a better way, I would like to know how. Below are outputs on Windows 10 with Anaconda 4.2/Python3, with pylsl-1.10.5 installed by pip. My usage is to send/receive FFmpeg encoded audio/video data, EEG/NIRS data and so on (I'm using my own library which gathers data and stores to HDF5 file using Windows, Intel Edison and others).
Thank you for your kind response.
NISHIO Shuichi
from pylsl import StreamInfo, StreamOutlet info = StreamInfo('BioSemi', 'EEG', 1, 100, 'string', 'myuid34234') outlet = StreamOutlet(info) while True: mysample = [b'\x00\x0a'] outlet.push_sample(mysample) time.sleep(0.01)
(C:\Anaconda3) C:\home\Desktop\t>python test_send.py Traceback (most recent call last): File "test_send.py", line 6, in
outlet.push_sample(mysample)
File "C:\Anaconda3\lib\site-packages\pylsl\pylsl.py", line 432, in push_sample
x = [v.encode('utf-8') for v in x]
File "C:\Anaconda3\lib\site-packages\pylsl\pylsl.py", line 432, in
x = [v.encode('utf-8') for v in x]
AttributeError: 'bytes' object has no attribute 'encode'