0001 function conformed = bml_conform_to(master, slave)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 assert(isstruct(master) && all(ismember({'trial','time','label'},fieldnames(master))),"Invalid master");
0026 assert(isstruct(slave) && all(ismember({'trial','time','label'},fieldnames(slave))),"Invalid slave");
0027
0028 master_N = length(master.trial);
0029 nChans = length(slave.label);
0030
0031
0032 annot_master = bml_raw2annot(master);
0033 annot_slave = bml_raw2annot(slave);
0034 master_slave = bml_annot_intersect(annot_master,annot_slave);
0035 assert(~isempty(master_slave), "Can't conform. No master trials correspond to any slave trials.");
0036 master_slave.master_frac = master_slave.duration/master_slave.master_duration;
0037 ms_map = zeros(length(master.trial),1);
0038 for i=1:master_N
0039 i_ms=master_slave(master_slave.master_id==i,:);
0040 if height(i_ms)>1
0041 [~,i_ms_max_idx]=max(i_ms.master_frac);
0042 i_ms = i_ms(i_ms_max_idx,:);
0043 end
0044 if height(i_ms)>0
0045 ms_map(i)=i_ms.slave_id(1);
0046 end
0047 end
0048
0049
0050 sub_slave_N=sum(ms_map>0);
0051 sub_slave=[];
0052 sub_slave.label = slave.label;
0053 sub_slave.trial = cell(1,sub_slave_N);
0054 sub_slave.time = cell(1,sub_slave_N);
0055 sub_master_time = cell(1,sub_slave_N);
0056 starts=zeros(sub_slave_N,1);
0057 ends=zeros(sub_slave_N,1);
0058 sub_ms_map = zeros(master_N,1);
0059 sub_slave_i=1;
0060 for i=1:master_N
0061 mc = annot_master(i,:);
0062 if ms_map(i)==0
0063 warning("Master trial
0064 else
0065 starts(sub_slave_i) = mc.t1;
0066 ends(sub_slave_i) = mc.t2;
0067 sub_ms_map(i) = sub_slave_i;
0068 sub_slave.trial{sub_slave_i} = slave.trial{ms_map(i)};
0069 sub_slave.time{sub_slave_i} = slave.time{ms_map(i)};
0070 sub_master_time{sub_slave_i} = master.time{i};
0071 sub_slave_i = sub_slave_i + 1;
0072 end
0073 end
0074
0075
0076
0077 if annot_slave.Fs(1) > 1.01 * annot_master.Fs(1)
0078 fprintf("low-pass filtering slave [
0079 cfg=[]; cfg.lpfilter='yes'; cfg.lpfreq=annot_master.Fs(1)/2;
0080 cfg.lpfilttype = 'but'; cfg.lpfiltord = 6;
0081 cfg.lpfiltdir = 'twopass';
0082 cfg.lpinstabilityfix = 'no';
0083 cfg.lpfiltwintype = 'hamming';
0084 slave = ft_preprocessing(cfg,slave);
0085 end
0086
0087
0088 cfg=[]; cfg.time=sub_master_time; cfg.method='pchip';
0089 cfg.feedback='no';
0090 sub_conformed=ft_resampledata(cfg,bml_crop(sub_slave,starts,ends));
0091
0092
0093 conformed=[];
0094 conformed.label = slave.label;
0095 conformed.trial = cell(1,master_N);
0096 conformed.time = cell(1,master_N);
0097 for i=1:master_N
0098 if sub_ms_map(i)>0
0099 conformed.time{i}=sub_conformed.time{sub_ms_map(i)};
0100 conformed.trial{i}=sub_conformed.trial{sub_ms_map(i)};
0101 else
0102 conformed.time{i}=master.time{i};
0103 conformed.trial{i}=zeros(nChans,length(conformed.time{i}));
0104 end
0105 end
0106
0107 if ismember('hdr',fields(slave))
0108 conformed.hdr=slave.hdr;
0109 else
0110 conformed.hdr=[];
0111 end
0112
0113
0114 conformed.hdr.nChans = length(conformed.label);
0115 conformed.hdr.Fs=round(1/mean(diff(conformed.time{1})));
0116 conformed.hdr.label=conformed.label;
0117
0118 if ismember('fsample',fields(master))
0119 conformed.fsample = master.fsample;
0120 conformed.hdr.Fs = master.fsample;
0121 elseif ismember('fsample',fields(conformed))
0122 conformed = rmfield(conformed,'fsample');
0123 end
0124
0125
0126
0127
0128
0129
0130
0131