Home > vbmeg > functions > common > loadfunc > subdirectory > vb_load_sensor.m

vb_load_sensor

PURPOSE ^

Load sensor position, sensor direction, weight of MEG (meg.mat) and EEG (eeg.mat).

SYNOPSIS ^

function [pick, Qpick, CoilWeight, Vcenter, result, channel_info] =vb_load_sensor(megfile, ch_type, ch_name, active_swt, method)

DESCRIPTION ^

 Load sensor position, sensor direction, weight of MEG (meg.mat) and EEG (eeg.mat).

 This function supports three formats of megfile; Standard MEG format, Minimum MEG format and fileinfo format.
 By default, this function load only active sensors kept in MEGinfo.ActiveChannel
 in case of Standard MEG format or fileinfo.channel_id in case of fileinfo format.  

 [usage]
 1. Load active sensors(Default) 
   [pick, Qpick, CoilWeight, Vcenter, result, channel_info] = ...
            vb_load_sensor(megfile);
 2. Load all sensors including inactive sensors.
   active_swt = false;
   [pick, Qpick, CoilWeight, Vcenter, result, channel_info] = ...
            vb_load_sensor(megfile, [], [], active_swt);

 [input]
      megfile : <required> <<file>> MEG-MAT file or EEG-MAT file
      ch_type : <optional> <<string>> channel type ['']
              :  '' or 'MEG' : MEG channels of MEG
              :        'REF' : REFFERENCE channels of MEG
              :        'ALL' : MEG + REFFERENCE channels of MEG
              :        'MAG' : magnetometer channels
              :        'AXIAL'  : axial channels
              :        'PLANAR' : planar channels
              :  'MAG_X'     : Magnetometer OPM channel data toward X-axis (only QZFM device)
              :  'MAG_Y'     : Magnetometer OPM channel data toward Y-axis (only QZFM device)
              :  'MAG_Z'     : Magnetometer OPM channel data toward Z-axis (only QZFM device)
              :  case-insensitive
      ch_name : <optional> <<cell array>> channel name list [{''}(empty)]
              :  If ch_type is specified, this is ignored.
   active_swt : <optional> <<boolean>> switch to filter channel
              :   if .ActiveChannel is valid [true]
              :   if .ActiveChannel is invalid [false]
              :    true) return only active channels
              :   false) return all the channels
       method : <optional> method of calculation
              :  ['AVE'] : average
              :   'TOP'  : use top data
              :  this is valid for 'INIT' mode
 [output]
         pick : n-th coil position  (Right-hand SPM coordinate) [m]
              :  [Ncoil x 3]
        Qpick : n-th coil direction (Right-hand SPM coordinate)
              :  [Ncoil x 3]
   CoilWeight : n-th coil weight for m-th channel [Nchannel x Ncoil]
              : basis(channel,dipole) = CoilWeight * basis(coil,dipole)
      Vcenter : Center of spherical head model [m] [1 x 3]
       result : <<integer>> error infomation
              :  In the case that meg_file is '.info.mat' file and method is
              :  'AVE', this will become error struct.
              :  fields are as follows:
              :  These are errors between base data of each file and average.
              :   .error_pick [n_ch x 3 x n_file]
              :   .error_Qpick [n_ch x 3 x n_file] (if they are)
 channel_info : <<struct>> channel information of loaded data.
              :  .Active [Nchannel x 1]
              :  .Name   [Nchannel x 1]
              :  .Type   [Nchannel x 1]
              :  .ID     [Nchannel x 1]
              : return empty when the loaded data contains reference sensor.
                ('REF', 'ALL')
 [note]
   if megfile is SBI data file or EEG-MAT file, REFFERENCE channel is empty

 [Active channel/Active trial information]
   * Place
    load(megfile, 'MEGinfo'); % EEG case, MEGinfo -> EEGinfo
    MEGInfo.ActiveChannel : Active channel list (boolean array) [Nchannelx 1]
           .ActiveTrial   : Active trial list   (boolean array) [Nrepeat x 1]
   * Inactivate channel/trial
     load_spec.ActiveChannel = false;
     load_spec.ActiveTrial   = false;
     [data] = vb_load_meg_data(meg_file, load_spec); % [Nchannel x Nsample x Ntrial]
     MEGinfo.ActiveChannel = ones(size(data, 1), 1); % All channel active
     MEGinfo.ActiveTrial   = ones(size(data, 3), 1); % All trial   active

     % Inactivate channel/trial
     MEGinfo.ActiveChannel(N) = 0; % Inactive data(N, :, :)
     MEGinfo.ActiveTrial(M)   = 0; % Inactive data(:, :, M)
     then save it. vb_save(megfile, 'MEGinfo');

 [see also]
   vb_megfile_get_sensor_position_by_name
   vb_megfile_get_sensor_position_by_type

 [history]
   2006-11-01 (Sako) modified to be able to accept EEGinfo
   2007-07-24 (Sako) added channel mode
   2008-04-16 (Sako) added active_swt, result
   2008-06-04 (Sako) changed default value of active_swt
   2009-08-21 (????) supported 'INFO' as "Measurement" but 'mode' is ignored
   2010-08-24 (Sako) added method argument
   2011-06-02 (Sako) converted return values of vb_load_device to upper case
   2011-07-26 (Sako) changed mode to ch_type, added ch_name as arguments
   2017-03-06 (rhayashi) supported ch_type, ch_name for fileinfo format.
   2017-04-15 (rhayashi) bugfix:ActiveChannel field work correctly.
   2018-08-22 (Takeda) removed warning message about Vcenter and
                       supported NEUROMAG
   2022-06-03 (k_suzuki) supported QZFM
   2022-06-24 (k_suzuki) fixed bug when load Info file of QZFM device

 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 [pick, Qpick, CoilWeight, Vcenter, result, channel_info] = ...
