Home > bml > signal > bml_hstack.m

bml_hstack

PURPOSE ^

BML_HSTACK concatenates multiple raw data structures by time

SYNOPSIS ^

function [data] = bml_hstack(cfg, varargin)

DESCRIPTION ^

 BML_HSTACK concatenates multiple raw data structures by time

 Use as
   data = bml_hstack(cfg, raw1, raw2, raw3, ..., rawN)
 where the configuration can be empty.

 cfg.timetol - double: time tolerance in seconds
 cfg.timeref - string: either 'common', 'independent' or 'auto'
               if 'auto' it is set to common if raws are time contiguous
 cfg.match_labels - logical: indicates if same labels (channel names)
               should be enforced for concatenation. If false and all
               raws have the same number of labels, concatenation will
               proceed with a warning. Defaults to true. 

 returns a time-concatenated raw

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [data] = bml_hstack(cfg, varargin)
0002 
0003 % BML_HSTACK concatenates multiple raw data structures by time
0004 %
0005 % Use as
0006 %   data = bml_hstack(cfg, raw1, raw2, raw3, ..., rawN)
0007 % where the configuration can be empty.
0008 %
0009 % cfg.timetol - double: time tolerance in seconds
0010 % cfg.timeref - string: either 'common', 'independent' or 'auto'
0011 %               if 'auto' it is set to common if raws are time contiguous
0012 % cfg.match_labels - logical: indicates if same labels (channel names)
0013 %               should be enforced for concatenation. If false and all
0014 %               raws have the same number of labels, concatenation will
0015 %               proceed with a warning. Defaults to true.
0016 %
0017 % returns a time-concatenated raw
0018 
0019 
0020 % 2017.10.27 AB: based on ft_appenddata,
0021 %
0022 % Copyright (C) 2005-2008, Robert Oostenveld
0023 % Copyright (C) 2009-2011, Jan-Mathijs Schoffelen
0024 %
0025 % This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
0026 % for the documentation and details.
0027 %
0028 %    FieldTrip is free software: you can redistribute it and/or modify
0029 %    it under the terms of the GNU General Public License as published by
0030 %    the Free Software Foundation, either version 3 of the License, or
0031 %    (at your option) any later version.
0032 %
0033 %    FieldTrip is distributed in the hope that it will be useful,
0034 %    but WITHOUT ANY WARRANTY; without even the implied warranty of
0035 %    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0036 %    GNU General Public License for more details.
0037 %
0038 %    You should have received a copy of the GNU General Public License
0039 %    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
0040 %
0041 % $Id$
0042 
0043 % check if the input data is valid for this function
0044 % for i=1:length(varargin)
0045 %   % FIXME: raw+comp is not always dealt with correctly
0046 %   varargin{i} = ft_checkdata(varargin{i}, 'datatype', {'raw', 'raw+comp'}, 'feedback', 'no');
0047 % end
0048 
0049 % set the defaults
0050 cfg.appenddim  = 'time';
0051 timetol       = bml_getopt(cfg, 'timetol', 1e-5);
0052 timeref       = bml_getopt(cfg, 'timeref', 'auto');
0053 match_labels  = bml_getopt(cfg, 'match_labels', true);
0054 
0055 isequaltime  = true;
0056 isequallabel = true;
0057 issamelabel  = true;
0058 issamenchan = true;
0059 isequaltrial = true;
0060 isequalfreq  = true;
0061 for i=2:numel(varargin)
0062   isequaltime  = isequaltime  && isequal(varargin{i}.time , varargin{1}.time );
0063   isequallabel = isequallabel && isequal(varargin{i}.label, varargin{1}.label);
0064   issamelabel  = issamelabel  && isempty(setxor(varargin{i}.label, varargin{1}.label));
0065   issamenchan  = issamenchan && (length(varargin{i}.label) == length(varargin{1}.label));
0066   isequaltrial = isequaltrial && isequal(numel(varargin{i}.trial),numel(varargin{1}.trial));
0067   isequalfreq  = isequalfreq && length(uniquetol([varargin{i}.fsample,varargin{1}.fsample],timetol))==1;
0068 end
0069 
0070 % ft_selectdata cannot create the union of the data contained in cell-arrays
0071 % make a dummy without the actual data, but keep trialinfo/sampleinfo/grad/elec/opto
0072 % also remove the topo/unmixing/topolabel, if present, otherwise it is not
0073 % possible to concatenate raw and comp data. Note that in append_common the
0074 % topo etc. is removed anyhow, when appenddim = 'chan'
0075 dummy = cell(size(varargin));
0076 for i=1:numel(varargin)
0077   dummy{i} = removefields(varargin{i}, {'trial', 'time'});
0078   if strcmp(cfg.appenddim, 'chan')
0079     dummy{i} = removefields(dummy{i}, {'topo', 'unmixing', 'topolabel'});
0080   end
0081   % add a dummy data field, this causes the datatype to become 'chan'
0082   dummy{i}.dummy       = ones(numel(dummy{i}.label),1);
0083   dummy{i}.dummydimord = 'chan';
0084 end
0085 
0086 if ~isequallabel
0087   if issamelabel
0088     for i=2:length(varargin)
0089       cfg1=[];
0090       cfg1.label = varargin{1}.label;
0091       varargin{i} = bml_reorder_channels(cfg1,varargin{i});
0092     end
0093   elseif issamenchan && ~match_labels
0094     ft_warning('concatenating raws with different channel names. Keeping labels of first raw.')
0095     for i=2:length(varargin)
0096       varargin{i}.label = varargin{1}.label;
0097       dummy{i}.label = varargin{1}.label;
0098     end
0099   else
0100       ft_error('Same channels required to append data by time')
0101   end
0102 end
0103 if ~isequaltrial
0104     ft_error('Same number of trials required to append data by time')
0105 end  
0106 if ~isequalfreq
0107     ft_error('Same Fs required to append data by time')        
0108 end
0109 
0110 % don't do any data appending inside the common function
0111 cfg.parameter = {};
0112 % use a low-level function that is shared with the other ft_appendxxx functions
0113 % this will handle the trialinfo/sampleinfo/grad/elec/opto
0114 data = append_common(cfg, dummy{:});
0115 % this is the actual data field that will be appended further down
0116 
0117 if ismember('fsample',fieldnames(varargin{1}))
0118   data.fsample=varargin{1}.fsample;
0119 end
0120 if ismember('hdr',fieldnames(varargin{1}))
0121   data.hdr=varargin{1}.hdr;
0122 end
0123 %data.sampleinfo=[];
0124 
0125 if strcmp(timeref,'auto')
0126   if bml_check_contiguity(cfg,varargin{:})
0127     timeref = 'common';
0128   else
0129     timeref = 'independent';
0130   end
0131 end
0132 
0133 if strcmp(timeref,'independent')
0134   dat = cell(1,0);
0135   tim = cell(1,0);
0136   for t=1:numel(varargin{1}.trial)
0137     trial_dat=[];
0138     trial_tim=[];
0139     curtime=varargin{i}.time{t}(1);
0140     for i=1:numel(varargin)
0141       trial_dat = cat(2, trial_dat, varargin{i}.trial{t});
0142       time0=varargin{i}.time{t}(1);
0143       trial_tim = cat(2, trial_tim, curtime-time0+1/data.fsample+varargin{i}.time{t});
0144       curtime=trial_tim(end);
0145     end
0146     dat = cat(2, dat, trial_dat);
0147     tim = cat(2, tim, trial_tim);
0148   end
0149   data.trial = dat;
0150   data.time  = tim;      
0151 elseif strcmp(timeref,'common')
0152   dat = cell(1,0);
0153   tim = cell(1,0);
0154   for t=1:numel(varargin{1}.trial)
0155     trial_dat=[];
0156     trial_tim=[];
0157     for i=1:numel(varargin)
0158       trial_dat = cat(2, trial_dat, varargin{i}.trial{t});
0159       trial_tim = cat(2, trial_tim, varargin{i}.time{t});
0160     end
0161     dat = cat(2, dat, trial_dat);
0162     tim = cat(2, tim, trial_tim);
0163   end
0164   data.trial = dat;
0165   data.time  = tim; 
0166 else
0167   error('unknown cfg.timeref');
0168 end
0169

Generated on Tue 25-Sep-2018 10:08:19 by m2html © 2005