Search code examples
matlabsaveeeglabeuropean-data-format

Saving a transformed .bdf file


I used MATLAB R2011b and EEGLab 13.4.3b to load a Biosemi .bdf file (EEG recording) that includes several spurious triggers. The position of triggers is stored in header.BDF.Trigger.POS and the trigger type is in header.BDF.Trigger.TYP.

After loading the file with:

header = sopen('05-AM-200-Deci.bdf','r',[1:40],'OVERFLOWDETECTION:OFF'); 

I made transformations to header.BDF.Trigger.POS and header.BDF.Trigger.TYP vectors and replaced them.

NOTE: These transformations shouldn't make a difference because even when I only load the bdf file and then try to save it back I get exactly the same errors.

Here's the structure of header (extracted with get()):

header = 

    FileName: '05-AM-200-Deci.bdf'
        FILE: [1x1 struct]
        TYPE: 'BDF'
      ErrNum: [1025 0]
      ErrMsg: ''
     keycode: [1x34 double]
          NS: 41
  SampleRate: 1
          T0: [2015 7 6 17 41 44]
      Filter: [1x1 struct]
        FLAG: [1x1 struct]
       EVENT: [1x1 struct]
     VERSION: -1
     Patient: [1x1 struct]
         PID: '05-AM-200'
         RID: '05-AM-200'
     HeadLen: 10752
   reserved1: '24BIT                                       '
        NRec: 1207
         Dur: 1
          AS: [1x1 struct]
       Label: {41x1 cell}
  Transducer: {41x1 cell}
     PhysDim: {41x1 cell}
     PhysMin: [1x41 double]
     PhysMax: [1x41 double]
      DigMin: [1x41 double]
      DigMax: [1x41 double]
     PreFilt: [41x80 char]
      GDFTYP: [1x41 double]
         SPR: 1
   THRESHOLD: [41x2 double]
         Cal: [1x41 double]
         Off: [1x41 double]
       Calib: [41x40 double]
         BDF: [1x1 struct]
 PhysDimCode: [41x1 double]
        ELEC: [1x1 struct]
  LeadIdCode: [41x1 double]
     CHANTYP: '                                         '
InChanSelect: [40x1 double]

I tried using EEGLab functions to save the transformed file (header) to no avail. I know how to save a bdf file in EEGLab using GUI. However, using GUI doesn't allow for a transformation that I need.

In order to save the file I tried using pop_writeeeg() and swrite() but none of them worked.

I used the following commands:

  1. First take:

    `pop_writeeeg(header);`
    

    Returns:

    Reference to non-existent field 'trials'.  
    Error in pop_writeeeg (line 38)
        if EEG.trials > 1
    
  2. Then I tried:

    `pop_writeeeg(header, '05-new', 'TYPE', 'BDF');`
    

    Which returned:

    Reference to non-existent field 'chanlocs'.
    Error in pop_writeeeg (line 66)
    if ~isempty(EEG.chanlocs)
    
  3. My next take was to use swrite() the following way:

    `swrite(header, '05-new');`
    

    Which returned:

    Error SWRITE can not be applied, File 05-AM-200-Deci.bdf is not opened in WRITE mode
    

I'm pretty sure I'm missing something simple here.

Does anyone know how to save transformed EEG (bdf) data back to a bdf file?


Solution

  • The EEGLAB toolbox does not include the functions you need; you want the Biosig toolbox (it is a plugin for EEGLAB). The paradigm of the Biosig functions is unusual. It uses a data structure with the file handle in the structure. So, to open a file and then save your modified data, you need to do the following steps:

    1) Open the BDF file and read in the data. This step retrieves file metadata and creates a structure of the metadata (as shown in the question).

    [raw_data,meta_data] = sload('05-AM-200-Deci.bdf',[1:40],'OVERFLOWDETECTION:OFF');
    

    2) Even if the transformations only involve metadata, you have to re-write the file with the raw data & metadata. Your data must be in a variable with the size Rows x Number_of_Channels. Depending on the features of the .bdf file, you may have to add an additional column which represents the Status channel.

    % do the transforms here. If it does not affect the raw data, no need to change variables.
    transformed_data = raw_data; % transformed data to be saved to a file
    meta_data.fZ = zeros([1 meta_data.NS]);
    transformed_data(:,meta_data.NS)=0;
    

    3) Open the file for writing WARNING: THIS WILL ERASE THE FILE ON DISK

    meta_data = sopen(meta_data,'w');
    

    4) Save your data to the file:

    swrite(meta_data,transformed_data);
    

    5) Close the file:

    sclose(meta_data);
    

    I tested this using the test files available here. The BDF format is old and has many options, so there is an extra step in this script to fill in the "Status" channel (channel 17), in order to make it work with the Biosig functions.

    [s,hdr] = sload('Newtest17-2048.bdf');     % get the raw data from the file
    hdr.fZ = zeros([1 hdr.NS]); s(:,hdr.NS)=0; % (create "missing" channel values)
    hdr = sopen(hdr,'w');                      % open the file for writing (ERASES FILE!)
    swrite(hdr,s);                             % write data to the file
    sclose(hdr);                               % close the file
    

    The hack for the "missing channel" is also required for the .bdf file linked in the question.