0001 function annot = bml_annot_detect(cfg, env)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
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
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);