pybv.write_brainvision(*, data, sfreq, ch_names, ref_ch_names=None, fname_base, folder_out, overwrite=False, events=None, resolution=0.1, unit='µV', fmt='binary_float32', meas_date=None)[source]

Write raw data to the BrainVision format [1].

datanp.ndarray, shape (n_channels, n_times)

The raw data to export. Voltage data is assumed to be in volts and will be scaled as specified by unit. Non-voltage channels (as specified by unit) are never scaled (e.g., “°C”).

sfreqint | float

The sampling frequency of the data in Hz.

ch_nameslist of {str | int}, len (n_channels)

The names of the channels. Integer channel names are converted to string.

ref_ch_namesstr | list of str, len (n_channels) | None

The name of the channel used as a reference during the recording. If references differed between channels, you may supply a list of reference channel names corresponding to each channel in ch_names. If None (default), assume that all channels are referenced to a common channel that is not further specified (BrainVision default).


The reference channel name specified here does not need to appear in ch_names. It is permissible to specify a reference channel that is not present in data.


The base name for the output files. Three files will be created (.vhdr, .vmrk, .eeg) and all will share this base name.


The folder where output files will be saved. Will be created if it does not exist yet.


Whether or not to overwrite existing files. Defaults to False.

eventsnp.ndarray, shape (n_events, {2, 3}) | list of dict, len (n_events) | None

Events to write in the marker file (.vmrk). Defaults to None (not writing any events).

If an array is passed, it must have either two or three columns and consist of nonnegative integers. The first column is always the zero-based onset index of each event (corresponding to the time dimension of the data array). The second column is a number associated with the description of the event. The (optional) third column specifies the duration of each event in samples (defaults to 1). All events are written as type “Stimulus” and interpreted as relevant to all channels. For more fine-grained control over how to write events, pass a list of dict as described next.

If list of dict is passed, each dict in the list corresponds to an event and may have the following entries:

  • "onset"int

    The zero-based index of the event onset, corresponding to the time dimension of the data array.

  • "duration"int

    The duration of the event in samples (defaults to 1).

  • "description"str | int

    The description of the event. Must be a positive int when type (see below) is either "Stimulus" or "Response", and may be a str when type is "Comment".

  • "type"str

    The type of the event, must be one of {"Stimulus", "Response", "Comment"} (defaults to "Stimulus"). Additional types like the known BrainVision types "New Segment", "SyncStatus", etc. are currently not supported.

  • "channels"str | list of {str | int}

    The channels that are impacted by the event. Can be "all" (reflecting all channels), or a channel name, or a list of channel names. An empty list means the same as "all". Integer channel names are converted to strings, as in the ch_names parameter. Defaults to "all".

Note that onset and description MUST be specified in each dict.


When specifying more than one but less than “all” channels that are impacted by an event, pybv will write the same event for as many times as channels are specified (see #77 for a discussion). This is valid according to the BrainVision specification, however for maximum compatibility with other BrainVision readers, we do not (yet) recommend using this feature.

resolutionfloat | np.ndarray, shape (n_channels,)

The resolution in unit in which you’d like the data to be stored. If float, the same resolution is applied to all channels. If array with n_channels elements, each channel is scaled with its own corresponding resolution from the array. Note that resolution is applied on top of the default resolution that a data format (see fmt) has. For example, the "binary_int16" format by design has no floating point support, but when scaling the data in µV for 0.1 resolution (default), accurate writing for all values >= 0.1 µV is guaranteed. In contrast, the "binary_float32" format by design already supports floating points up to 1e-6 resolution, and writing data in µV with 0.1 resolution will thus guarantee accurate writing for all values >= 1e-7 µV (1e-6 * 0.1).

unitstr | list of str

The unit of the exported data. This can be one of "V", "mV", "µV" (or equivalently "uV") , or "nV", which will scale the data accordingly. Defaults to "µV". Can also be a list of units with one unit per channel. Non-voltage channels are stored “as is”, for example temperature might be available in "°C", which pybv will not scale.


Binary format the data should be written as. Valid choices are "binary_float32" (default) and "binary_int16".

meas_datedatetime.datetime | str | None

The measurement date specified as a datetime.datetime object. Alternatively, can be a str in the format “YYYYMMDDhhmmssuuuuuu” (“u” stands for microseconds). Note that setting a measurement date implies that one additional event is created in the .vmrk file. To prevent this, set this parameter to None (default).


iEEG/EEG/MEG data is assumed to be in V, and pybv will scale these data to µV by default. Any unit besides µV is officially unsupported in the BrainVision specification. However, if one specifies other voltage units such as mV or nV, we will still scale the signals accordingly in the exported file. We will also write channels with non-voltage units such as °C as is (without scaling). For maximum compatibility, all signals should be written as µV.

When passing a list of dict to events, the event type that can be passed is currently limited to one of {"Stimulus", "Response", "Comment"}. The BrainVision specification itself does not limit event types, and future extensions of pybv may permit additional or even arbitrary event types.




>>> data = np.random.random((3, 5))
>>> # write data with varying units
... # Note channels A1 and A2 are expected to be in volt and will get
... # rescaled to µV and mV respectively.
... # TEMP is expected to be in some other unit (i.e., NOT volt), and
... # will not get scaled (it is written "as is")
... write_brainvision(data=data, sfreq=1, ch_names=["A1", "A2", "TEMP"],
...                   folder_out="./",
...                   fname_base="pybv_test_file",
...                   unit=["µV", "mV", "°C"])
>>> # remove the files
>>> for ext in [".vhdr", ".vmrk", ".eeg"]:
...     os.remove("pybv_test_file" + ext)