0002   vb_load_sensor(megfile, ch_type, ch_name, active_swt, method)
0003 % Load sensor position, sensor direction, weight of MEG (meg.mat) and EEG (eeg.mat).
0004 %
0005 % This function supports three formats of megfile; Standard MEG format, Minimum MEG format and fileinfo format.
0006 % By default, this function load only active sensors kept in MEGinfo.ActiveChannel
0007 % in case of Standard MEG format or fileinfo.channel_id in case of fileinfo format.
0008 %
0009 % [usage]
0010 % 1. Load active sensors(Default)
0011 %   [pick, Qpick, CoilWeight, Vcenter, result, channel_info] = ...
0012 %            vb_load_sensor(megfile);
0013 % 2. Load all sensors including inactive sensors.
0014 %   active_swt = false;
0015 %   [pick, Qpick, CoilWeight, Vcenter, result, channel_info] = ...
0016 %            vb_load_sensor(megfile, [], [], active_swt);
0017 %
0018 % [input]
0019 %      megfile : <required> <<file>> MEG-MAT file or EEG-MAT file
0020 %      ch_type : <optional> <<string>> channel type ['']
0021 %              :  '' or 'MEG' : MEG channels of MEG
0022 %              :        'REF' : REFFERENCE channels of MEG
0023 %              :        'ALL' : MEG + REFFERENCE channels of MEG
0024 %              :        'MAG' : magnetometer channels
0025 %              :        'AXIAL'  : axial channels
0026 %              :        'PLANAR' : planar channels
0027 %              :  'MAG_X'     : Magnetometer OPM channel data toward X-axis (only QZFM device)
0028 %              :  'MAG_Y'     : Magnetometer OPM channel data toward Y-axis (only QZFM device)
0029 %              :  'MAG_Z'     : Magnetometer OPM channel data toward Z-axis (only QZFM device)
0030 %              :  case-insensitive
0031 %      ch_name : <optional> <<cell array>> channel name list [{''}(empty)]
0032 %              :  If ch_type is specified, this is ignored.
0033 %   active_swt : <optional> <<boolean>> switch to filter channel
0034 %              :   if .ActiveChannel is valid [true]
0035 %              :   if .ActiveChannel is invalid [false]
0036 %              :    true) return only active channels
0037 %              :   false) return all the channels
0038 %       method : <optional> method of calculation
0039 %              :  ['AVE'] : average
0040 %              :   'TOP'  : use top data
0041 %              :  this is valid for 'INIT' mode
0042 % [output]
0043 %         pick : n-th coil position  (Right-hand SPM coordinate) [m]
0044 %              :  [Ncoil x 3]
0045 %        Qpick : n-th coil direction (Right-hand SPM coordinate)
0046 %              :  [Ncoil x 3]
0047 %   CoilWeight : n-th coil weight for m-th channel [Nchannel x Ncoil]
0048 %              : basis(channel,dipole) = CoilWeight * basis(coil,dipole)
0049 %      Vcenter : Center of spherical head model [m] [1 x 3]
0050 %       result : <<integer>> error infomation
0051 %              :  In the case that meg_file is '.info.mat' file and method is
0052 %              :  'AVE', this will become error struct.
0053 %              :  fields are as follows:
0054 %              :  These are errors between base data of each file and average.
0055 %              :   .error_pick [n_ch x 3 x n_file]
0056 %              :   .error_Qpick [n_ch x 3 x n_file] (if they are)
0057 % channel_info : <<struct>> channel information of loaded data.
0058 %              :  .Active [Nchannel x 1]
0059 %              :  .Name   [Nchannel x 1]
0060 %              :  .Type   [Nchannel x 1]
0061 %              :  .ID     [Nchannel x 1]
0062 %              : return empty when the loaded data contains reference sensor.
0063 %                ('REF', 'ALL')
0064 % [note]
0065 %   if megfile is SBI data file or EEG-MAT file, REFFERENCE channel is empty
0066 %
0067 % [Active channel/Active trial information]
0068 %   * Place
0069 %    load(megfile, 'MEGinfo'); % EEG case, MEGinfo -> EEGinfo
0070 %    MEGInfo.ActiveChannel : Active channel list (boolean array) [Nchannelx 1]
0071 %           .ActiveTrial   : Active trial list   (boolean array) [Nrepeat x 1]
0072 %   * Inactivate channel/trial
0073 %     load_spec.ActiveChannel = false;
0074 %     load_spec.ActiveTrial   = false;
0075 %     [data] = vb_load_meg_data(meg_file, load_spec); % [Nchannel x Nsample x Ntrial]
0076 %     MEGinfo.ActiveChannel = ones(size(data, 1), 1); % All channel active
0077 %     MEGinfo.ActiveTrial   = ones(size(data, 3), 1); % All trial   active
0078 %
0079 %     % Inactivate channel/trial
0080 %     MEGinfo.ActiveChannel(N) = 0; % Inactive data(N, :, :)
0081 %     MEGinfo.ActiveTrial(M)   = 0; % Inactive data(:, :, M)
0082 %     then save it. vb_save(megfile, 'MEGinfo');
0083 %
0084 % [see also]
0085 %   vb_megfile_get_sensor_position_by_name
0086 %   vb_megfile_get_sensor_position_by_type
0087 %
0088 % [history]
0089 %   2006-11-01 (Sako) modified to be able to accept EEGinfo
0090 %   2007-07-24 (Sako) added channel mode
0091 %   2008-04-16 (Sako) added active_swt, result
0092 %   2008-06-04 (Sako) changed default value of active_swt
0093 %   2009-08-21 (????) supported 'INFO' as "Measurement" but 'mode' is ignored
0094 %   2010-08-24 (Sako) added method argument
0095 %   2011-06-02 (Sako) converted return values of vb_load_device to upper case
0096 %   2011-07-26 (Sako) changed mode to ch_type, added ch_name as arguments
0097 %   2017-03-06 (rhayashi) supported ch_type, ch_name for fileinfo format.
0098 %   2017-04-15 (rhayashi) bugfix:ActiveChannel field work correctly.
0099 %   2018-08-22 (Takeda) removed warning message about Vcenter and
0100 %                       supported NEUROMAG
0101 %   2022-06-03 (k_suzuki) supported QZFM
0102 %   2022-06-24 (k_suzuki) fixed bug when load Info file of QZFM device
0103 %
0104 % Copyright (C) 2011, ATR All Rights Reserved.
0105 % License : New BSD License(see VBMEG_LICENSE.txt)
0106 
0107 % --- CHECK ARGUMENTS --- %
0108 if ~exist('megfile', 'var'), megfile = []; end
0109 if ~exist('ch_type', 'var'), ch_type = []; end
0110 if ~exist('ch_name', 'var'), ch_name = []; end
0111 if ~exist('active_swt', 'var'), active_swt = []; end
0112 if ~exist('method', 'var'), method = ''; end
0113 [megfile, ch_type, ch_name, active_swt, method, result] = ...
0114   inner_check_arguments(megfile, ch_type, ch_name, active_swt, method);
0115 
0116 % --- MAIN PROCEDURE --------------------------------------------------------- %
0117 %
0118 pick = [];
0119 Qpick = [];
0120 CoilWeight = [];
0121 Vcenter = [];
0122 channel_info = [];
0123 
0124 if result ~= 0
0125   return;
0126 end
0127 
0128 func_ = mfilename;
0129 
0130 measurement = vb_load_device(megfile);
0131 Measurement = upper(measurement);
0132 
0133 % return variables
0134 % check measurement parameter
0135 switch  Measurement
0136   case  'MEG'
0137     if ~isempty(ch_type)
0138       [pick, Qpick, CoilWeight, Vcenter, result, channel_info] = ...
0139         vb_megfile_get_sensor_position_by_type(megfile, ch_type, active_swt);
0140 
0141     elseif ~isempty(ch_name)
0142       [pick, Qpick, CoilWeight, Vcenter, result, channel_info] = ...
0143         vb_megfile_get_sensor_position_by_name(megfile, ch_name, active_swt);
0144       
0145     else
0146       error('(%s) Both ch_type and ch_name are invalid', mfilename);
0147     end
0148 
0149   case  'EEG'
0150     % for EEG
0151     if strcmp(ch_type, 'REF')
0152       % return empty
0153       return;
0154     else
0155       [pick, Vcenter, result, channel_info] = vb_load_eeg_sensor(megfile, active_swt);
0156       return;
0157     end
0158   
0159   case  'INFO'
0160     load(megfile, 'fileinfo');
0161 
0162     switch method
0163       case 'AVE'
0164         [pick, Qpick, CoilWeight, Vcenter, result] = ...
0165           inner_calc_average(fileinfo);
0166       case 'TOP'
0167         [pick, Qpick, CoilWeight, Vcenter, result] = ...
0168           vb_load_sensor(fileinfo.filename{1}, [], [], false);
0169       otherwise
0170         msg = sprintf('(%s) undefined method : %s --> average', ...
0171           'vb_load_sensor', method);
0172         vb_disp(msg);
0173         [pick, Qpick, CoilWeight, Vcenter, result] = ...
0174           inner_calc_average(fileinfo);
0175     end
0176 
0177     % Loaded sensor info
0178     info    = vb_load_measurement_info(megfile);
0179     ch_info = vb_info_get_channel_info(info);
0180 
0181     % ch_info.ID : is IDs for loaded information(pick, Qpick, CoilWeight).
0182     % To access the fileinfo.channel_id data, search and find index of ch_info.ID
0183     if isfield(fileinfo, 'channel_id')
0184         active_ix = vb_util_get_index(ch_info.ID, fileinfo.channel_id);
0185     else
0186         active_ix = find(fileinfo.ActiveChannel == 1);
0187     end
0188     
0189     % reset active information
0190     ch_info.Active = zeros(length(ch_info.ID), 1);
0191     ch_info.Active(active_ix) = true;
0192 
0193     if active_swt
0194         chan_info_ix = active_ix;
0195     else
0196         chan_info_ix = [1:length(ch_info.ID)]';
0197     end
0198 
0199     % specified channel type and name
0200     chan_info_type = ch_info.Type(chan_info_ix);
0201     chan_info_name = ch_info.Name(chan_info_ix);
0202 
0203     % 'chan_info_ix' modification by channel type
0204     ignore_ch_name = false; % alternative (both specified case: ch_type is used.)
0205     if strcmpi(ch_type, 'MAG')
0206         chan_info_ix = chan_info_ix(find(chan_info_type == 1)); % MAG = 1;
0207         ignore_ch_name = true;
0208     elseif strcmpi(ch_type, 'AXIAL')
0209         chan_info_ix = chan_info_ix(find(chan_info_type == 2)); % AXIAL = 2;
0210         ignore_ch_name = true;
0211     elseif strcmpi(ch_type, 'PLANAR')
0212         chan_info_ix = chan_info_ix(find(chan_info_type == 3)); % PLANAR = 3;
0213         ignore_ch_name = true;
0214     elseif strcmpi(ch_type, 'MAG_X')
0215         chan_info_ix = chan_info_ix(find(chan_info_type == 4)); % MAG_X = 4;
0216         ignore_ch_name = true;
0217     elseif strcmpi(ch_type, 'MAG_Y')
0218         chan_info_ix = chan_info_ix(find(chan_info_type == 5)); % MAG_Y = 5;
0219         ignore_ch_name = true;
0220     elseif strcmpi(ch_type, 'MAG_Z')
0221         chan_info_ix = chan_info_ix(find(chan_info_type == 6)); % MAG_Z = 6;
0222         ignore_ch_name = true;
0223     elseif strcmpi(ch_type, 'MEG')
0224         % fall through
0225         % NOTE:default ch_type is 'MEG' even if the data file is for EEG.
0226     else
0227         error('unknown channel type is supported. : %s', ch_type);
0228     end
0229 
0230     % 'chan_info_ix' modification by channel name
0231     if ~isempty(ch_name)  && ignore_ch_name == false
0232         ix = [];
0233         for k=1:length(ch_name)
0234             add_ix = strmatch(ch_name{k}, chan_info_name, 'exact');
0235             if isempty(add_ix)
0236                 % display not found channel name.
0237                 fprintf('%s ', ch_name{k});
0238             end
0239             ix = [ix; add_ix];
0240         end
0241         if length(ix) ~= length(ch_name)
0242             fprintf('data not loaded.\n');
0243         end
0244         chan_info_ix = chan_info_ix(ix);
0245     end
0246 
0247     % get sensor info through the 'chan_info_ix'.
0248     if isempty(CoilWeight)
0249         pick = pick(chan_info_ix,:);
0250     else
0251         weight  = CoilWeight(chan_info_ix,:);
0252         ix_coil = find( sum(abs(weight), 1) > 0);
0253         
0254         pick = pick(ix_coil,:);
0255         Qpick = Qpick(ix_coil,:);
0256         CoilWeight = weight(:,ix_coil);
0257     end
0258 
0259     % channel_info
0260     channel_info.Active = ch_info.Active(chan_info_ix);
0261     channel_info.Name   = ch_info.Name(chan_info_ix);
0262     channel_info.Type   = ch_info.Type(chan_info_ix);
0263     channel_info.ID     = ch_info.ID(chan_info_ix);
0264 
0265 otherwise
0266     msg = sprintf('(%s)unknown Measurement : %s', func_, Measurement);
0267     vb_disp(msg);
0268     result = 2;
0269 end
0270 
0271 % --- solve empty center problem
0272 if isempty(Vcenter) && ~isempty(pick)
0273     Vcenter = sum(pick, 1) ./ size(pick, 1);
0274 end
0275 return;
0276 %
0277 % --- END OF MAIN PROCEDURE -------------------------------------------------- %
0278 
0279 % --- INNER FUNCTIONS -------------------------------------------------------- %
0280 %
0281 % --- inner_check_arguments()
0282 %
0283 function [megfile, ch_type, ch_name, active_swt, method, result] = ...
0284   inner_check_arguments(megfile, ch_type, ch_name, active_swt, method)
0285 func_ = mfilename;
0286 result = 0; % success
0287 
0288 if isempty(megfile)
0289   msg = sprintf('(%s)megfile is a required parameter', func_);
0290   vb_disp(msg);
0291   result = 1; % error code 1 means bad megfile
0292   return;
0293 end
0294 
0295 if exist(megfile, 'file') ~= 2
0296   msg = sprintf('(%s)cannot find megfile : %s', func_, megfile);
0297   vb_disp(msg);
0298   result = 1;
0299   return;
0300 end
0301 
0302 % --- ch_name must be a cell array
0303 if ischar(ch_name)
0304   ch_name = {ch_name};
0305 end
0306 
0307 if iscellstr(ch_name) && isempty(ch_name{1})
0308   ch_name = [];
0309 end
0310 
0311 if isempty(ch_type)
0312   if isempty(ch_name)
0313     ch_type = 'MEG';
0314   end
0315 end
0316 
0317 % case-insensitive
0318 ch_type = upper(ch_type);
0319 
0320 if isempty(active_swt)
0321   if vb_msrmnt_active_channel_is_valid(megfile)
0322     active_swt = true;
0323   else
0324     active_swt = false;
0325   end
0326 end
0327 
0328 if isempty(method)
0329   method = 'AVE';
0330 end
0331 method = upper(method);
0332 return;
0333 %
0334 % --- end of inner_check_arguments()
0335 
0336 % --- inner_calc_average()
0337 %
0338 function [pick, Qpick, CoilWeight, Vcenter, result] = ...
0339           inner_calc_average(fileinfo)
0340 %
0341 n_file = length(fileinfo.filename);
0342 
0343 pick = 0;
0344 Qpick = 0;
0345 CoilWeight = 0;
0346 Vcenter = 0;
0347 
0348 for i_file = 1:n_file
0349   cur_file = fileinfo.filename{i_file};
0350   [a, b, c, d] = vb_load_sensor(cur_file, [], [], false);
0351   
0352   pick = pick + a;
0353   Qpick = Qpick + b;
0354   CoilWeight = CoilWeight + c;
0355   Vcenter = Vcenter + d;
0356 end
0357 
0358 pick = pick / n_file;
0359 Qpick = Qpick / n_file;
0360 CoilWeight = CoilWeight / n_file;
0361 Vcenter = Vcenter / n_file;
0362 
0363 error_pick = zeros(size(pick,1), size(pick,2), n_file);
0364 error_Qpick = zeros(size(Qpick,1), size(Qpick,2), n_file);
0365 
0366 % --- error
0367 for i_file = 1:n_file
0368   cur_file = fileinfo.filename{i_file};
0369   [a, b, c, d] = vb_load_sensor(cur_file, [], [], false);
0370   error_pick(:,:,i_file) = pick - a;
0371   error_Qpick(:,:,i_file) = Qpick - b;
0372 end
0373 
0374 result = struct;
0375 result.error_pick = error_pick;
0376 result.error_Qpick = error_Qpick;
0377 return;
0378 %
0379 % --- end of inner_calc_average()
0380 %
0381 % --- END OF INNER FUNCTIONS ------------------------------------------------- %

Generated on Mon 22-May-2023 06:53:56 by m2html © 2005