We have a 96-channel MAP Plexon system in the lab, which we use to record from an array implanted in V4. Originally we ran open-loop experiments (mapping stimuli and such), but soon we decided to perform closed loop experiments. Recording at 10kHz per channel sucks up a lot of CPU and thus the presentation software is on another computer (a Mac, while the Plexon recording system is Windows only). We hadn’t planned ahead for doing closed loop stuff, so the communication interface between the Mac and Win computers was rudimentary, an ITC18 system that sends TTL pulses over one of 8 channels from the Mac to the Windows computer which records these as Plexon events. Apparently with this setup there was some way of sending spikes from one or 2 channels to the Mac but this seemed very limited.
Question: how do you forward spikes from the Plexon system to a Mac? It should be noted that the Mac’s presentation software uses Matlab and runs PsychToolbox at its core. It should also be noted that Plexon has an API that runs in Matlab that can interface with its recordign software to read out spikes and events in realtime. So the basic idea then was to write a Matlab server that would run on the Plexon computer, read spikes, and spit them out over an unidentified protocol to a Matlab client on a Mac.
After some consultation with the friendly PsychToolbox mailing list I decided to send the spikes over IP, since the bandwidth required was just too much for a serial interface. There is a nice Matlab toolbox that does both TCP and UDP IP using a mex file (no JVM required) called pnet. I decided to use UDP instead of TCP. UDP is designed for streaming and is non-blocking, if a packet never reaches its endpoint it doesn’t try to resend it or anything, which seems good for sending spikes because in case of a hiccup I’d rather lose spikes than have them lagged by a number of seconds.
I ended up with this simple protocol:
- Server waits for incoming connections
- Client connects to server, sends out a message called “MARCO”, with a payload of the client’s IP and its prefered callback port
- Server connects to client, sends out a message called “POLO”, with a payload of the current timestamp of the Plexon server. This is essential, since otherwise the client has no way to sync its time to the server
- Server then continually streams messages called “SPIKES”, with a payload of channel event type (5 = spikes, 2 = Plexon event, I think), channel number (1-96), channel unit number (uses the clusters defined in the Plexon online sorter), and timestamp. These spikes are read using the Plexon API. Messages are chopped up if they are too big for UDP’s packet size limit.
- Client sends “KEEPALIVE” messages every N seconds to make sure that the server doesn’t disconnect it.
- When the client wants to stop streaming spikes, it sends a message “DISCONNECT” to the server. The server responds by freeing itself up for the next connection. In case of a bug on the client that causes it to not send a DISCONNECT message (ie fatal Matlab error), the server frees itself up after it hasn’t received a KEEPALIVE message for a while.
The first application thing we used it for was plotting receptive fields of a dozen neurons in real time, and that was pretty amazingly cool.
Here are scripts for implementing the server and client. The client doesn’t implement the DISCONNECT message sending because it simply receives the spikes continually, but reading the server code you should be able to figure out how to implement this. Many thanks to Kyler Brown (now at U of Chicago, I believe) for helping out debugging the thing. Hope this is useful to somebody, let me know.
Edit: I have updated the .zip file to include PlxConnection, which I had omitted. If you need precompiled mex files for pnet, you can get them as part of PsychToolbox. Thanks to Kyler Eastman from the Huk lab at UTAustin for letting me know about these issues.