Home > functions > device > eeg > vb_job_eeg.m

vb_job_eeg

PURPOSE ^

make EEG-MAT file from BDF file

SYNOPSIS ^

function result_code = vb_job_eeg(read_bdf_spec, verbose_swt)

DESCRIPTION ^

 make EEG-MAT file from BDF file

 [usage]
   result_code = vb_job_eeg(read_bdf_spec, load_eeg_spec, verbose_swt)

 [input]
   read_bdf_spec   : <required> <<struct>> specification to read BDF file.
                   : If this is empty ([]), pass through reading BDF.
     .bdf_file     : <required> <<file>> BDF file with valid path
     .pos_file     : <required> <<file>> POS-MAT file with valid path
     .device       : <optional> ['BIOSEMI'] device name
     .output_dir   : <optional> output directory for EEG-MAT files ['.']
     .eeg_file     : <optional> ['<date>.eeg.mat'] EEG-MAT file name
     .bin_data_dir : <optional> output directory for binary data files
                   :  ['.\(name of eeg_file)_bin']
                   :  this is relative path from output_dir
  .eeginfo_version : <optional> [] version of EEGinfo - unused yet

   verbose_swt     : <optional> <<boolean>> [false]
                   :   switch to output verbose message
 [output]
   result_code : <integer> be seldome used in practice
               :  1) no problem
 [note]
   See also
     vb_job_meg

 [history]
   2008-02-27 (Sako) initial version
   2008-03-26 (Sako) modified data directories
   2009-07-16 (Sako) added EEGinfo.ChannelInfo
   2009-08-10 (Sako) modified the case that pos_file is not given
   2009-12-25 (Sako) modified the unit of data when importing
   2011-02-08 (Sako) adjusted file extension to modified definitions
   2011-02-17 (Sako) changed defailt value of '.bin_data_dir'
   2011-05-30 (Sako) modified according to the new data format
   2011-08-18 (Sako) added setting a default value to the pretrigger field

 Copyright (C) 2011, ATR All Rights Reserved.
 License : New BSD License(see VBMEG_LICENSE.txt)

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function result_code = vb_job_eeg(read_bdf_spec, verbose_swt)
0002 % make EEG-MAT file from BDF file
0003 %
0004 % [usage]
0005 %   result_code = vb_job_eeg(read_bdf_spec, load_eeg_spec, verbose_swt)
0006 %
0007 % [input]
0008 %   read_bdf_spec   : <required> <<struct>> specification to read BDF file.
0009 %                   : If this is empty ([]), pass through reading BDF.
0010 %     .bdf_file     : <required> <<file>> BDF file with valid path
0011 %     .pos_file     : <required> <<file>> POS-MAT file with valid path
0012 %     .device       : <optional> ['BIOSEMI'] device name
0013 %     .output_dir   : <optional> output directory for EEG-MAT files ['.']
0014 %     .eeg_file     : <optional> ['<date>.eeg.mat'] EEG-MAT file name
0015 %     .bin_data_dir : <optional> output directory for binary data files
0016 %                   :  ['.\(name of eeg_file)_bin']
0017 %                   :  this is relative path from output_dir
0018 %  .eeginfo_version : <optional> [] version of EEGinfo - unused yet
0019 %
0020 %   verbose_swt     : <optional> <<boolean>> [false]
0021 %                   :   switch to output verbose message
0022 % [output]
0023 %   result_code : <integer> be seldome used in practice
0024 %               :  1) no problem
0025 % [note]
0026 %   See also
0027 %     vb_job_meg
0028 %
0029 % [history]
0030 %   2008-02-27 (Sako) initial version
0031 %   2008-03-26 (Sako) modified data directories
0032 %   2009-07-16 (Sako) added EEGinfo.ChannelInfo
0033 %   2009-08-10 (Sako) modified the case that pos_file is not given
0034 %   2009-12-25 (Sako) modified the unit of data when importing
0035 %   2011-02-08 (Sako) adjusted file extension to modified definitions
0036 %   2011-02-17 (Sako) changed defailt value of '.bin_data_dir'
0037 %   2011-05-30 (Sako) modified according to the new data format
0038 %   2011-08-18 (Sako) added setting a default value to the pretrigger field
0039 %
0040 % Copyright (C) 2011, ATR All Rights Reserved.
0041 % License : New BSD License(see VBMEG_LICENSE.txt)
0042 tic;
0043 
0044 % ----- constants
0045 vb_define_device;
0046 func_ = mfilename;
0047 result_code = 1; % no problem
0048 
0049 % --- CHECK ARGUMENT --- %
0050 if ~exist('read_bdf_spec', 'var'), read_bdf_spec = []; end;
0051 if ~exist('verbose_swt', 'var'), verbose_swt = []; end;
0052 [read_bdf_spec, VERBOSE] = inner_check_arguments(read_bdf_spec, verbose_swt);
0053 
0054 % --- MAIN PROCEDURE --------------------------------------------------------- %
0055 %
0056 % set local variables
0057 [bdf_file, pos_file, ...
0058   figure_info, device, output_dir, eeg_file, data_dir, eeginfo_version] = ...
0059     inner_get_var_read_bdf_spec(read_bdf_spec);
0060   
0061 % The eeg_file is defined from output_dir
0062 % As data_dir is defined by the relative path from eeg_file,
0063 % binary files will be created in 'output_dir/data_dir' directory in fact
0064 
0065 % --- PREPARATION --- %
0066 if ~isempty(figure_info)
0067   SensorPosition        = figure_info.SensorPosition;
0068   CoordType             = figure_info.CoordType;
0069   ChannelName_digitizer = figure_info.ChannelLabel;
0070 else
0071   SensorPosition        = [];
0072   CoordType             = '';
0073   ChannelName_digitizer = [];
0074 end
0075 
0076 % ----- read BDF file
0077 [ChannelName_hardware, RecordTime, Nch, SampleRate, data_type, ...
0078   org_physical_unit, DAT] = vb_bdffile_get_info(bdf_file);
0079   
0080 % ----- match channels between digitizer label and hardware label
0081 [eeg_name, eeg_idx, extra_name, extra_idx, coord_idx] = ...
0082     inner_match_channel_label(ChannelName_hardware, ChannelName_digitizer);
0083   
0084 % ----- open files of each channel data
0085 eeg_file_path = vb_get_file_parts(eeg_file);
0086 act_data_dir = [eeg_file_path filesep data_dir];
0087 
0088 all_eeg_ch = [eeg_name;extra_name];
0089 
0090 [fid, data_type_list] = inner_open_files( ...
0091   all_eeg_ch, act_data_dir, data_type, VERBOSE);
0092 
0093 % ----- make binary data files
0094 ch_idx = [eeg_idx;extra_idx];
0095 [new_physical_unit, new_eeg_idx, new_extra_idx] = ...
0096   inner_write_channel_data(fid, all_eeg_ch, ...
0097   DAT, RecordTime, data_type_list, org_physical_unit, ch_idx, VERBOSE);
0098 
0099 % ----- close files
0100 inner_close_files(fid, VERBOSE);
0101 
0102 if VERBOSE
0103   fprintf('\n--- record time: %d [sec], sample rate:%d[Hz]\n', ...
0104     RecordTime, SampleRate);
0105 end
0106 
0107 % ----- make EEGinfo
0108 EEGinfo = [];
0109 
0110 % ------- MRI_ID, Vcenter, Vradius, (device_info)TransInfo
0111 EEGinfo = vb_info_add_posfile_info(EEGinfo, pos_file);
0112 
0113 EEGinfo.Measurement      = 'EEG';
0114 EEGinfo.Device           = device;
0115 
0116 % ------- channel
0117 EEGinfo.ChannelID        = eeg_idx;
0118 EEGinfo.ChannelName      = eeg_name;
0119 EEGinfo.Nchannel         = length(eeg_name);
0120 
0121 % ------- extra channel
0122 n_extra_ch = length(extra_idx);
0123 ExtraChannelInfo.Channel_active = ones(n_extra_ch,1);
0124 ExtraChannelInfo.Channel_name   = extra_name;
0125 ExtraChannelInfo.Channel_type   = ones(n_extra_ch,1);
0126 ExtraChannelInfo.Channel_id     = extra_idx;
0127 
0128 % ---------- physical unit - temporarily
0129 ExtraChannelInfo.PhysicalUnit   = new_physical_unit(new_extra_idx);
0130 
0131 EEGinfo.ExtraChannelInfo = ExtraChannelInfo;
0132 
0133 EEGinfo.SampleFrequency  = SampleRate;
0134 EEGinfo.Nsample          = RecordTime * SampleRate;
0135 EEGinfo.DataType         = data_type_list;
0136 
0137 EEGinfo = vb_eeginfo_set_sensor_position(EEGinfo, SensorPosition(coord_idx,:));
0138 EEGinfo.CoordType        = CoordType;
0139 % EEGinfo.Vcenter          = figure_info.Vcenter;
0140 % EEGinfo.Vradius          = figure_info.Vradius;
0141 
0142 % ----- file information
0143 EEGinfo.File.BaseFile    = bdf_file;
0144 EEGinfo.File.OutputDir   = output_dir;
0145 [path,name,ext] = vb_get_file_parts(eeg_file);
0146 EEGinfo.File.EEGFile     = [name ext];
0147 EEGinfo.File.DataDir     = data_dir;
0148 
0149 % ----- trial
0150 Trial.number  = 1;
0151 Trial.sample  = 1:EEGinfo.Nsample;
0152 Trial.Active  = true;
0153 EEGinfo.Trial = Trial;
0154 
0155 % ----- set initial active channel flag
0156 active_channel = ones(vb_info_get_Nchannel(EEGinfo), 1);
0157 EEGinfo = vb_info_set_active_channel(EEGinfo, active_channel);
0158 % --- EEGinfo.ChannelInfo.Active is set here
0159 
0160 % ----- set initial active trial flag
0161 % active_trial   = ones(vb_info_get_trial_number(EEGinfo), 1);
0162 % EEGinfo = vb_info_set_active_trial(EEGinfo, active_trial);
0163 EEGinfo = vb_info_adjust_trial(EEGinfo);
0164 
0165 % ----- make ChannelInfo
0166 EEGinfo.ChannelInfo.Type = ones(EEGinfo.Nchannel, 1);
0167 EEGinfo.ChannelInfo.Name = EEGinfo.ChannelName;
0168 EEGinfo.ChannelInfo.ID = EEGinfo.ChannelID;
0169 
0170 % ---------- physical unit - temporarily
0171 EEGinfo.ChannelInfo.PhysicalUnit = new_physical_unit(new_eeg_idx);
0172 
0173 % ----- Pretrigger (default value)
0174 EEGinfo = vb_eeginfo_set_pre_trigger(EEGinfo, 0);
0175 
0176 % ----- DEVICE DEPENDENT DATA
0177 EEGinfo = vb_eeginfo_set_reference(EEGinfo, EEGINFO_REFERENCE_COMMON);
0178 EEGinfo = vb_eeginfo_set_rectime(EEGinfo, RecordTime);
0179 EEGinfo = vb_eeginfo_set_header(EEGinfo, DAT.Head);
0180 EEGinfo = vb_eeginfo_set_version(EEGinfo, eeginfo_version);
0181 
0182 % ------- record history
0183 history = ...
0184   sprintf('%s(''%s'', ''%s'', ''%s'')', func_, bdf_file, device, eeg_file);
0185 EEGinfo = vb_eeginfo_add_history(EEGinfo, history);
0186 
0187 % measurement information
0188 fprintf('--- now making EEG-MAT file(%s) ...', eeg_file);
0189 % if VERBOSE, fprintf('--- now making EEG-MAT file(%s) ...', eeg_file); end
0190 
0191 Measurement = 'EEG';
0192 vb_fsave(eeg_file, 'EEGinfo', 'Measurement');
0193 
0194 fprintf(' done!\n');
0195 fprintf('--- (%s) %e [sec]\n', func_, toc);
0196 % if VERBOSE, fprintf(' done!\n'); end
0197 % if VERBOSE, fprintf('--- (%s) %e [sec]\n', func_, toc); end
0198 return;
0199 %
0200 % --- END OF MAIN PROCEDURE -------------------------------------------------- %
0201 
0202 
0203 % --- INNER FUNCTIONS -------------------------------------------------------- %
0204 %
0205 % --- inner_check_arguments()
0206 %
0207 function [read_bdf_spec, verbose_swt]= ...
0208   inner_check_arguments(read_bdf_spec, verbose_swt)
0209 func_ = mfilename;
0210 if isempty(read_bdf_spec)
0211   error('(%s)read_bdf_spec is a required parameter', func_);
0212 end;
0213 
0214 % ----- check fields
0215 if ~isfield(read_bdf_spec, 'bdf_file')
0216   error('(%s)cannot find bdf_file in read_bdf_spec', func_);
0217 end
0218 if ~isfield(read_bdf_spec, 'pos_file')
0219   read_bdf_spec.pos_file = '';
0220 end
0221 
0222 if exist(read_bdf_spec.bdf_file, 'file') ~= 2
0223   error('(%s)cannot find bdf_file: %s', func_, read_bdf_spec.bdf_file);
0224 end
0225 
0226 if exist(read_bdf_spec.pos_file, 'file') ~= 2
0227   fprintf('--- (%s)read_bdf_spec.pos_file is empty\n', func_);
0228 end
0229 
0230 if ~isfield(read_bdf_spec, 'device') ...
0231     || isempty(read_bdf_spec.device)
0232   read_bdf_spec.device = 'BIOSEMI';
0233 end
0234 
0235 if ~isfield(read_bdf_spec, 'output_dir') ...
0236     || isempty(read_bdf_spec.output_dir)
0237   read_bdf_spec.output_dir = '.';
0238 end
0239 
0240 if ~isfield(read_bdf_spec, 'eeg_file') ...
0241     || isempty(read_bdf_spec.eeg_file);
0242   read_bdf_spec.eeg_file = ...
0243     sprintf('%s.eeg.mat', datestr(now,'yyyymmdd_HHMMSS'));
0244 end
0245 
0246 % --- Also resolve directory of imported data
0247 if ~isfield(read_bdf_spec, 'bin_data_dir') ...
0248     || isempty(read_bdf_spec.bin_data_dir)
0249   
0250   real_eeg_file = [read_bdf_spec.output_dir '/' read_bdf_spec.eeg_file];
0251   [out_dir, real_dir] = vb_device_make_data_dir(real_eeg_file);
0252   read_bdf_spec.bin_data_dir = out_dir;
0253 else
0254   real_dir = [read_bdf_spec.output_dir '/' read_bdf_spec.bin_data_dir];
0255 end
0256 
0257 if exist(real_dir, 'dir') ~= 7
0258   vb_mkdir(real_dir);
0259 end
0260 
0261 if ~isfield(read_bdf_spec, 'eeginfo_version')
0262   read_bdf_spec.eeginfo_version = [];
0263 end
0264 
0265 if isempty(verbose_swt)
0266   verbose_swt = false;
0267 end
0268 return;
0269 %
0270 % --- end of inner_check_arguments()
0271 
0272 % --- inner_get_var_read_bdf_spec()
0273 %
0274 function [bdf_file, pos_file, ...
0275   figure_info, device, output_dir, eeg_file, bin_data_dir, eeginfo_version] = ...
0276   inner_get_var_read_bdf_spec(read_bdf_spec)
0277 
0278 % required fields
0279 bdf_file = read_bdf_spec.bdf_file;
0280 pos_file = read_bdf_spec.pos_file;
0281 device = read_bdf_spec.device;
0282 output_dir = read_bdf_spec.output_dir;
0283 eeg_file = [output_dir filesep read_bdf_spec.eeg_file];
0284 bin_data_dir = read_bdf_spec.bin_data_dir;
0285 eeginfo_version = read_bdf_spec.eeginfo_version;
0286 
0287 if ~isempty(pos_file)
0288   figure_info = vb_posfile_get_posinfo(pos_file);
0289 else
0290   figure_info = [];
0291 end
0292 % ---=== figure_info ===--- %
0293 % figure_info.SensorPosition;
0294 % figure_info.CoordType;
0295 % figure_info.ChannelLabel;
0296 % figure_info.Vcenter;
0297 % figure_info.Vradius;
0298 
0299 return;
0300 %
0301 % --- end of inner_get_var_read_bdf_spec()
0302 
0303 
0304 % --- inner_match_channel_label()
0305 %
0306 function [eeg_name, eeg_idx, extra_name, extra_idx, coord_idx] = ...
0307   inner_match_channel_label(ch_hw, ch_dg)
0308 func_ = mfilename;
0309 
0310 vb_define_device;
0311 
0312 % --- if there is not pos-mat file
0313 if isempty(ch_dg)
0314   % --- hard code extra channels
0315   ch_ex = {'Status'};
0316 
0317   % reset label size to [n_channel x 1]
0318   ch_hw = vb_util_arrange_list(ch_hw);
0319   ch_ex = vb_util_arrange_list(ch_ex);
0320 
0321   % --- get index of extra channels
0322   [idx_hw_ex] = vb_util_get_index(ch_hw, ch_ex);
0323 
0324   % ----- get labels of sensor channels and not sensor channels
0325   [ch_sensor, ch_sensor_idx, ch_extra, ch_extra_idx] = ...
0326     vb_util_clean_list(ch_hw, idx_hw_ex);
0327 
0328   % ----- set return values
0329   eeg_name = ch_sensor;
0330   eeg_idx  = ch_sensor_idx;
0331   extra_name = ch_extra;
0332   extra_idx  = ch_extra_idx;
0333   coord_idx  = [];
0334 
0335 else
0336   % reset label size to [n_channel x 1]
0337   ch_hw = vb_util_arrange_list(ch_hw);
0338   ch_dg = vb_util_arrange_list(ch_dg);
0339 
0340   [idx_hw, idx_dg] = vb_util_get_index(ch_hw, ch_dg);
0341 
0342   % ----- get mask list
0343   [ex_ch_hw, ex_ch_hw_idx] = vb_util_clean_list(ch_hw, idx_hw);
0344 
0345   % ----- set return values
0346   eeg_name = ch_hw(idx_hw);
0347   eeg_idx  = idx_hw;
0348   extra_name = ex_ch_hw;
0349   extra_idx  = ex_ch_hw_idx;
0350   coord_idx  = idx_dg;
0351 end
0352 return;
0353 %
0354 % --- end of inner_match_channel_label()
0355 
0356 
0357 % --- inner_open_files()
0358 %
0359 function [fid, data_type_list] = ...
0360   inner_open_files(channel_label, data_dir, data_type, VERBOSE)
0361 func_ = mfilename;
0362 vb_define_device;
0363 
0364 % ----- make directory if necessary
0365 if ~exist(data_dir, 'dir')
0366   if ~vb_mkdir(data_dir)
0367     error('(%s)cannot make directory: %s', func_, data_dir);
0368   end
0369 end
0370 
0371 Nch = size(channel_label,1);
0372 
0373 DataFile = cell(Nch,1);
0374 fid = zeros(Nch,1);
0375 data_type_list = cell(Nch,1);
0376 
0377 % support 'Status' channel
0378 common_data_type = data_type;
0379 status_data_type = STATUS_CH_DATA_TYPE;
0380 status_channel_label = STATUS_CH_LABEL;
0381 
0382 for ch = 1:Nch
0383   ch_name = channel_label{ch};
0384   
0385   DataFile{ch} = sprintf('%s%s%s.%s', ...
0386     data_dir, filesep, ch_name, FILE_EXT_BIN_CH_EEG);
0387   fid(ch) = fopen(DataFile{ch},'w');
0388   
0389   if fid(ch) < 0
0390     error('(%s)cannot open : %s', func_, DataFile{ch});
0391   end
0392 
0393   % data type
0394   if strcmp(ch_name, status_channel_label) == 1
0395     data_type_list{ch} = status_data_type;
0396   else
0397     data_type_list{ch} = common_data_type;
0398   end
0399   
0400   if VERBOSE, fprintf(' >>> open %s\n', DataFile{ch}); end
0401 end
0402 return;
0403 %
0404 % --- end of inner_open_files()
0405 
0406 % --- inner_write_channel_data()
0407 %
0408 function [new_physical_unit, new_eeg_idx, new_extra_idx] = ...
0409   inner_write_channel_data(fid, ch_list, ...
0410   EDF_struct, RecordTime, data_type, org_physical_unit, ch_idx, VERBOSE)
0411 
0412 do_mv2v = true;
0413 vb_define_device;
0414 
0415 if VERBOSE
0416   PLOT_EVERY = 30;
0417   fprintf('--- now reading and storing BDF data (plot every %d/%d [sec])', ...
0418     PLOT_EVERY, RecordTime);
0419 end
0420 
0421 Nch = length(fid);
0422 ReadMode   = 0;
0423 
0424 % --- these lists are expected to be the same order with ch_list
0425 calib      = EDF_struct.Head.Cal(ch_idx);
0426 org_offset = EDF_struct.Head.Off(ch_idx);
0427 physical_unit = org_physical_unit(ch_idx);
0428 new_physical_unit = cell(size(org_physical_unit));
0429 new_eeg_idx = [];
0430 new_extra_idx = [];
0431 
0432 UNIT_MICRO_VOLT = 'uV';
0433 UNIT_VOLT = 'V';
0434 CF_MV2V = 10.^(-6);
0435 
0436 n_ch = size(org_offset, 1);
0437 offset = zeros(n_ch,1);
0438 
0439 if do_mv2v
0440   % --- make new physical unit list and offset list
0441   for i_ch = 1:n_ch
0442     % --- physical_unit is the original list of physical unit
0443     if strcmp(physical_unit{i_ch}, UNIT_MICRO_VOLT)
0444       offset(i_ch) = org_offset(i_ch) * CF_MV2V;
0445       new_physical_unit{i_ch} = UNIT_VOLT;
0446     else
0447       offset(i_ch) = org_offset(i_ch);
0448       new_physical_unit{i_ch} = physical_unit{i_ch};
0449     end
0450 
0451     if strcmp(ch_list{i_ch}, STATUS_CH_LABEL)
0452       new_extra_idx = [new_extra_idx, i_ch];
0453     else
0454       new_eeg_idx = [new_eeg_idx, i_ch];
0455     end
0456   end
0457 else
0458   offset = org_offset;
0459 end
0460 
0461 % --- arrange lists to [N_channel x ]
0462 new_physical_unit = new_physical_unit';
0463 new_extra_idx = new_extra_idx';
0464 new_eeg_idx = new_eeg_idx';
0465 
0466 for r = 1:RecordTime
0467   [DAT,DataBuf] = vb_readbdf(EDF_struct, r, ReadMode);
0468   
0469   for i_ch = 1:Nch
0470     cur_raw = DataBuf(:,i_ch);
0471 
0472     if strcmp(ch_list{i_ch}, STATUS_CH_LABEL)
0473       this_eeg = cur_raw;
0474     else
0475       if do_mv2v
0476         if strcmp(physical_unit(i_ch), UNIT_MICRO_VOLT)
0477           this_eeg = (cur_raw * CF_MV2V) * calib(i_ch) + offset(i_ch);
0478         else
0479           this_eeg = cur_raw * calib(i_ch) + offset(i_ch);
0480         end
0481       else
0482         this_eeg = cur_raw * calib(i_ch) + offset(i_ch);
0483       end
0484     end
0485     fwrite(fid(i_ch), this_eeg, data_type{i_ch}); 
0486   end
0487   if VERBOSE && rem(r,PLOT_EVERY) == 0, fprintf('.'); end
0488 end
0489 if VERBOSE, fprintf('\n'); end
0490 return;
0491 %
0492 % --- end of inner_write_channel_data()
0493 
0494 % --- inner_close_files()
0495 %
0496 function inner_close_files(fid, VERBOSE)
0497 Nch = length(fid);
0498 for ch=1:Nch
0499   fclose(fid(ch));
0500 end
0501 if VERBOSE, fprintf('--- closing files done ...\n'); end
0502 return;
0503 %
0504 % --- end of inner_close_files()
0505 %
0506 % --- END OF INNER FUNCTIONS ------------------------------------------------- %
0507 
0508 %%% END OF FILE %%%

Generated on Tue 27-Aug-2013 11:46:04 by m2html © 2005