Home > bml > annot > bml_annot_detect.m

bml_annot_detect

PURPOSE ^

BML_ANNOT_DETECT identifies annotations thresholding an envelope signal

SYNOPSIS ^

function annot = bml_annot_detect(cfg, env)

DESCRIPTION ^

 BML_ANNOT_DETECT identifies annotations thresholding an envelope signal

 Use as
   annot = bml_annot_detect(cfg, raw)

 cfg.threshold - double len 1 or 2: lower/upper threshold for the segmentation
 cfg.max_annots - integer: maximun number of regions of interest in a
       envelope

 returns an annotation table

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function annot = bml_annot_detect(cfg, env)
0002 
0003 % BML_ANNOT_DETECT identifies annotations thresholding an envelope signal
0004 %
0005 % Use as
0006 %   annot = bml_annot_detect(cfg, raw)
0007 %
0008 % cfg.threshold - double len 1 or 2: lower/upper threshold for the segmentation
0009 % cfg.max_annots - integer: maximun number of regions of interest in a
0010 %       envelope
0011 %
0012 % returns an annotation table
0013 
0014 max_annots        = bml_getopt(cfg, 'max_annots', inf);
0015 threshold         = bml_getopt(cfg, 'threshold');
0016 if ~isempty(threshold)
0017   assert(length(threshold)<=2,"threshold should be of length 1 or 2");
0018   lower_threshold = threshold(1);
0019   upper_threshold = threshold(end);
0020 else
0021   lower_threshold = [];
0022   upper_threshold = [];
0023 end
0024 upper_threshold   = bml_getopt(cfg, 'upper_threshold', upper_threshold);
0025 lower_threshold   = bml_getopt(cfg, 'lower_threshold', lower_threshold);
0026 assert(~isempty(upper_threshold) & ~isempty(lower_threshold),"cfg.threshold required");
0027 
0028 assert(numel(env.label)==1,"One channel in env expected for detection");
0029 
0030 annot = table();
0031 for i=1:numel(env.trial)
0032   i_env = ft_selectdata(struct('trial',i,'feedback','no'), env);
0033   env_coord = bml_raw2coord(i_env);
0034   
0035   zero_cross_ixs = find(abs(diff(sign(env.trial{i}-lower_threshold)))>=1);
0036   reset_value=min([min(env.trial{i}),0]);
0037   search_detect = true;
0038   loop_count = 0;
0039   while search_detect
0040       loop_count = loop_count + 1;
0041     [env_max, env_max_ix] = max(env.trial{i});       
0042     assert(loop_count <= max_annots, "More annots detected than max_annots");
0043         
0044     if env_max > upper_threshold
0045         %finding start and end of current annot
0046       if isempty(zero_cross_ixs)
0047         starts = env.time{i}(1)-0.5/env.fsample;
0048         ends = env.time{i}(end)+0.5/env.fsample;
0049       elseif env_max_ix <= zero_cross_ixs(1)
0050         starts = env.time{i}(1)-0.5/env.fsample;
0051         ends = env.time{i}(zero_cross_ixs(1))+0.5/env.fsample;
0052       elseif env_max_ix > zero_cross_ixs(end)
0053           starts = env.time{i}(zero_cross_ixs(end))-0.5/env.fsample;
0054         ends = env.time{i}(end)+0.5/env.fsample;
0055       else
0056           zc_ix = find(diff(sign(zero_cross_ixs-env_max_ix)),1);
0057         starts = env.time{i}(zero_cross_ixs(zc_ix))-0.5/env.fsample;
0058         ends = env.time{i}(zero_cross_ixs(zc_ix+1))+0.5/env.fsample;
0059       end
0060             
0061       overlaps = false;
0062       for j=1:height(annot)
0063         row = annot(j,:);
0064         if row.starts < ends && row.ends > starts
0065           overlaps = true;
0066         end
0067       end
0068       if ~overlaps
0069         annot = [annot; table(starts,ends,env_max,i)];
0070       end
0071       [s,e] = bml_crop_idx_valid(env_coord,starts,ends);
0072       env.trial{i}(1,s:e)=reset_value;
0073     else
0074         search_detect = false;
0075     end
0076   end
0077 end
0078 
0079 annot = bml_annot_table(annot);

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