gentnerlab / pyoperant

python package for operant conditioning
BSD 3-Clause "New" or "Revised" License
13 stars 15 forks source link

Extend Event class for real-time experiments synchronized with electophysiology recordings #108

Open siriuslee opened 8 years ago

siriuslee commented 8 years ago

A few of us have discussed offline about the need for updating the code to better enable real-time experiments with simultaneous electrophysiology. The consensus way to address this problem is to synchronize the state of the panel with the electrophysiology data acquisition by making every change in state of the panel an Event instance. The event can then be logged and also sent to a separate interface for integration with any recording data.

There are multiple ways we could implement this, but the fundamentals would be: Each event instance is given a unique ID. The instance will contain all information related to the change in the panel state. Either the unique ID or a serialized dump of the full instance would then be sent to a custom interface.

This would require three main additions:

  1. Custom interface for recording software
    • Currently OpenEphys seems to be needed most
  2. EventStore class that stores events in standardized way
    • This could be implemented as the SubjectStore class is in the #100
    • Additional data storage might be necessary (SQLite, MongoDB, etc?)
  3. Each interface would have to be modified to output an event instance as right before an output or right after it receives an input (only if the input evaluates to true?)
    • Timing is of utmost importance here, so while it might be nice to do this at the level of the component or the hwio, I'm not sure if these would be too slow.

I'll see if I can come up with a suggested implementation shortly.

siriuslee commented 8 years ago

Just to update on our lab's current thoughts on this,

For each event in an experiment, we want to record which component changed, what the change was, additional metadata, and possibly a timestamp. This should be done by having each method of a component (e.g. Feeder.up or PeckPort.on) fill in a dictionary with this information and pass it along with the command down to the interface layer. Then, right before calling an output to the hardware, the interface will emit an event. The event is emitted in a separate thread for each EventHandler (e.g. an EventInterfaceHandler that sends the event information out a boolean output or an EventLogHandler that writes the event to a log file). By emitting the event right before actually calling out to the hardware and then having the EventHandlers run in separate threads (or processes) we should not have much of a delay.

The interesting question then is what to actually write to the interface as a boolean array. We were thinking about sending a start bit, 32 bits coding a 4 letter component name, 32 bits coding a 4 letter action description, then an optional metadata code (perhaps 128 bits) followed by a stop bit. The only thing we plan to send in the metadata would be an md5 hash of the stimulus.

I'll update this with example code when I get it going. Let me know if you have any suggestions!