NWB format (old)

Note: This version of the documentation is valid for version 0.4.2.1 or earlier only. For newer versions please refer to NWB Format

From the NWB website:

Neurodata Without Borders: Neurophysiology (NWB:N) is a project to develop a unified data format for cellular-based neurophysiology data, focused on the dynamics of groups of neurons measured under a large range of experimental conditions. The NWB:N team consists of neuroscientists and software developers who recognize that adoption of a unified data format is an important step toward breaking down the barriers to data sharing in neuroscience.

NWB:N is funded by GE, the Allen Institute for Brain Science, the Howard Hughes Medical Institute (HHMI), The Kavli Foundation and the International Neuroinformatics Coordinating Facility. Our founding scientific partners are the Allen Institute, the Svoboda Lab at the Janelia Research Campus of HHMI, the Meister Lab at the California Institute of Technology, the Buzsáki Lab at New York University School of Medicine and the University of California, Berkeley.

We are working on implementing the ability to write directly to an NWB file from the Open Ephys GUI. We're hoping that NWB becomes a common standard for neuroscience, so saving your data in NWB format will make it much easier to share with other researchers. It also comes with all the advantages (and disadvantages) of HDF5.

The official format specification can be found on GitHub as raw HTML files. We've adapted it for use with Open Ephys in the following way:

Open Ephys NWB File Structure (based on version 1.0.4_beta)

(NOTE: The current version of the NWB record format on the development branch of Open Ephys is untested and unfinished so it might have bugs or fields not completely complying with the specification. A current known issue is that the messages and event timestamps are not saved in seconds but in sample numbers. The value in seconds can be manually obtained by dividing the sample number by the relevant source sample rate)


Top-level groups (always created):

/acquisition
/analysis
/epochs
/general
/processing
/stimulus

Top-level datasets (always created):

/file_create_date: date + time in ISO format (text array)
/identifier: from text fields in recording options (text)
/nwb_version: 'NWB-1.0.4_beta' (text)
/session_description: <blank string> (text)
/session_start_time: date + time in ISO format (text)



/acquisition group:

All of the data generated during recording should be stored in this group.


For writing continuous data, we use the NWB ElectricalSeries:

/acquisition/timeseries/continuous/processor<*>/recording<**>
    ./ancestry: ['TimeSeries', 'ElectricalSeries'] (text array attr)
    ./comments: <empty> (text attr)
    ./description: <empty> (text attr)
    ./neurodata_type: 'TimeSeries' (text attr)
    ./source: processor name + number (text attr)
    ./help: 'Stores acquired voltage data from extracellular recordings' (text attr)
    ./data: M samples x N channels (int16 array)
        ./conversion: bitVolts (float32 attr)
        ./resolution: 1/2^16 * bitVolts (float32 attr)
        ./unit: 'volt' (text attr)
    ./num_samples: M (int32, stored at end of recording)
    ./timestamps: M timestamps relative to experiment start time (float64 array)
        ./interval: 1 (int32 attr)
        ./unit: 'seconds' (text attr)
 

For writing spike data, we use the NWB SpikeEventSeries:

/acquisition/timeseries/spikes/electrode<***>/recording<**>
    ./ancestry: ['TimeSeries', 'SpikeEventSeries'] (text array attr)
    ./comments: <empty> (text attr)
    ./description: electrode name (text attr)
    ./neurodata_type: 'TimeSeries' (text attr)
    ./source: processor name + number (text attr)
    ./help: 'Snapshorts of spike events from data' (attr, text)
    ./data: X spikes x Y channels x Z samples (int16 array)
        ./conversion: bitVolts (float32 attr)
        ./resolution: 1/2^16 * bitVolts (float32 attr)
        ./unit: 'volt' (text attr)
    ./timestamps: X timestamps relative to experiment start time (float64 array)
        ./interval: 1 (int32 attr)
        ./unit: 'seconds' (text attr)
 

For writing messages, we use the NWB AnnotationSeries:

/acquisition/timeseries/messages/recording<**>
    ./ancestry: ['TimeSeries', 'AnnotationSeries'] (text array attr)
    ./comments: <empty> (text attr)
    ./description: <empty> (text attr)
    ./neurodata_type: 'TimeSeries' (text attr)
    ./source: 'Message center' (text attr)
    ./help: 'Time-stamped annotations about an experiment' (attr, text)
    ./data: N messages as text array
        ./conversion: 'NaN' (float32 attr)
        ./resolution: 'NaN' (float32 attr)
        ./unit: 'n/a' (text attr)
    ./num_samples: N (int32, stored at end of recording)
    ./timestamps: N timestamps relative to experiment start time (float64 array)
        ./interval: 1 (int32 attr)
        ./unit: 'seconds' (text attr)
 

For writing events, we use the NWB IntervalSeries:

/acquisition/timeseries/events/recording<**>
    ./ancestry: ['TimeSeries', 'IntervalSeries'] (text array attr)
    ./comments: <empty> (text attr)
    ./description: <empty> (text attr)
    ./neurodata_type: 'TimeSeries' (text attr)
    ./source: 'All processors' (text attr)
    ./help: 'Stores the start and stop times for events' (attr, text)
    ./data: N events [+(channel#) for event 'on', -(channel#) for event 'off'] (int8 array)
        ./conversion: 'NaN' (float32 attr)
        ./resolution: 'NaN' (float32 attr)
        ./unit: 'n/a' (text attr)
    ./control: N processor IDs for each event (uint8 array)
    ./num_samples: N (int32, stored at end of recording)
    ./timestamps: N timestamps relative to experiment start time (float64 array)
        ./interval: 1 (int32 attr)
        ./unit: 'seconds' (text attr)


* = processorID_subprocessorID (e.g., 101_1, 102_1, etc.)

** = index of recording (1, 2, 3, etc.)

*** = index of electrode (1, 2, 3, etc.)


Rules for creating new files, versus creating new groups:

  • If acquisition is stopped, create a new file (experiment1.nwb, experiment2.nwb, etc.). Timestamps are reset to zero.
  • If recording is stopped (but acquisition is active), create a new group (recording1, recording2, etc.). Timestamps are relative to start of acquisition.





/general group:

All of the experimental metadata should be stored in this group. Eventually, we should have a pop-up window inside the GUI that allows the user to input various parameters (e.g., subject name, experimenter name) that will be automatically written here.


/general/data_collection/software: 'Open Ephys GUI vX.X.X' (text attr)
/general/data_collection/configuration: XML string of config file (text attr)