Add support for byte buffers in MWorks data?

Hi Chris,

first i must say: I really like the new format of the PlugInCode!

And (more work) we got for near future only one wish left :slight_smile: (at least, I don’t know, what near future means in this context).
We want to save all dot position into a binary container. I try it with a BIG charbuffer/string, but converting float to string take to much time. When I copy the bytes directly (and convert every ‘\0’ to any other other char than ‘\0’) into a char buffer and copy that one into a stringparameter, the system is fast enough to calculate and store that values (my goal was to write 100.000 single floats into one buffer 60 times a second).

So, is it possible to add something like a byteBuffer to mWorks?

Lieben Gruß aus Göttingen
Ralf

Hi Ralf,

first i must say: I really like the new format of the PlugInCode!

Great, I’m glad to hear it!

So, is it possible to add something like a byteBuffer to mWorks?

We basically already have it, in that Datum::setString(const char *data, int size) can be used to store a byte array that contains embedded NUL’s. For example, here’s a bit of code you could add to DynamicRandomDots::getCurrentAnnounceDrawData that includes the raw bytes of the dots vector in a single field called “dots”:

Datum dotsData;
dotsData.setString((char*)(&(dots[0])), dots.size() * sizeof(GLfloat));
announceData.addElement("dots", dotsData);

I’ve tried this, and it seems to run pretty efficiently. The only issue is that the data file bindings currently don’t support non-text strings; the Python bindings will truncate the string at the first NUL, and the MATLAB bindings will probably blow up on any non-printable character. However, this should be pretty straightforward to fix.

I’ll be out of the office tomorrow (Friday), but I’ll look in to this some more when I return on Monday.

Chris

Perfect :slight_smile: The more important thing is to save the data for further (later) use.
To check if the saved data is consistent I exchange every NULL with a 0x1… and (no surprise for you) it looks fine (y). The speed of streaming the data from the plugIn via the server to disk is impressive. With my old Aluminum MacBook (DualCore) 9.000.000 GLfloats per second (written in 60 buffer á 150.000 GLfloats) seems to be possible…

Lieben Gruß aus Göttingen
Ralf

Hi Ralf,

FYI, I added a new parameter, “announce_dots”, to my dynamic random dots stimulus. Setting it to true causes the dots data to be included in the stimulus announcement as described above. The parameter is stored as an MWorks variable, so it can be toggled on and off while the stimulus is running.

Also, I updated the Python data bindings to support strings with embedded NULs. If you’ve extracted an #announceStimulus event from a data file, then you can use NumPy to convert the “dots” string back into a float array like so:

data = numpy.fromstring(event.value['dots'], numpy.float32)
x = data[::2]
y = data[1::2]

I’ll make a similar change to the MATLAB data bindings.

Chris

Hi Ralf,

The MATLAB data bindings now support reading byte buffers (finally!) If a byte array is not a valid C string (i.e. it doesn’t have exactly one NUL byte, located at the end of the array), the MATLAB bindings convert it into a uint8 array. If the data represent an array of single-precision floating-point dot coordinates, as described above, then you can extract the coordinates as follows:

data = typecast(event.data.dots, 'single');
x = data(1:2:end);
y = data(2:2:end);

This change should be in tonight’s nightly build.

Cheers,
Chris