Record Engines#

Record Engines define how continuous data, events, and spikes are written to disk.#

Type

Plugin::Type::RECORD_ENGINE

Base Class

RecordEngine

Template

open-ephys-plugins/record-engine-template

In the Open Ephys GUI, data formats are defined within plugins, making it straightforward to add compatibility with alternate formats. By default, the GUI contains Record Engines for the Binary Format, while the Open Ephys Format and NWB Format can be added via the Plugin Installer.

To create a new Record Engine, start with the Record Engine Template and add code that implements the following methods:

String getEngineId() const#
Returns:

A string that can be used to uniquely identify this record engine.

void openFiles(File rootFolder, int experimentNumber, int recordingNumber)#

Called when a new recording begins. The Record Engine should open all of the files it will need, as data writing will begin immediately after this method returns.

Parameters:
  • rootFolder – A Juce File object that specifies where this Record Engine’s files will be stored.

  • experimentNumber – The zero-based index of the current experiment. The experiment number is incremented every time acquisition is stopped (assuming at least one recording has taken place already).

  • recordingNumber – The one-based index of the current recording. The recording number is incremented every time recording is stopped.

void closeFiles()#

Called when a recording stops. The Record Engine should close all open files and perform all necessary cleanup operations inside this method.

void writeContinuousData(int writeChannel, int realChannel, const float *dataBuffer, const double *timestampBuffer, int size)#

Called whenever a new block of continuous data for one channel is available for writing.

Parameters:
  • writeChannel – The index of the continuous channel relative to all actively recorded channels.

  • realChannel – The index of the continuous channel relative to all channels processed by the Record Node.

  • dataBuffer – A read-only buffer of continuous data samples.

  • timestampABuffer – A real-only buffer of timestamps for each sample, in seconds relative to the start of recording.

  • size – The total number of valid samples.

void writeEvent(int eventChannel, const EventPacket &event)#

Called whenever a new event is available for writing.

Parameters:
  • eventChannel – The index of the event channel relative to all channels processed by the Record Node.

  • event – An EventPacket object containing the event sample number, timestamp, TTL line, and other relevant information.

void writeSpike(int electrodeIndex, const Spike *spike)#

Called whenever a new spike is available for writing.

Parameters:
  • eventChannel – The index of the electrode that generated this spike.

  • event – A pointer to a Spike object containing the spike sample number, timestamp, waveform, and sorted ID.

void writeTimestampSyncText(uint16 streamId, int64 sampleNumber, float sourceSampleRate, String text)#

Called once per incoming data stream at the start of each recording, in order to inform the Record Engine about the first sample number recorded by each data stream. Writing these values to disk is optional, but recommended.

Parameters:
  • streamId – The unique ID of the current data stream.

  • sampleNumber – The first sample number that will be recorded by this stream.

  • sourceSampleRate – The sample rate (in Hz) for this stream.

  • text – A message with additional information about this stream.

NPY Files#

All Record Engines have access to a NpyFile class that can be used to write data in NPY format. NPY is a simple format intended for storing array data, and which is straightforward to read with both Python and Matlab.

To create a new NPY file, a Record Engine should use the following methods:

NpyFile(String path, NpyType type)#

Constructor for a 1-dimensional NPY file with a specified type.

Parameters:
  • path – Absolute path to the file.

  • type – The data type for this file. The available types are defined in Metadata.h.

Here are some usage examples for common data types:

NpyFile* integerFile = new NpyFile("/path/to/file1.npy", NpyType(BaseType::INT16, 1))
NpyFile* floatFile = new NpyFile("/path/to/file2.npy", NpyType(BaseType::FLOAT, 1))

Once the file has been opened, data can be written using the following methods:

void writeData(const void *data, size_t nSamples)#

Writes a block of data to an NPY file.

Parameters:
  • data – An array of values to write; the data type must match the data type that was specified when opening the file.

  • nSamples – The total number of samples to write.

void increaseRecordCount(int count = 1)#

Increases the count of the number of records in the file. The record count can be increased at any time, but the final count must match the total number of samples that have been written in order for the file to be loaded properly.

Parameters:

count – The amount by which this file’s record count should be increased.

Sequential Block Files#

All Record Engines also have access to a SequentialBlockFile class that can be used to write data to compact binary files that are often have a “.bin” or “.dat” extension. This is how continuous data is stored in the Open Ephys Binary Format, and it is common to see these files in other neuroscience-specific formats as well.

To write data to a Sequential Block File, only three methods are needed:

SequentialBlockFile(int nChannels)#

Sequential Block File constructor.

Parameters:

nChannels – The total number of continuous channels to store in this file.

bool openFile(String filename)#

Opens the file at the requested location.

Parameters:

filename – Absolute path to the file.

bool writeChannel(uint64 startPos, int channel, int16 *data, int nSamples)#

Writes data for a particular channel.

Parameters:
  • startPos – The index of the first sample to write.

  • channel – The index of the channel to write.

  • data – Pointer to the first sample to be written.

  • nSamples – The total number of samples to write.