Open Ephys format
Open Ephys data format (version 0.4)
Headers
All headers are 1024 bytes long, and are written as a MATLAB-compatible string. Therefore, loading the header (regardless of its content), can be done with three lines of code:
hdr = fread(fid, 1024, 'char*1');
eval(char(hdr'));
info.header = header;
This is actually pretty handy, since any changes to the header format (which will probably happen often) won't affect the code for reading data files. However, note that reading files using this method also creates a security risk if there is any doubt as to the origin of the file, since reading the header involves executing a portion of the file as MATLAB code. Therefore, be careful if you are working with files in one of these formats that you did not create yourself.
The current header format uses ASCII encoding, and defines MATLAB struct with the following fields and values:
- format = 'Open Ephys Data Format'
- version = 0.4
- header_bytes = 1024
- description = '(String describing the header)'
- date_created = 'dd-Mmm-yyyy hhmmss'
- channel = '(String with channel name)'
- channelType = '(String describing the channel type)'
- sampleRate = (integer sampling rate)
- blockLength = 1024
- bufferSize = 1024
- bitVolts = (floating point value of microvolts/bit)
For those not using MATLAB, each header entry is on a separate line with the following format:
- field names appear after a "header." prefix
- field names and values are separated by " = "
- the value of the field is in plain text, with intended strings enclosed in single quotes (as demonstrated above)
- each line is terminated with a semicolon
Continuous data files (.continuous)
Each continuous channel within each processor has its own file, titled "XXX_CHY.continuous
", where XXX
= the processor ID #, and Y
= the channel number. For each record, it saves:
- One little-endian int64 timestamp (actually a sample number; this can be converted to seconds using the sampleRate variable in the header)
- One little-endian uint16 number (N) indicating the samples per record (always 1024, at least for now)
- One little-endian uint16 recording number (version 0.2 and higher)
- 1024 big-endian int16 samples
- 10-byte record marker (0 1 2 3 4 5 6 7 8 255)
This makes up a record of 2070 bytes (= 8 + 2 + 2 + 2048 + 10).
If a file is opened or closed in the middle of a record, the leading or trailing samples are set to zero.
Event files (.events)
Non-spike events are saved in a different format. Events generated by all channels are dumped into the file "all_channels.events
" with the following data for each event:
- int64 timestamp (to align with timestamps from the continuous records)
- int16 sample position within a buffer
- uint8 event type (all the events that are saved have type TTL = 3 ; Network Event = 5)
- uint8 processor ID (the processor this event originated from)
- uint8 event ID (code associated with this event, usually 1 or 0)
- uint8 event channel (the channel this event is associated with)
- One uint16 recording number (version 0.2 and higher)
Spike files (.spikes)
Data from each electrode is saved in a separate file. The filename is based on the name of the electrode itself, but without spaces (e.g., "Tetrode1.spikes").
Each record contains an individual spike event (saved for one or more channels), and is written in the following format, defined in SpikeObject::packSpike():
- uint8 eventType (always equal to 4, for spike events)
- int64 timestamp (to align with timestamps from the continuous records)
- int64 software timestamp (not currently used)
- uint16 sourceID (electrode number)
- uint16 number of channels (N)
- uint16 number of samples per spike (M)
- uint16 sorted id (used by Spike Sorter)
- uint16 electrodeID (unique electrode ID)
- uint16 channel (channel within the electrode that triggered spike acquisition)
- 3 uint8 color codes (for drawing spikes)
- 2 float32 principle component projections (x and y)
- uint16 sampling frequency (Hz)
- N*M uint16 samples (individual channels are contiguous)
- N float32 gains (actually gain*1000, to increase resolution)
- N uint16 thresholds used for spike extraction
- One uint16 recording number (version 0.2 and higher)
Since the samples are saved as unsigned integers, converting them to microvolts involves subtracting
32768, dividing by the gain, and multiplying by 1000.
Reading data into MATLAB
Here's some example code for loading the first record from a data file called `102_CH1.continuous
`:
fid = fopen('102_CH1.continuous');
hdr = fread(fid, 1024, 'char*1');
timestamp = fread(fid, 1, 'int64',0,'l');
N = fread(fid, 1, 'uint16',0,'l');
recordingNumber = fread(fid, 1, 'uint16', 0, 'l');
samples = fread(fid, N, 'int16',0,'b');
recordmarker = fread(fid, 10, 'char*1');
fclose(fid);
figure; plot(samples);
See the analysis-tools repository for additional MATLAB and Python code.