%% (Internal) Create new QRS detections based on other lead/algorithms detections % % artificial_annotations = combine_anns(time_serie, estimated_labs, header) % % Arguments: % % + time_serie: all the QRS detections % % + estimated_labs: estimated labels (TP, FP, FN) of each detection % % + header: ECG header struct. % % Output: % % + artificial_annotations: all the QRS detections plus the new ones % created. % % Example: % % aux_idx = best_detections_idx(1:min(10, length(best_detections_idx))); % artificial_annotations = combine_anns(all_annotations(aux_idx), estimated_labs(aux_idx), ECG_struct.header); % % See also QRScorrector % % Author: Mariano Llamedo Soria llamedom@electron.frba.utn.edu.ar % Version: 0.1 beta % Last update: 14/5/2014 % Birthdate : 21/4/2015 % Copyright 2008-2015 % function artificial_annotations = combine_anns(time_serie, estimated_labs, header) % cantidad de leads artificiales que generará min_artificial_leads = 3; % lreferences = length(time_serie); for ii = 1:min_artificial_leads artificial_annotations(ii).time = []; end start_sample = min(cell2mat(cellfun(@(a)(min(a)),time_serie, 'UniformOutput', false))); end_sample = max(cell2mat(cellfun(@(a)(max(a)),time_serie, 'UniformOutput', false))) + 1; win_size = 20e3; % milliseconds % aux_seq = (start_sample+win_size):round(win_size/2):end_sample; aux_seq = (start_sample+win_size):win_size:end_sample; if( isempty(aux_seq) ) return end if(aux_seq(end) ~= end_sample ) aux_seq = [aux_seq (aux_seq(end)+win_size) ]; end laux_seq = length(aux_seq); aux_idx = arrayfun(@(a)( ... cellfun( @(b)( ... findStartEnd( b >= (a - win_size) & b < a ) ... ), time_serie, 'UniformOutput', false )... ), aux_seq, 'UniformOutput', false); aux_q = cellfun( @(a)( cell2mat(cellfun( @(b, c)( ... calc_q_val( b, c ) ... ), estimated_labs, a, 'UniformOutput', false ))... ), aux_idx, 'UniformOutput', false ); [~, aux_q_idx] = cellfun( @(a)( sort(a, 'descend') ), aux_q, 'UniformOutput', false ); % TODO: hacer una estrategia que divida los segmentos de aux_seq hasta % que no haya problemas de transiciones de los segmentos solapados. % while() % aux_idx = arrayfun( @(ii)( cell2mat(arrayfun( @(jj)( find_disagreements(aux_idx, aux_q_idx, ii, jj ) ), 1:laux_seq , 'UniformOutput', false)) ), 1:3, 'UniformOutput', false ); % end aux_val = arrayfun( @(ii)( cell2mat(cellfun( @(a, q_idx)( build_combined_series(time_serie, a, q_idx, ii ) ), aux_idx, aux_q_idx, 'UniformOutput', false)) ), 1:min_artificial_leads, 'UniformOutput', false ); cant_artificial_leads = min(min_artificial_leads, sum(cellfun(@(a)(~isempty(a)), aux_val )) ); if( cant_artificial_leads > 0 ) for ii = 1:cant_artificial_leads % avoid annotations very close each other. aux_time_serie = aux_val{ii}; aux_time_serie(find( diff(sort(aux_time_serie)) <= round(0.15 * header.freq) ) +1) = []; if( ~isempty(aux_time_serie) ) artificial_annotations(ii).time = colvec(aux_time_serie); end end if( cant_artificial_leads < min_artificial_leads ) for ii = cant_artificial_leads+1:min_artificial_leads artificial_annotations(ii).time = artificial_annotations(cant_artificial_leads).time; end end end function start_end_aux = findStartEnd( bAux ) start_aux = find( bAux, 1, 'first' ); end_aux = find( bAux, 1, 'last' ); start_end_aux = [start_aux end_aux]; function this_q = calc_q_val(this_labs, strt_end) % win_size in milliseconds if( isempty(strt_end) || isempty(this_labs) ) this_q = []; else this_labs = this_labs(strt_end(1):strt_end(2)); this_se = sum(this_labs == 3) / sum(this_labs == 3 | this_labs == 1) ; this_pp = sum(this_labs == 3) / sum(this_labs == 3 | this_labs == 2) ; this_q = (2*this_se + this_pp)/3; end function new_str_end = find_disagreements(str_end, q_idx, ii, jj) this_q_idx = q_idx{jj}; next_q_idx = q_idx{jj+1}; if( isempty(this_q_idx) || ii > length(q_idx) ) new_str_end = []; else if( q_idx(ii) == q_idx(ii+1) ) new_str_end = []; else end end function combined_series = build_combined_series(ts, str_end, q_idx, ii) if( isempty(q_idx) || ii > length(q_idx) ) combined_series = []; else q_idx = q_idx(ii); aux_idx = str_end{q_idx}; aux_val = ts{q_idx}; if( isempty(aux_idx) || isempty(aux_val) ) combined_series = []; else combined_series = rowvec(aux_val(aux_idx(1):aux_idx(2))); end end