Home > bml > annot > bml_annot_intersect.m

bml_annot_intersect

PURPOSE ^

BML_ANNOT_INTERSECT returns the intersection of two annotation tables

SYNOPSIS ^

function annot = bml_annot_intersect(cfg, x, y)

DESCRIPTION ^

 BML_ANNOT_INTERSECT returns the intersection of two annotation tables

 Use as
   annot = bml_annot_intersect(x, y);
   annot = bml_annot_intersect(cfg, x, y);
   annot = bml_annot_intersect(cfg.keep, x, y);

 The first argument cfg is a optional configuration structure, which can contain
 the following optional fields:

 cfg.keep - string: 'x','y','none' or 'both'. Indicates which variables to keep
                         if 'both' (default), common variable names are prefixed
                         with the table's description. 
 cfg.description - string: description of output annotation
 cfg.warn - logical: indicates if warnings should be issue if variables
           are overwriten

 x, y - annot tables with fields 'starts' and 'ends'.
        'y' should have no overlapping annotations 

 Returns an annotation table with the folloing variables:
   id
   starts
   ends
   {x name}_id
   {y name}_id
   {x name}_{common vars}
   {y name}_{common vars}
   {unique x vars}
   {unique y vars}

 The name in annot.Properties.Description is set to 'intersect_{xname}_{yname}'

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function annot = bml_annot_intersect(cfg, x, y)
0002 
0003 % BML_ANNOT_INTERSECT returns the intersection of two annotation tables
0004 %
0005 % Use as
0006 %   annot = bml_annot_intersect(x, y);
0007 %   annot = bml_annot_intersect(cfg, x, y);
0008 %   annot = bml_annot_intersect(cfg.keep, x, y);
0009 %
0010 % The first argument cfg is a optional configuration structure, which can contain
0011 % the following optional fields:
0012 %
0013 % cfg.keep - string: 'x','y','none' or 'both'. Indicates which variables to keep
0014 %                         if 'both' (default), common variable names are prefixed
0015 %                         with the table's description.
0016 % cfg.description - string: description of output annotation
0017 % cfg.warn - logical: indicates if warnings should be issue if variables
0018 %           are overwriten
0019 %
0020 % x, y - annot tables with fields 'starts' and 'ends'.
0021 %        'y' should have no overlapping annotations
0022 %
0023 % Returns an annotation table with the folloing variables:
0024 %   id
0025 %   starts
0026 %   ends
0027 %   {x name}_id
0028 %   {y name}_id
0029 %   {x name}_{common vars}
0030 %   {y name}_{common vars}
0031 %   {unique x vars}
0032 %   {unique y vars}
0033 %
0034 % The name in annot.Properties.Description is set to 'intersect_{xname}_{yname}'
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 %no overlaps in x
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=[]; % x.Properties.VariableNames{1}=xidn;
0125 y.starts=[]; y.ends=[]; % y.Properties.VariableNames{1}=yidn;
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 %s. Allowed values are 'both', 'none', 'x' or 'y'",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       %common_vars_x(bml_getidx(rm_vars(i),x.Properties.VariableNames))=[];
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       %common_vars_y(bml_getidx(rm_vars(i),y.Properties.VariableNames))=[];
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

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