0001 function annot = bml_annot_intersect(cfg, x, y)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 if nargin == 2
0037 y=bml_annot_table(x,[],inputname(2));
0038 x=bml_annot_table(cfg,[],inputname(1));
0039 cfg=[];
0040 description = ['intersect_' x.Properties.Description '_' y.Properties.Description];
0041 elseif nargin == 3
0042 if ischar(cfg) || iscellstr(cfg) || isstring(cfg)
0043 cfg = struct('keep',cellstr(cfg));
0044 end
0045 x=bml_annot_table(x,[],inputname(2));
0046 y=bml_annot_table(y,[],inputname(3));
0047 description = ['intersect_' x.Properties.Description '_' y.Properties.Description];
0048 description = ft_getopt(cfg,'description',description);
0049 else
0050 error('use as bml_annot_intersect(x, y)')
0051 end
0052
0053 keep = bml_getopt_single(cfg,'keep','both');
0054 warn = bml_getopt(cfg,'warn',true);
0055
0056 if isempty(x.Properties.Description); x.Properties.Description = 'x'; end
0057 if isempty(y.Properties.Description); y.Properties.Description = 'y'; end
0058
0059 if strcmp(x.Properties.Description,y.Properties.Description)
0060 x.Properties.Description = [x.Properties.Description '_x'];
0061 y.Properties.Description = [y.Properties.Description '_y'];
0062 end
0063
0064 xidn=[x.Properties.Description '_id'];
0065 yidn=[y.Properties.Description '_id'];
0066
0067 ovlp_x = ~isempty(bml_annot_overlap(x));
0068 ovlp_y = ~isempty(bml_annot_overlap(y));
0069 if ovlp_y; error('''y'' has overlaps'); end
0070
0071 i=1; j=1;
0072 annot = cell2table(cell(0,4));
0073 annot.Properties.VariableNames = {'starts','ends',xidn,yidn};
0074
0075 if ovlp_x
0076 while i<=height(x) && j<=height(y)
0077 if x.starts(i) < y.ends(j) && x.ends(i) > y.starts(j)
0078 annot = [annot;{...
0079 max(x.starts(i),y.starts(j)),...
0080 min(x.ends(i),y.ends(j)),...
0081 x.id(i),...
0082 y.id(j)}];
0083 if x.ends(i) < y.ends(j) || j >= height(y)
0084 i = i + 1;
0085 j=1;
0086 else
0087 j = j + 1;
0088 end
0089 elseif x.ends(i) <= y.starts(j) || j >= height(y)
0090 i=i+1;
0091 j=1;
0092 elseif x.starts(i) >= y.ends(j)
0093 j=j+1;
0094 else
0095 error('Unsupported input annotations tables');
0096 end
0097 end
0098 else
0099 while i<=height(x) && j<=height(y)
0100 if x.starts(i) < y.ends(j) && x.ends(i) > y.starts(j)
0101 annot = [annot;{...
0102 max(x.starts(i),y.starts(j)),...
0103 min(x.ends(i),y.ends(j)),...
0104 x.id(i),...
0105 y.id(j)}];
0106 if x.ends(i) < y.ends(j)
0107 i = i + 1;
0108 else
0109 j = j + 1;
0110 end
0111 elseif x.ends(i) <= y.starts(j)
0112 i=i+1;
0113 elseif x.starts(i) >= y.ends(j)
0114 j=j+1;
0115 else
0116 error('Unsupported input annotations tables');
0117 end
0118 end
0119 end
0120
0121 annot = bml_annot_table(annot,description);
0122 if isempty(annot); return; end
0123
0124 x.starts=[]; x.ends=[];
0125 y.starts=[]; y.ends=[];
0126
0127 switch keep
0128 case {'both','keepboth','keep both','keep_both'}
0129 keep='both';
0130 common_vars=intersect(x.Properties.VariableNames,y.Properties.VariableNames);
0131 common_vars_x=ismember(x.Properties.VariableNames,common_vars);
0132 common_vars_y=ismember(y.Properties.VariableNames,common_vars);
0133 unique_vars_x=setdiff(x.Properties.VariableNames,common_vars);
0134 unique_vars_y=setdiff(y.Properties.VariableNames,common_vars);
0135 case {'none','keepnone','keep none','keep_none'}
0136 keep='none';
0137 common_vars_x=[];
0138 common_vars_y=[];
0139 unique_vars_x=[];
0140 unique_vars_y=[];
0141 case {'x','keepx','keep x','keep_x'}
0142 keep='x';
0143 common_vars_x={'id','duration'};
0144 common_vars_y=[];
0145 unique_vars_x=setdiff(x.Properties.VariableNames,common_vars_x);
0146 unique_vars_y=[];
0147 case {'y','keepy','keep y','keep_y'}
0148 keep='y';
0149 common_vars_x=[];
0150 common_vars_y={'id','duration'};
0151 unique_vars_x=[];
0152 unique_vars_y=setdiff(y.Properties.VariableNames,common_vars_y);
0153 otherwise
0154 error("unknown value for keep
0155 end
0156
0157 new_names_common_vars_x = strcat([x.Properties.Description '_'],x.Properties.VariableNames(common_vars_x));
0158 if ~isempty(new_names_common_vars_x)
0159 new_names_common_vars_x_repeated = ismember(new_names_common_vars_x,unique_vars_x);
0160 if any(new_names_common_vars_x_repeated)
0161 rm_vars = new_names_common_vars_x(new_names_common_vars_x_repeated);
0162 for i=1:length(rm_vars)
0163 if warn
0164 warning('Overwriting variable %s of table %s',rm_vars{i},x.Properties.Description);
0165 end
0166
0167 x.(rm_vars{i})=[];
0168 end
0169 end
0170 end
0171
0172 new_names_common_vars_y = strcat([y.Properties.Description '_'],y.Properties.VariableNames(common_vars_y));
0173 if ~isempty(new_names_common_vars_y)
0174 new_names_common_vars_y_repeated = ismember(new_names_common_vars_y,unique_vars_y);
0175 if any(new_names_common_vars_y_repeated)
0176 rm_vars = new_names_common_vars_y(new_names_common_vars_y_repeated);
0177 for i=1:length(rm_vars)
0178 if warn
0179 warning('Overwriting variable %s of table %s',rm_vars{i},y.Properties.Description);
0180 end
0181
0182 y.(rm_vars{i})=[];
0183 end
0184 end
0185 end
0186
0187 x.Properties.VariableNames(common_vars_x) = new_names_common_vars_x;
0188 y.Properties.VariableNames(common_vars_y) = new_names_common_vars_y;
0189
0190 if ismember(yidn,x.Properties.VariableNames)
0191 if warn
0192 warning('Overwriting variable %s from table %s',yidn,x.Properties.Description);
0193 end
0194 x.(yidn)=[];
0195 end
0196 if ismember(xidn,y.Properties.VariableNames)
0197 if warn
0198 warning('Overwriting variable %s from table %s',xidn,y.Properties.Description);
0199 end
0200 y.(xidn)=[];
0201 end
0202
0203 if ismember(keep,{'x','both'})
0204 annot=join(annot,x,'Keys',xidn);
0205 end
0206 if ismember(keep,{'y','both'})
0207 annot=join(annot,y,'Keys',yidn);
0208 end
0209
0210
0211
0212
0213
0214
0215
0216