%% (Internal) obsolete, use plot_ecg_strip % This function is used by the ECGtask related with QRS detection. % % Example % % Arguments: % % Output: % % See also plot_ecg_strip % % Author: Mariano Llamedo Soria llamedom@electron.frba.utn.edu.ar % Version: 0.1 beta % Last update: 14/5/2014 % Birthdate : 23/4/2013 % Copyright 2008-2015 function ECG_hdl = plot_ecg_heartbeat(ECG, lead_idx, QRS_locations, ECG_start_idx, QRS_start_idx, cant_qrs, heasig, filtro, axes_hdl ) if( nargin < 7 ) filtro = []; end if( nargin < 8 || isempty(axes_hdl) ) axes_hdl = gca; end ECG_hdl = []; % cla(axes_hdl); % axes(axes_hdl); axes(axes_hdl) fig_hdl = gcf; lECG = size(ECG,1); cant_sig = length(lead_idx); if( isempty(QRS_locations) ) QRS_start_idx = []; cant_qrs = []; end if( iscell(QRS_locations) ) other_QRS_locations = QRS_locations(2:end); QRS_locations = QRS_locations{1}; else other_QRS_locations = []; end cant_QRS_locations = length(QRS_locations); QRS_start_idx = min(cant_QRS_locations, QRS_start_idx); if( isfield(heasig, 'btime') ) aux_val = datevec(datenum(heasig.btime, 'HH:MM:SS')); base_start_time = round((aux_val(4) * 60 * 60 + aux_val(5) * 60 + aux_val(6)) * heasig.freq); else base_start_time = 1; end if( isempty(QRS_locations) ) start_idx = 1; end_idx = 10*heasig.freq; else if( (QRS_start_idx-cant_qrs) < 1 ) start_idx = max(1, (QRS_locations(QRS_start_idx) -ECG_start_idx + 1) - 5 * heasig.freq ); else % avoid gaps between marks aux_start = max(1, QRS_start_idx-cant_qrs); aux_idx = aux_start:QRS_start_idx; aux_marks = QRS_locations(aux_idx); valid_marks_idx = find(~isnan(aux_marks)); aux_diffs = diff(aux_marks); median_diff = median(aux_diffs); gap_idx = find( aux_diffs > 5*median_diff , 1, 'last' ); if( isempty(gap_idx) ) if( isempty(valid_marks_idx) ) start_idx = 1; else if( length(valid_marks_idx) < cant_qrs ) start_idx = max(1, (QRS_locations(aux_idx(valid_marks_idx(1)))-ECG_start_idx + 1)- 5 * heasig.freq ); else start_idx = max(1, (QRS_locations(aux_idx(valid_marks_idx(1)))-ECG_start_idx + 1) ); end end else start_idx = max(1, (aux_marks(gap_idx+1)-ECG_start_idx + 1) - 5 * heasig.freq); end end if( QRS_start_idx >= (cant_QRS_locations-cant_qrs) ) end_idx = min(lECG, (QRS_locations(QRS_start_idx) -ECG_start_idx + 1) + 5 * heasig.freq ); else aux_end = min(cant_QRS_locations, QRS_start_idx+cant_qrs); aux_idx = QRS_start_idx:aux_end; aux_marks = QRS_locations(aux_idx); valid_marks_idx = find(~isnan(aux_marks)); aux_diffs = diff(aux_marks); median_diff = median(aux_diffs); gap_idx = find( 5*median_diff < aux_diffs, 1, 'last' ); if( isempty(gap_idx) ) if( isempty(valid_marks_idx) ) end_idx = lECG; else if( length(valid_marks_idx) < cant_qrs ) end_idx = min(lECG, (QRS_locations(aux_idx(valid_marks_idx(end)))-ECG_start_idx + 1) + 5 * heasig.freq ); else end_idx = min(lECG, (QRS_locations(aux_idx(valid_marks_idx(end)))-ECG_start_idx + 1) ); end end else end_idx = min(lECG, (aux_marks(gap_idx)-ECG_start_idx + 1) + 5 * heasig.freq); end end end aux_idx = start_idx:end_idx; if( ~isempty(filtro) && ~isempty(aux_idx) ) % zero phase filtering of the ECG signals only. ECG_idx = get_ECG_idx_from_header(heasig); aux_lead_idx = intersect(lead_idx, ECG_idx); if( isempty(aux_lead_idx) ) if( isempty(ECG_idx) ) cprintf('[1,0.5,0]', disp_option_enumeration( 'No filter was applied since no ECG leads found. Lead description found:', cellstr(heasig.desc) ) ) fprintf(1, '\n') end else aux_idx2 = max(1, aux_idx(1) - 1 * heasig.freq ):min(lECG, aux_idx(end) + 1 * heasig.freq ); orig_class = class(ECG); aux_val = filter(filtro, double(flipud(ECG(aux_idx2,aux_lead_idx))) ); % round works bad with floating point. % ECG(aux_idx2,aux_lead_idx) = cast( round(filter(filtro, flipud(aux_val))), orig_class); ECG(aux_idx2,aux_lead_idx) = cast( (filter(filtro, flipud(aux_val))), orig_class); end end if( cant_sig > 1 ) max_values = max(ECG(aux_idx,lead_idx)); min_values = min(ECG(aux_idx,lead_idx)); aux_ranges = max_values - min_values; aux_sig = bsxfun( @minus, double(ECG(aux_idx,lead_idx)), mean(ECG(aux_idx,lead_idx))); aux_sig = bsxfun( @times, aux_sig, double(max(aux_ranges))./double(aux_ranges) ); ecg_max = max(max(aux_sig)); ecg_min = min(min(aux_sig)); else aux_sig = ECG(aux_idx,lead_idx); ecg_max = max(aux_sig); ecg_min = min(aux_sig); end ecg_range = ecg_max - ecg_min; k_range = 0.05; ecg_lims = [ ecg_min + k_range*ecg_range ecg_max - k_range*ecg_range ]; if( isempty(aux_idx) ) qrs_ploted =[]; else qrs_ploted = find(QRS_locations >= (aux_idx(1) + ECG_start_idx - 1) & QRS_locations <= (aux_idx(end) + ECG_start_idx - 1) ); end cla(axes_hdl); ColorOrder = my_colormap( 12 ); set(axes_hdl, 'ColorOrder', ColorOrder); set(axes_hdl, 'Ylim', ecg_lims ); hold(axes_hdl, 'on') ECG_hdl = colvec(arrayfun(@(sig_idx, col_idx)(plot(axes_hdl, aux_idx, aux_sig(:,sig_idx), 'Color', ColorOrder(col_idx,:) )), 1:length(lead_idx), lead_idx, 'UniformOutput', false )); % ECG_hdl = [ECG_hdl; colvec( arrayfun( @(a,b)( plot(axes_hdl, a, b , 'r--' )), repmat(rowvec(QRS_locations(qrs_ploted) - ECG_start_idx + 1 ),2,1), [ repmat(ecg_max, 1,length(qrs_ploted)) ; zeros(1,length(qrs_ploted)) ], 'UniformOutput', false ) ) ]; ECG_hdl = [ECG_hdl; colvec( cellfun( @(a,b)( plot(axes_hdl, a, b, 'r--' )), mat2cell( repmat(rowvec(QRS_locations(qrs_ploted) - ECG_start_idx + 1 ),2,1), 2, ones(length(qrs_ploted),1) ), mat2cell ( [ repmat(ecg_max, 1,length(qrs_ploted)) ; zeros(1,length(qrs_ploted))], 2, ones(length(qrs_ploted),1) ), 'UniformOutput', false) ) ]; aux_yrange = get(axes_hdl, 'Ylim'); ytext_loc = double(aux_yrange(2) - 0.05*ecg_range); if( ~isempty(qrs_ploted) ) aux_hdl2 = []; for ii = rowvec(qrs_ploted) aux_hdl = text( QRS_locations(ii) - ECG_start_idx + 1, ytext_loc, num2str(ii), 'BackgroundColor', [1 1 1], 'EdgeColor', ColorOrder(1,:), 'Margin', 2 ); end uistack(aux_hdl2, 'bottom'); aux_text_pos = get(aux_hdl, 'Extent'); aux_val = unique(QRS_locations(qrs_ploted) - ECG_start_idx + 1 ); set(axes_hdl, 'XTick', rowvec(aux_val) ); set(axes_hdl, 'XTickLabel', Seconds2HMS(colvec(aux_val + base_start_time - 1 + ECG_start_idx - 1)*1/heasig.freq) ); end if( isempty(other_QRS_locations) ) ytext_loc = aux_yrange(2); else jj = 2; x_offset = aux_text_pos(3); for this_QRS_location = rowvec(other_QRS_locations) this_QRS_locations = this_QRS_location{1}; qrs_ploted = find(this_QRS_locations >= aux_idx(1) & this_QRS_locations <= aux_idx(end) ); ECG_hdl = [ECG_hdl; colvec( cellfun( @(a,b)( plot(axes_hdl, a, b, 'LineStyle', ':', 'Color', ColorOrder(jj,:) )), mat2cell( repmat(rowvec(this_QRS_locations(qrs_ploted)),2,1), 2, ones(length(qrs_ploted),1) ), mat2cell ( [ repmat(ecg_max, 1,length(qrs_ploted)) ; zeros(1,length(qrs_ploted))], 2, ones(length(qrs_ploted),1) ), 'UniformOutput', false) ) ]; for ii = rowvec(qrs_ploted) text( this_QRS_locations(ii) + x_offset, ytext_loc, num2str(ii), 'FontSize', 7, 'BackgroundColor', [1 1 1], 'EdgeColor', ColorOrder(jj,:) ); end x_offset = x_offset + aux_text_pos(3); % ytext_loc = ytext_loc+aux_text_pos(4)/3; jj = jj + 1; end end aux_yrange = [aux_yrange(1) ytext_loc ]; set(axes_hdl, 'Ylim', aux_yrange); set(axes_hdl, 'Box', 'off'); hold(axes_hdl, 'off');