ECG-Kit 1.0

File: <base>/common/plot_ecg_mosaic.m (47,046 bytes)
%% Plots multidimentional signal in mosaic style
% This function plots several subplots in the same figure in order to do a
% mosaic with the different leads available in ECG. Annotations can be
% provided to each or for all the mosaic.
%   
% Prototype
% 
%   [ ECG_hdl axes_hdl fig_hdl all_yranges ] = plot_ecg_mosaic( ECG, varargin )
% 
% Arguments:
% 
%     +ECG: [numeric or cell] REQUIRED
%           
%           [numeric]: signal matrix of dimension [sig_length sig_size
%           repetitions_size] where:
%             - sig_length: time length in samples
%             - sig_size: number of ECG leads or number of signals.
%             - repetitions_size: number of repetitions of the same
%             signals. Typically used when time-synchronized events, like
%             heartbeats.  
%           
%           [cell]: cell array of length repetitions_size, where each cell
%           is (probably a time alligned event) a signal of dimension
%           [sig_length sig_size]
% 
%     +QRS_locations: [numeric] OPTIONAL. Default values enclosed in ()
%                 Synchronization sample. In ECG context, this values are
%                 the QRS fiducial point. (empty)
% 
%     +WinSize: [numeric] OPTIONAL. Default values enclosed in ()
%           Width of the window around each fiducial point provided in
%           QRS_locations. (empty)
% 
%     +ECG_header: [struct] OPTIONAL. 
% 
%             Description of the ECG typically available in the
%             header. Structure with fields:
% 
%               -freq: Sampling rate in Hz. (1)
% 
%               -nsig: Number of ECG leads. (size(ECG,2))
% 
%               -nsamp: Number of ECG samples. (size(ECG,1))
% 
%               -adczero: ADC offset (e.g. 2^(adc_res-1) when
%               using unsigned integers). ( repmat(0, ECG_header.nsig , 1) ) 
% 
%               -adcgain: ADC gain in units/adc_sample
%               (typically uV/adc_unit). ( repmat(1, ECG_header.nsig , 1) )
% 
%               -units: Measurement units. ( repmat('uV', ECG_header.nsig , 1) )
% 
%               -desc: Signal description. ( num2str(colvec(1:ECG_header.nsig)) )
%                 
%     +MaxECGrange: [numeric or string] OPTIONAL. Force a vertial range in order to
%                     ease visual comparison of signals in the mosaic. 
%                   [string] 
%                     'max': force the maximum range to be the range
%                            for all mosaics.
%                     'min', 'mean', 'median': are also available options.
%                     'none': Each mosaic with a different range. (Default).
%     
%     +RowsCols: [numeric] OPTIONAL. Number of rows and columns of the
%                 mosaic. If ommited or if rows * cols ~= ECG_header.nsig, these values are
%                 automatically adapted to the best fit mosaic in relation to the
%                 aspect ratio of the screen.   
%     
%     +FigureHdl: [figure handle] OPTIONAL. Choose the figure to be produced
%                the mosaic. (handle produced by gcf)
% 
%     +ECG_delineation: [struct] OPTIONAL. Default values enclosed in ()
%               Annotation struct generated with wavedet. 
% 
%     +ECG_annotations: [cell] OPTIONAL. Default values enclosed in ()
%               Annotations to be included in the mosaic. The funcion
%               accepts 2 type of annotations: points and lines. 
% 
% Output:
% 
%     + ECG_hdl: handle to the plotted signals.
% 
%     + axes_hdl: handle to the axes.
% 
%     + fig_hdl: handle to fig.
% 
%     + all_yranges: vertical ranges of the plotted signals.
% 
% 
% Example:
% 
% This example makes a synchronized plot of several random events (+1 0 -1)
% ocurryng randomly with additive white gaussian noise.  
% win_size = 100; 
% sig_samp = 10000;
% sig_size = 12;
% event_size = 50;
% x = 0.1*randn(sig_samp,sig_size); 
% event_locations = randsample(win_size:sig_samp-win_size, event_size);
% x(event_locations-1,:) = x(event_locations-1,:) + 1;
% x(event_locations+1,:) = x(event_locations+1,:) - 1;
% x_packed = pack_signal(x, event_locations, win_size);    
% 
% figure(1)
% % estimation of the signal averaged event
% plot_ecg_mosaic( mean(x_packed,3) );
% figure(2)
% % visualization of all events. In this case previous pack_signal call is
% % not needed. 
% plot_ecg_mosaic(x, 'QRS_locations', event_locations, 'WinSize', win_size);
% 
% figure(3)
% % introducing several kind of marks to the plot
% 
% h_line = cell(sig_size,7);
% h2_line = cell(sig_size,7);
% v_line = cell(sig_size,7);
% v2_line = cell(sig_size,7);
% point = cell(sig_size,7);
% a_line = cell(sig_size,7);
% 
% h_line(:,1) = {'line'};
% h_line(:,2) = { [ { 'String'                     'LineStyle' 'LineWidth' 'Color' 'TextColor' }; ...
%                   { 'horizontal line text'       '--'         1.5         'r'     'r'        } ]'}; 
% h_line(1:sig_size, [6 7]) = num2cell( repmat(-0.5,sig_size,2) );
% 
% h2_line(:,1) = {'line'};
% h2_line(:,2) = { [ { 'String'           'LineStyle' 'LineWidth' 'Color' 'TextColor' }; ...
%                   { 'other h-line'      '--'         1.5         'm'     'm'        } ]'}; 
% h2_line(1:sig_size, 4:7) = num2cell( [ repmat(60,sig_size,1) repmat(70,sig_size,1) repmat(0.5,sig_size,2) ] );
% 
% v_line(:,1) = {'line'};
% v_line(:,2) = { [ { 'String'             'LineStyle' 'LineWidth' 'Color' 'TextColor' }; ...
%                   { 'vertical line text' '--'         1.5         'g'     'g'        } ]'}; 
% v_line(1:sig_size, [4 5]) = num2cell( repmat(20,sig_size,2) );
% 
% v2_line(:,1) = {'line'};
% v2_line(:,2) = { [ { 'String'      'LineStyle' 'LineWidth' 'Color' 'TextColor' }; ...
%                   { 'other v-line' '--'         1.5         'b'     'b'        } ]'}; 
% v2_line(1:sig_size, 4:7) = num2cell( [ repmat(80,sig_size,2) repmat(-0.8,sig_size,1) repmat(-0.3,sig_size,1) ] );
% 
% point(:,1) = {'point'};
% point(:,2) = { [ { 'String'    'Color'       'TextColor'   }; ...
%                  { 'one-point' [0.2 0.3 0.4] [0.2 0.3 0.4] } ]'}; 
% point(1:sig_size,4) = num2cell( repmat(50,sig_size,1) );
% 
% a_line(:,1) = {'line'};                    
% a_line(:,2) = { [ { 'String'    'LineStyle' 'LineWidth' 'Color' 'TextColor' }; ...
%                   { 'line text' '--'         1.5         'k'     'k'        } ]'}; 
% a_line(1:sig_size,4:7) = num2cell( [ repmat(30,sig_size,1) repmat(40,sig_size,1) repmat(0.5,sig_size,1) repmat(-0.5,sig_size,1) ] );
%        
% aux_anns = cat(3,h_line,v_line,h2_line,v2_line,point,a_line);
% 
% plot_ecg_mosaic(mean(x_packed,3), 'ECG_annotations', aux_anns );
% 
% See also plot_ecg_strip
% 
% Author: Mariano Llamedo Soria llamedom@electron.frba.utn.edu.ar
% Last update: 19/10/2014
% Birthdate  : 16/2/2012
% Copyright 2008-2015
function [ ECG_hdl axes_hdl fig_hdl all_yranges ] = plot_ecg_mosaic( ECG, varargin )

    %% constants

    cWaveAnnotations = { 'Pon' 'P' 'Poff' 'QRSon' 'Q' 'R' 'S' 'QRSoff' 'Ton' 'T' 'Toff' };
    waveMode_idx = 1;
    lWaveAnnotations = length(cWaveAnnotations);
    
    cModesMaxYrange = {'max','min','mean','median','none'};

    % bgTextColor = [251 248 230]/255;
    ColorMinorGrid = [0.8 0.8 0.8];

    ann_typ_idx = 1;
    plot_options_str_idx = 2;
    x1_idx = 4;
    x2_idx = 5;
    y1_idx = 6;
    y2_idx = 7;
    n_cant_idx = 7;

    PwaveColor =   [210 255 189]/255;
    QRScplxColor = [255 200 255]/255;
    TwaveColor =   [255 240 170]/255;
    
    DelineationNotEditedColor = [ 0.8 0.8 0.8];
    DelineationEditedColor = [ 1 0 0 ];
    
    %% parse input

    p = inputParser;   % Create instance of inputParser class.
    p.addParamValue('ECG_header', [], @(x)(isstruct(x)) );
    p.addParamValue('QRS_locations', [], @(x)( isnumeric(x) && all(x > 0) ) );
    p.addParamValue('WinSize', [], @(x)( all(isnumeric(x)) ) );
    p.addParamValue('ECG_annotations', [], @(x)( isnumeric(x) || iscell(x) ) );
    p.addParamValue('ECG_delineation', [], @(x)(isstruct(x)) );
    p.addParamValue('MaxECGrange', [], @(x)(isnumeric(x) || ischar(x) && any(strcmpi(cModesMaxYrange, x)) ) );
    p.addParamValue('RowsCols', [], @(x)( all(isnumeric(x)) && all(x > 0) ) );
    p.addParamValue('FigureHdl', [], @(x)( ishandle(x) ) );
    p.addParamValue('AllowEdition', false, @(x)(islogical(x)) );

    try
        p.parse( varargin{:} );
    catch MyError
        fprintf(2, 'Incorrect argval/argvalue, use:\n' );
        fprintf(2, 'plot_ecg_mosaic( ECG, ''arg_name'', ''arg_value'');\n\n' );
        fprintf(2, 'Valid arg_name are:\n' );
        fprintf(2, '+ ECG_header\n' );
        fprintf(2, '+ QRS_locations\n' );
        fprintf(2, '+ ECG_annotations\n' );
        fprintf(2, '+ ECG_delineation\n' );
        fprintf(2, '+ WinSize\n' );
        fprintf(2, '+ MaxECGrange\n' );
        fprintf(2, '+ RowsCols\n' );
        fprintf(2, '+ FigureHdl\n' );
        fprintf(2, '\nOr run ''doc plot_ecg_mosaic'' for details.\n\n' );
        rethrow(MyError);    
    end

    QRS_locations = p.Results.QRS_locations;
    winSize = p.Results.WinSize;
    ECG_header = p.Results.ECG_header;
    annotations = p.Results.ECG_annotations;
    positions = p.Results.ECG_delineation;
    all_yranges = p.Results.MaxECGrange;
    rowscols = p.Results.RowsCols;
    fig_hdl = p.Results.FigureHdl;
    bAllowEdition = p.Results.AllowEdition;

    delete(p)

    if( isempty(fig_hdl) )
        fig_hdl = gcf;
    else
        figure(fig_hdl)
    end
    clf('reset')

    if( iscell(ECG) )

        [lECG, cant_sig ] = size(ECG{1});
        cant_realizations = length(ECG);

        ECG = cell2mat(reshape(ECG, 1, 1, cant_realizations));

    elseif( isnumeric(ECG) )

        if( ~isempty(QRS_locations) )
            ECG = pack_signal(ECG, QRS_locations, winSize);    
        end

        [lECG, cant_sig, cant_realizations] = size(ECG);

    end

    if( isempty(all_yranges) )
        bYrange_given = false;
        all_yranges = nan(cant_sig,2);
        rangeMode = 'none';
    else
        if(ischar(all_yranges))
            rangeMode = lower(all_yranges);
            all_yranges = nan(cant_sig,2);
            bYrange_given = false;
        else
            bYrange_given = true;
        end
    end

    % plot arrows when range was not given.
    bArrow = ~bYrange_given;

    if( isempty(ECG_header) )
        ECG_header.freq = nan;
        ECG_header.nsamp = lECG;
        ECG_header.nsig = cant_sig;
        ECG_header.desc = num2str(colvec(1:cant_sig));
        ECG_header.units = repmat('#', ECG_header.nsig , 1);
        ECG_header.gain = repmat(1, ECG_header.nsig , 1);
        ECG_header.adczero = repmat(0, ECG_header.nsig , 1);

        bGridScale = false;
    else
        if( ECG_header.nsig ~= cant_sig )
            ECG_header.nsig = cant_sig;
            ECG_header.units = repmat(ECG_header.units(1,:), ECG_header.nsig , 1);
            ECG_header.gain = repmat(ECG_header.gain(1), ECG_header.nsig , 1);
            ECG_header.adczero = repmat(ECG_header.adczero(1), ECG_header.nsig , 1);
        end
        bGridScale = true;

        [ECG ECG_header] = ADC2units(ECG, ECG_header, 'uv');
    end

    if( isempty(positions) )
        all_annotations = annotations;
    else

        if( isempty(annotations) )
            all_annotations = update_annotations_from_positions(positions);
        else
            all_annotations = cat(3, annotations, update_annotations_from_positions(positions) );
        end
        
    end

    if( isempty(all_annotations) )

        all_annotations = cell(cant_sig,1);
        anns_provided = false;

    else
        if(iscell(all_annotations))

            anns_provided = true;

            [lannotations, cant_params, cant_type_anns] = size(all_annotations);

            if(cant_params ~= n_cant_idx )
                error( 'Invalid number of params: \n\nCol1: Ann point location\nCol2: Ann line start\nCol3: Ann line end\nCol4: plot LineSpec or Prop Name/Val\nCol5: Ann legend\nCol6: Annotation type\n' );
            end

            if(lannotations == 1)
                %same ann for all signals
                all_annotations = repmat(all_annotations, cant_sig, 1);
            elseif( lannotations > 1 && lannotations < cant_sig )
                error([ 'Invalid number of annotations: ' num2str(lannotations) ' for ' num2str(cant_sig) ' signals.'  ])
            end

        else
            error('Invalid annotation format.')
        end
    end

    if( isempty(rowscols) || prod(rowscols) < cant_sig )

        prev_units = get(fig_hdl,'units');
        prev_size = get(fig_hdl,'outerposition');

        set(fig_hdl,'Visible', 'off');
        set(fig_hdl,'units','normalized');
        set(fig_hdl,'outerposition',[0 0.03 1 0.97]);
        set(fig_hdl,'units','pixels');
        screen_size = get(fig_hdl,'outerposition');

        % restore originals
        set(fig_hdl,'outerposition',prev_size);
        set(fig_hdl,'units',prev_units);
        set(fig_hdl,'Visible', 'on');

        target_aspect = screen_size(3)/screen_size(4);
        aux_val = [1:cant_sig; ceil(cant_sig./(1:cant_sig)) ] ;
        bExact = (cant_sig - prod(aux_val)) == 0;
        if( any(bExact(2:end-1)) )
            % non-trivial solution
            aux_val = aux_val(:, bExact);
        end
        aux_aspects = aux_val(1,:)./aux_val(2,:);
        [~, aux_idx] = sort(abs(aux_aspects - target_aspect));
        n_rows = aux_val(1,aux_idx(1));
        n_cols = aux_val(2,aux_idx(1));
    else
        n_rows = rowscols(1);
        n_cols = rowscols(2);
    end

    %%

    db_status = dbstatus();
    bRestoreErrorStatus = false;
    if( length(db_status) > 1 && strcmpi(db_status(end).cond, 'caught error')  )
        dbclear if caught error
        bRestoreErrorStatus = true;
    end

    ECG_hdl = [];
    axes_hdl = nan(cant_sig,1);
    anns_hdl = [];

    if( isnan(ECG_header.freq) )
        xTimeGridSpacing = round(lECG/5); % mseg
        xTimeGrid = 0:xTimeGridSpacing:lECG;
    else
        xTimeGridSpacing = 50; % mseg
        xTimeGrid = 0:(xTimeGridSpacing/1e3*ECG_header.freq):lECG;
    end


    plotXmin = 1;
    plotXmax = lECG;
    plotXrange = plotXmax - plotXmin;
    xTextOffset = 0.005*plotXrange;

    if(anns_provided)
        lineWidth = 1.3;
    else
        lineWidth = 1;
    end

    v_space = 0.02/(n_rows+1);
    h_space = 0.02/(n_cols+2);
    axe_width = 0.98/n_rows;
    axe_height = 0.98/n_cols;
    axe_x = h_space;
    axe_y = 1-axe_height-v_space;

    for ii = 1:cant_sig

        txthdl = [];

        axes_hdl(ii) = axes();

        % AUX ECG plot

        % ECG plot
        ECG_hdl = [ ECG_hdl; plot( squeeze(ECG(:,ii,:)), 'LineWidth', lineWidth )];

        if(~bYrange_given)
            all_yranges(ii,:) = rowvec(get(axes_hdl(ii), 'ylim'));
        end

        set(axes_hdl(ii), 'xlim', [1 lECG]);

        prev_units = get(axes_hdl(ii),'units');
        set(axes_hdl(ii),'units','pixels');
        axis_position = get(axes_hdl(ii),'Position');
        set(axes_hdl(ii),'units',prev_units);

        set(axes_hdl(ii), 'Box', 'off' );
        set(axes_hdl(ii), 'Xtick', [] );
        set(axes_hdl(ii), 'Ytick', [] );
        set(axes_hdl(ii), 'Xcolor', [1 1 1] );
        set(axes_hdl(ii), 'Ycolor', [1 1 1] );

        [x_loc, y_loc] = ind2sub([n_rows n_cols], ii);
        axe_x = h_space * x_loc + axe_width * (x_loc-1);
        axe_y = 1-( v_space * y_loc + axe_height * y_loc);

    %     aux_val = get(axes_hdl(ii), 'Position' );
    %     set(axes_hdl(ii), 'Position', [ aux_val(1:2) - (k_magnify-1)/2*aux_val(3:4) k_magnify*aux_val(3:4) ] );
        set(axes_hdl(ii), 'Position', [ axe_x axe_y axe_width axe_height ] );

        
    end

    max_yrange = [min(all_yranges(:,1)) max(all_yranges(:,2)) ];
    % min_range = min(all_yranges(:,2) - all_yranges(:,1));

    for ii = 1:cant_sig

        set(fig_hdl, 'CurrentAxes', axes_hdl(ii));
        hold(axes_hdl(ii), 'on');

        if(bGridScale) 
            % grid plot

            yTimeGridSpacing = (all_yranges(ii,2) - all_yranges(ii,1)) / 5; % uV

            yTimeGrid = max_yrange(1):yTimeGridSpacing:max_yrange(2);

            lyTimeGrid = length(yTimeGrid);
            if( lyTimeGrid > 10 )
                yTimeGrid = yTimeGrid( yTimeGrid >= all_yranges(ii,1) & yTimeGrid <= all_yranges(ii,2) );
            end

            aux_hdl = plot( repmat([1; lECG], 1, length(yTimeGrid)), repmat(yTimeGrid,2,1), 'Color', ColorMinorGrid, 'LineStyle', ':' );
            aux_hdl = [aux_hdl; plot( repmat(xTimeGrid,2,1), repmat(colvec(max_yrange), 1, length(xTimeGrid) ), 'Color', ColorMinorGrid, 'LineStyle', ':' ) ];

            set(aux_hdl,'ButtonDownFcn',@WindowButtonDown);            

        end

        % zero line
        aux_hdl = plot( [ xTimeGrid(1) xTimeGrid(end)], [0 0], '-k' );

        set(aux_hdl,'ButtonDownFcn',@WindowButtonDown);            
        
        hold(axes_hdl(ii), 'off');

    end

    if(~bYrange_given)
        switch(rangeMode)
            case 'max'
                all_yranges = repmat([ min(all_yranges(:,1)) max(all_yranges(:,2)) ], cant_sig, 1   );
            case 'min'
                all_yranges = repmat([ max(all_yranges(:,1)) min(all_yranges(:,2)) ], cant_sig, 1   );
            case 'mean'
                all_yranges = repmat([ mean(all_yranges(:,1)) mean(all_yranges(:,2)) ], cant_sig, 1   );
            case 'median'
                all_yranges = repmat([ median(all_yranges(:,1)) median(all_yranges(:,2)) ], cant_sig, 1   );
        end
    end


    ECG_lgd = [];
    
    for ii = 1:cant_sig
    %     aux_val = get(axes_hdl(ii), 'ylim');
    %     aux_val2 = (all_yranges - abs(diff(aux_val)))/2;
    %     set(axes_hdl(ii), 'ylim', aux_val + [-aux_val2 aux_val2] );
        set(axes_hdl(ii), 'ylim', all_yranges(ii,:) );

        set(fig_hdl, 'CurrentAxes', axes_hdl(ii));
        y_lims = get(axes_hdl(ii), 'ylim');
        x_lims = get(axes_hdl(ii), 'xlim');

        if( ii <= size(ECG_header.desc,1) )
            ECG_lgd = [ECG_lgd; text(x_lims(1) + 0.01*abs(diff(x_lims)), y_lims(2) - 0.05*abs(diff(y_lims)), ECG_header.desc(ii,:), 'EdgeColor', [0 0 0] )];
        else
            ECG_lgd = [ECG_lgd; text(x_lims(1) + 0.01*abs(diff(x_lims)), y_lims(2) - 0.05*abs(diff(y_lims)), ['Sig ' num2str(ii)], 'EdgeColor', [0 0 0] )];
        end

        plotXmin = x_lims(1);
        plotXmax = x_lims(2);
        plotXrange = plotXmax - plotXmin;
        plotYmin = y_lims(1);
        plotYmax = y_lims(2);
        plotYrange = plotYmax - plotYmin;
        yTextOffset = 0.01*plotYrange;

        yTimeGridSpacing = (all_yranges(ii,2) - all_yranges(ii,1)) / 5; % uV
        yTimeGrid = max_yrange(1):yTimeGridSpacing:max_yrange(2);

        aux_idx = find(yTimeGrid > plotYmin & yTimeGrid < plotYmax);

        width_legend = 0.18*plotXrange;
        height_legend = 0.1*plotYrange;
        left_legend = plotXmax - width_legend - 5*xTextOffset;
        bottom_legend = plotYmax - height_legend - 2*yTextOffset;

        % scale X
    %         plot( [-xTimeGridSpacing/2 -xTimeGridSpacing/2 xTimeGridSpacing/2 xTimeGridSpacing/2] + 5/7*lECG, plotYmin + 0.05*plotYrange + [yTextOffset 0 0 yTextOffset], 'Color', [0 0 0], 'LineWidth', 1 );
        if( bArrow )
            ECG_lgd = [ECG_lgd; arrow( [ xTimeGrid(2) plotYmin + 0.05*plotYrange], [ xTimeGrid(3) plotYmin + 0.05*plotYrange], 2, 0.5, [0 0 0], axes_hdl(ii) )];
        end

        if( isnan(ECG_header.freq) )
            aux_str =  [ num2str(xTimeGridSpacing) ' #' ];
        else
            aux_str =  [ num2str(xTimeGridSpacing) ' ms' ];
        end

        ECG_lgd = [ECG_lgd; text( mean(xTimeGrid(2:3)),  plotYmin + 0.05*plotYrange + 5*yTextOffset, aux_str, 'FontSize', 8, 'HorizontalAlignment', 'center') ];

        % scale Y
    %         plot( [ -xTextOffset 0 0 -xTextOffset] + 0.95*lECG, plotYmin + 5/7*plotYrange + [-yTimeGridSpacing/2 -yTimeGridSpacing/2 yTimeGridSpacing/2 yTimeGridSpacing/2], 'Color', [0 0 0], 'LineWidth', 1 );
        if( bArrow )
            ECG_lgd = [ECG_lgd; arrow( [0.95*lECG - xTextOffset; yTimeGrid(aux_idx(2))], [0.95*lECG - xTextOffset; yTimeGrid(aux_idx(3))], 2, 0.5, [0 0 0], axes_hdl(ii) )];
        end

        ECG_lgd = [ECG_lgd; text( 0.95*lECG - 10*xTextOffset, mean(yTimeGrid(aux_idx(2:3))), [ num2str(yTimeGridSpacing) ' ' ECG_header.units(ii,:) ], 'FontSize', 8, 'HorizontalAlignment', 'center', 'Rotation', 90)];

        txthdl = [];

        if( ~isempty(all_annotations{ii}) )

            update_annotations( ii )

        end

        if ~isempty(positions)
            ECG_lgd = [ ECG_lgd; patch([left_legend left_legend [left_legend left_legend]+width_legend left_legend ], [bottom_legend [bottom_legend bottom_legend]+height_legend bottom_legend bottom_legend], [1 1 1], 'EdgeColor', [0 0 0])];
            ECG_lgd = [ ECG_lgd; text( left_legend + width_legend/4, bottom_legend + height_legend/2, 'P', 'FontSize', 8, 'HorizontalAlignment', 'center', 'BackgroundColor', PwaveColor) ];
            ECG_lgd = [ ECG_lgd; text( left_legend + width_legend/2, bottom_legend + height_legend/2, 'QRS', 'FontSize', 8, 'HorizontalAlignment', 'center', 'BackgroundColor', QRScplxColor ) ];
            ECG_lgd = [ ECG_lgd; text( left_legend + width_legend*3/4, bottom_legend + height_legend/2, 'T', 'FontSize', 8, 'HorizontalAlignment', 'center', 'BackgroundColor', TwaveColor ) ];
        end
        
    end

    if(bRestoreErrorStatus)
        dbstop if caught error
    end
    
    my_timer = timer('TimerFcn',@timer_fcn, 'StopFcn', @timer_stop_fcn , 'StartDelay', 10);

    set(fig_hdl, ...
        'WindowScrollWheelFcn', {@ScrollWheel}, ...
        'WindowKeyPressFcn', {@KeyPress}, ...
        'WindowButtonUpFcn', {@WindowButtonUp} ...
        );            

    set(axes_hdl,...
        'ButtonDownFcn', {@WindowButtonDown} ...
        );            


    set(ECG_hdl,...
        'ButtonDownFcn', {@WindowButtonDown} ...
        );            

    if( isempty(positions) )
        for ii = 1:lWaveAnnotations
            manual_edited_position.(cWaveAnnotations{ii}) = nan;
        end
        manual_edited_position = repmat(manual_edited_position, ECG_header.nsig,1);
    else
        manual_edited_position = positions;
    end

    PrevStateWindowButtonMotionFcn = nan;
    bIsDragAllowed = false;
    lead_move_idx = [];
    axes_move = [];
    move_hdl = [];
    sample_move = [];
    bFixedWave = false;
    bPreserveFix = false;
    manual_edited_position_matrix = positions2matrix(manual_edited_position, cWaveAnnotations);
    bDelineationEdited = false;
    
    if( nargout == 0 )
        ECG_hdl = [];
    end
    
%% Internal functions    

    function timer_stop_fcn(obj,event_obj)
         
        if(bPreserveFix)
            % never stop when editing
            start(my_timer)
        end
        
    end

    function timer_fcn(obj,event_obj)
        
        delete(findobj('Tag', 'title_efimero' ));

        if(~bPreserveFix)
            % allow edition of the closer wave
            bFixedWave = false;
        end
        
    end

    function this_annotations = update_annotations_from_positions( this_positions )
        
        [min_vals_pw_x, min_vals_pw_y, max_vals_pw_x, max_vals_pw_y]     = CalcMinMax( this_positions, {'Pon' 'P' 'Poff'} );
        [min_vals_qrs_x, min_vals_qrs_y, max_vals_qrs_x, max_vals_qrs_y] = CalcMinMax( this_positions, {'QRSon' 'qrs' 'QRSoff'} );
        [min_vals_tw_x, min_vals_tw_y, max_vals_tw_x, max_vals_tw_y]     = CalcMinMax( this_positions, {'Ton' 'T' 'Toff'} );

        Pwave = cell(cant_sig,7);
        Pwave_max = cell(cant_sig,7);
        QRScplx = cell(cant_sig,7);
        Twave = cell(cant_sig,7);
        QRScplx_point = cell(cant_sig,7);
        Qwave = cell(cant_sig,7);
        Rwave = cell(cant_sig,7);
        Swave = cell(cant_sig,7);
        Twave_max = cell(cant_sig,7);

        Pwave(:,1) = {'patch'};
        Pwave(:,2) = { [ { 'FaceColor' }; ...   
                         { PwaveColor  } ]'}; 
        Pwave(:,[x1_idx y1_idx x2_idx y2_idx]) = [ num2cell(min_vals_pw_x), num2cell(min_vals_pw_y), num2cell(max_vals_pw_x), num2cell(max_vals_pw_y)];

        k_point_color = 0.9;
        
        Pwave_max(:,1) = {'point'};
        Pwave_max(:,2) = { [ { 'String' 'Marker' 'MarkerSize' 'Color' }; ...
                         {     'P'      'd'       5            k_point_color*PwaveColor    } ]'}; 
        Pwave_max(:,4) = {this_positions(:).P};
        
        QRScplx(:,1) = {'patch'};
        QRScplx(:,2) = { [ { 'FaceColor' }; ...   
                         { QRScplxColor  } ]'}; 
        QRScplx(:,[x1_idx y1_idx x2_idx y2_idx]) = [ num2cell(min_vals_qrs_x), num2cell(min_vals_qrs_y), num2cell(max_vals_qrs_x), num2cell(max_vals_qrs_y)];

%         QRScplx_point(:,1) = {'point'};
%         QRScplx_point(:,2) = { [ { 'String' 'Marker' 'MarkerSize' 'Color' }; ...
%                          {          'qrs'      'd'       5            k_point_color*QRScplxColor    } ]'}; 
%         QRScplx_point(:,4) = {this_positions(:).qrs};
        QRScplx_point = [];
        
        Qwave(:,1) = {'point'};
        Qwave(:,2) = { [ { 'String' 'Marker' 'MarkerSize' 'Color' }; ...
                         { 'Q'      'd'       5            k_point_color*QRScplxColor    } ]'}; 
        Qwave(:,4) = {this_positions(:).Q};
        
        Rwave(:,1) = {'point'};
        Rwave(:,2) = { [ { 'String' 'Marker' 'MarkerSize' 'Color' }; ...
                         { 'R'      'd'       5            k_point_color*QRScplxColor    } ]'}; 
        Rwave(:,4) = {this_positions(:).R};
        
        Swave(:,1) = {'point'};
        Swave(:,2) = { [ { 'String' 'Marker' 'MarkerSize' 'Color' }; ...
                         { 'S'      'd'       5            k_point_color*QRScplxColor    } ]'}; 
        Swave(:,4) = {this_positions(:).S};
        
        Twave(:,1) = {'patch'};
        Twave(:,2) = { [ { 'FaceColor' }; ...   
                         { TwaveColor  } ]'}; 
        Twave(:,[x1_idx y1_idx x2_idx y2_idx]) = [ num2cell(min_vals_tw_x), num2cell(min_vals_tw_y), num2cell(max_vals_tw_x), num2cell(max_vals_tw_y)];

        Twave_max(:,1) = {'point'};
        Twave_max(:,2) = { [ { 'String' 'Marker' 'MarkerSize' 'Color' }; ...
                         {     'T'      'd'       5            k_point_color*TwaveColor    } ]'}; 
        Twave_max(:,4) = {this_positions(:).T};
        
        this_annotations = cat(3, Pwave_max, QRScplx_point, Qwave, Rwave, Swave, Twave_max, Pwave, QRScplx, Twave);
        
    end
    
    function update_annotations( lead_idx )
        
        x_lims = get(axes_hdl(lead_idx), 'xlim');
        x_range = abs(diff(x_lims));
        y_lims = all_yranges(lead_idx,:);
        y_range = abs(diff(y_lims));

        for jj = 1:cant_type_anns

            switch( all_annotations{lead_idx,ann_typ_idx,jj} )

                case 'point'

                    if( ~isnan(all_annotations{lead_idx,x1_idx,jj}) )

                        aux_hdl = text_arrow(all_annotations{lead_idx,x1_idx,jj}, ECG(all_annotations{lead_idx,x1_idx,jj}, lead_idx), '', all_annotations{lead_idx,plot_options_str_idx,jj}, axes_hdl(lead_idx) );

                        set(aux_hdl, 'Tag', num2str(lead_idx) );
                        
                        txthdl = [ txthdl aux_hdl ];

                        uistack(aux_hdl,'bottom');

                        if(bAllowEdition)
                            set(aux_hdl,...
                                'ButtonDownFcn', {@WindowButtonDown} ...
                                );            
                        end

%                         aux_hdl = eval( [ 'plot( all_annotations{' num2str(lead_idx) ',' num2str(x1_idx) ',' num2str(jj) '}, ECG(all_annotations{' num2str(lead_idx) ',' num2str(x1_idx) ',' num2str(jj) '},' num2str(lead_idx) ',1)  ' all_annotations{lead_idx,plot_options_str_idx,jj} ')']);
%                         anns_hdl = [ anns_hdl; colvec(aux_hdl)];
%                         txthdl = [ txthdl; text( all_annotations{lead_idx,x1_idx,jj} + 0.03*x_range, ECG(all_annotations{lead_idx,x1_idx,jj}, lead_idx, 1), all_annotations{lead_idx,text_idx,jj}, 'BackgroundColor', bgTextColor )];
                    end

                case 'line'

                    if( isempty(all_annotations{lead_idx,x1_idx,jj}) )
                        all_annotations{lead_idx,x1_idx,jj} = repmat(x_lims(1),1,length(all_annotations{lead_idx,y1_idx,jj}));
                    end
                    if( isempty(all_annotations{lead_idx,x2_idx,jj}) )
                        all_annotations{lead_idx,x2_idx,jj} = repmat(x_lims(2),1,length(all_annotations{lead_idx,y1_idx,jj}));
                    end

                    if(cant_realizations > 1)
                        if( isempty(all_annotations{lead_idx,y1_idx,jj}) )
                            all_annotations{lead_idx,y1_idx,jj} = min(squeeze(ECG(all_annotations{lead_idx,x1_idx,jj},lead_idx,:)),[],2);
                        end
                        if( isempty(all_annotations{lead_idx,y2_idx,jj}) )
                            all_annotations{lead_idx,y2_idx,jj} = max(squeeze(ECG(all_annotations{lead_idx,x1_idx,jj},lead_idx,:)),[],2);
                        end
                    else
                        if( isempty(all_annotations{lead_idx,y1_idx,jj}) )
                            all_annotations{lead_idx,y1_idx,jj} = repmat(min(ECG(:,lead_idx)),1,length(all_annotations{lead_idx,x1_idx,jj}));
                        end
                        if( isempty(all_annotations{lead_idx,y2_idx,jj}) )
                            all_annotations{lead_idx,y2_idx,jj} = repmat(max(ECG(:,lead_idx)),1,length(all_annotations{lead_idx,x1_idx,jj}));
                        end
                    end

                    if( ~isempty(cell2mat(all_annotations(lead_idx,4:7,jj)))   )

                        aux_hdl = text_line(cell2mat(all_annotations(lead_idx,[x1_idx x2_idx],jj)), cell2mat(all_annotations(lead_idx,[y1_idx y2_idx],jj)), '', all_annotations{lead_idx,plot_options_str_idx,jj}, axes_hdl(lead_idx) );

                        set(aux_hdl, 'Tag', num2str(lead_idx) );
                        
                        txthdl = [ txthdl aux_hdl ];

                        for kk = aux_hdl
                            uistack(kk,'bottom');
                            if(bAllowEdition)
                                set(kk,...
                                    'ButtonDownFcn', {@WindowButtonDown} ...
                                    );            
                            end
                        end                        
%                         aux_hdl = eval( [ 'plot( cell2mat(all_annotations(' num2str(lead_idx) ', [' num2str(x1_idx) ' ' num2str(x2_idx) '],' num2str(jj) ')), cell2mat(all_annotations(' num2str(lead_idx) ', [' num2str(y1_idx) ' ' num2str(y2_idx) '],' num2str(jj) '))'  all_annotations{lead_idx,plot_options_str_idx,jj} ')']);
%                         anns_hdl = [ anns_hdl; colvec(aux_hdl)];
%                         if( ~strcmpi('', all_annotations{lead_idx,text_idx,jj}) )
%                             txthdl = [ txthdl; text(all_annotations{lead_idx,x1_idx,jj} + 0.03*x_range, all_annotations{lead_idx,y1_idx,jj} + 0.03*y_range, all_annotations{lead_idx,text_idx,jj}, 'VerticalAlignment', 'bottom','BackgroundColor', bgTextColor )];
% %                             set(txthdl(end), 'Rotation', round(180/pi*atan2( (all_annotations{lead_idx,y2_idx,jj} - all_annotations{lead_idx,y1_idx,jj}) * axis_position(4) / y_range , (all_annotations{lead_idx,x2_idx,jj} - all_annotations{lead_idx,x1_idx,jj}) * axis_position(3) / x_range )) );
% %                             set(txthdl(end), 'Rotation', 90 );
%                         end                    
                    end

                case 'patch'

                    if( isempty(all_annotations{lead_idx,x1_idx,jj}) )
                        all_annotations{lead_idx,x1_idx,jj} = repmat(x_lims(1),1,length(all_annotations{lead_idx,y1_idx,jj}));
                    end
                    if( isempty(all_annotations{lead_idx,x2_idx,jj}) )
                        all_annotations{lead_idx,x2_idx,jj} = repmat(x_lims(2),1,length(all_annotations{lead_idx,y1_idx,jj}));
                    end

                    if(cant_realizations > 1)
                        if( isempty(all_annotations{lead_idx,y1_idx,jj}) )
                            all_annotations{lead_idx,y1_idx,jj} = min(squeeze(ECG(all_annotations{lead_idx,x1_idx,jj},lead_idx,:)),[],2);
                        end
                        if( isempty(all_annotations{lead_idx,y2_idx,jj}) )
                            all_annotations{lead_idx,y2_idx,jj} = max(squeeze(ECG(all_annotations{lead_idx,x1_idx,jj},lead_idx,:)),[],2);
                        end
                    else
                        if( isempty(all_annotations{lead_idx,y1_idx,jj}) )
                            all_annotations{lead_idx,y1_idx,jj} = repmat(min(ECG(:,lead_idx)),1,length(all_annotations{lead_idx,x1_idx,jj}));
                        end
                        if( isempty(all_annotations{lead_idx,y2_idx,jj}) )
                            all_annotations{lead_idx,y2_idx,jj} = repmat(max(ECG(:,lead_idx)),1,length(all_annotations{lead_idx,x1_idx,jj}));
                        end
                    end                    

                    if( ~isempty(cell2mat(all_annotations(lead_idx,4:7,jj)))   )

                        aux_hdl = patch( [all_annotations{lead_idx,x1_idx,jj} all_annotations{lead_idx,x1_idx,jj} all_annotations{lead_idx,x2_idx,jj} all_annotations{lead_idx,x2_idx,jj} ], [ all_annotations{lead_idx,y1_idx,jj} all_annotations{lead_idx,y2_idx,jj} all_annotations{lead_idx,y2_idx,jj} all_annotations{lead_idx,y1_idx,jj} ], [1 1 1], 'EdgeColor', 'none');
                        aux_prop_vals = all_annotations{lead_idx,plot_options_str_idx,jj};
                        set( aux_hdl, aux_prop_vals(:,1)', aux_prop_vals(:,2)' );

                        set(aux_hdl, 'Tag', num2str(lead_idx) );
                        
                        if(bAllowEdition)
                            set(aux_hdl,...
                                'ButtonDownFcn', {@WindowButtonDown} ...
                                );            
                            
                        end
                        
                        txthdl = [ txthdl aux_hdl ];

                        uistack(aux_hdl,'bottom');

                    end                    

            end

        end
        
        
    end
    
    function ScrollWheel(obj,event_obj)

        if( ~bAllowEdition )
            return
        end
        
        if (event_obj.VerticalScrollCount > 0)
            waveMode_idx = waveMode_idx + 1;
            if(waveMode_idx > lWaveAnnotations)
                waveMode_idx = 1;
            end
        else
            waveMode_idx = waveMode_idx - 1;
            if(waveMode_idx < 1)
                waveMode_idx = lWaveAnnotations;
            end
        end
        
        bFixedWave = true;
        
        update_title_efimero( cWaveAnnotations{waveMode_idx}, 10 );
        
    end

    function KeyPress(obj,event_obj)

        if(strcmp(event_obj.Key,'e'))
            bAllowEdition = ~bAllowEdition;
            if(bAllowEdition)
                update_title_efimero( 'Edit mode ON', 2 )
                set(ECG_lgd, 'visible', 'off')
            else
                update_title_efimero( 'Edit mode OFF', 2 )
                set(ECG_lgd, 'visible', 'on')
            end
            
        elseif (strcmp(event_obj.Key,'s'))
            
            if( bDelineationEdited )
                % store manual_edited_position
                assignin('caller', 'manual_edited_position', manual_edited_position)
                fprintf(1, '[%s] Edited positions stored in caller workspace.\n', datestr(now) );
                set( fig_hdl, 'Color', DelineationNotEditedColor )                
            else
                fprintf(2, '[%s] No changes made, edit delineation before saving.\n', datestr(now) );
            end
            
        end

    end

    function [min_vals_x, min_vals_y, max_vals_x, max_vals_y] = CalcMinMax( this_annotation, field_names )

        if( isfield(this_annotation, field_names{1} ) )
            aux_on = cell2mat({this_annotation(:).(field_names{1})});
        else
            aux_on = [];
        end

        if( isfield(this_annotation, field_names{2} ) )
            aux_peak = cell2mat({this_annotation(:).(field_names{2})});
        else
            aux_peak = [];
        end

        if( isfield(this_annotation, field_names{3} ) )
            aux_off = cell2mat({this_annotation(:).(field_names{3})});
        else
            aux_off = [];
        end

        start_sample = 1;

        % wave start
        bOn = ~isnan(aux_on) & aux_on >= start_sample & aux_on <= start_sample+lECG;
        % wave end
        bOff = ~isnan(aux_off) & aux_off >= start_sample & aux_off <= start_sample+lECG;

        % wave peak
        bPeak = ~isnan(aux_peak) & aux_peak >= start_sample & aux_peak <= start_sample+lECG;

        % wave conection between start-end
        bOnOff = bOn & bOff;
        aux_complete_idx = find(bOnOff);

        aux_complete_idxx = num2cell(nan(ECG_header.nsig,1));
        % normal sampled version
        aux_complete_idxx(aux_complete_idx) = arrayfun( @(a)( max(1, aux_on(a)):min(lECG,aux_off(a)) ),aux_complete_idx, 'UniformOutput', false);
        if( any(~bOnOff & bOn & bPeak) )
            % on-peak
            aux_complete_idx = find( ~bOnOff & bOn & bPeak);
            aux_complete_idxx(aux_complete_idx) = arrayfun( @(a)( aux_on(a):aux_peak(a) ),aux_complete_idx, 'UniformOutput', false);
        end

        if( any(~bOnOff & bOff & bPeak) )
            % peak-off
            aux_complete_idx = find(~bOnOff & bPeak & bOff);
            aux_complete_idxx(aux_complete_idx) = arrayfun( @(a)( aux_peak(a):aux_off(a) ),aux_complete_idx, 'UniformOutput', false);
        end         

        max_vals_x = cellfun( @(a,lead)( a(end) ), aux_complete_idxx);
        max_vals_y = cellfun( @(a,lead)( max(dummyfun(ECG,a, lead))), aux_complete_idxx, num2cell((1:ECG_header.nsig)'));
        min_vals_x = cellfun( @(a,lead)( a(1) ), aux_complete_idxx);
        min_vals_y = cellfun( @(a,lead)( min(dummyfun(ECG,a, lead))), aux_complete_idxx, num2cell((1:ECG_header.nsig)'));

    end

    function fun_val = dummyfun(a,b,c)
        
        fun_val = nan;
        if( ~any(isnan(b)) && ~any(isnan(c)) )
            fun_val = a(b,c);
        end
        
    end

    function [lead_idx, obj ] = get_lead_idx(obj)
       
        lead_idx = find(obj == axes_hdl);
        
        if( isempty(lead_idx) )
            %click on the signal
            obj = get(obj, 'Parent');            
            lead_idx = find(obj == axes_hdl);
        end
        
    end

    function WindowButtonMotion(obj,event_obj)
        
        if (bIsDragAllowed)
        
            point = get(axes_move,'CurrentPoint');

            sample_move = round(point(1));

            sample_move = min( lECG, max(1, round(sample_move) ) );

            if( ~isempty(move_hdl) )
                delete(move_hdl)
            end

            move_hdl = plot(axes_move, sample_move, ECG(sample_move, lead_move_idx), '+r', 'MarkerSize', 8 );

        else
            set(fig_hdl, 'WindowButtonMotionFcn', PrevStateWindowButtonMotionFcn );
        end
    end

    function WindowButtonUp(obj,event_obj)
        
        if (bIsDragAllowed)

            bIsDragAllowed = false;
            bPreserveFix = false;
            
            set(fig_hdl, 'WindowButtonMotionFcn', PrevStateWindowButtonMotionFcn );
            
            hold(axes_move, 'off' )
            
            if( ~isempty(move_hdl) )
                delete(move_hdl)
                move_hdl = [];
            end
            
            manual_edited_position(lead_move_idx).((cWaveAnnotations{waveMode_idx})) = sample_move;
            
            aux_mat = manual_edited_position_matrix{lead_move_idx};
            aux_mat(waveMode_idx) = sample_move;
            manual_edited_position_matrix{lead_move_idx} = aux_mat;
            
            if( isempty(annotations) )
                all_annotations = update_annotations_from_positions(manual_edited_position);
            else
                all_annotations = cat(3, annotations, update_annotations_from_positions(manual_edited_position) );
            end
            
            delete(findobj('Tag', num2str(lead_move_idx) ))
            
            update_annotations( lead_move_idx )
            
            lead_move_idx = [];
            bDelineationEdited = true;
            set( fig_hdl, 'Color', DelineationEditedColor )                
            
        end
        
    end

    function WindowButtonDown(obj,event_obj)

        if( ~bAllowEdition )
            return
        end
        
        [lead_idx, obj] = get_lead_idx(obj);
        
        if (strcmp(get(fig_hdl,'SelectionType'),'alt'))
            % Delete annotation
            
            point = get(obj,'CurrentPoint');

            sample = round(point(1));

            if( ~bFixedWave )
                [~, waveMode_idx] = sort(abs(manual_edited_position_matrix{lead_idx} - sample));
                waveMode_idx = waveMode_idx(1);
            end
            
            manual_edited_position(lead_idx).((cWaveAnnotations{waveMode_idx})) = nan;
            
            aux_mat = manual_edited_position_matrix{lead_idx};
            aux_mat(waveMode_idx) = nan;
            manual_edited_position_matrix{lead_idx} = aux_mat;
            
            if( isempty(annotations) )
                all_annotations = update_annotations_from_positions(manual_edited_position);
            else
                all_annotations = cat(3, annotations, update_annotations_from_positions(manual_edited_position) );
            end
            
            delete(findobj('Tag', num2str(lead_idx) ))
            
            update_annotations( lead_idx )            

        elseif( strcmp(get(fig_hdl,'SelectionType'),'extend') )

            point = get(obj,'CurrentPoint');

            sample = round(point(1));

            if( bFixedWave )
                bPreserveFix = true;
            else
                [~, waveMode_idx] = sort(abs(manual_edited_position_matrix{lead_idx} - sample));
                
                if( sample < manual_edited_position(lead_idx).((cWaveAnnotations{waveMode_idx(1)})) )
                    waveMode_idx = max(1, waveMode_idx(1) - 1);
                elseif( sample == manual_edited_position(lead_idx).((cWaveAnnotations{waveMode_idx(1)})) )
                    waveMode_idx = waveMode_idx(1);
                else
                    waveMode_idx = min( lWaveAnnotations, waveMode_idx(1) + 1);
                end
                
            end            

            manual_edited_position(lead_idx).((cWaveAnnotations{waveMode_idx})) = sample;
            
            aux_mat = manual_edited_position_matrix{lead_idx};
            aux_mat(waveMode_idx) = sample;
            manual_edited_position_matrix{lead_idx} = aux_mat;
            
            if( isempty(annotations) )
                all_annotations = update_annotations_from_positions(manual_edited_position);
            else
                all_annotations = cat(3, annotations, update_annotations_from_positions(manual_edited_position) );
            end
            
            delete(findobj('Tag', num2str(lead_idx) ))
            
            update_annotations( lead_idx )
            
            bDelineationEdited = true;
            set( fig_hdl, 'Color', DelineationEditedColor )     
            
            
        elseif (strcmp(get(fig_hdl,'SelectionType'),'normal'))

            if (~bIsDragAllowed)

                axes_move = obj;
                lead_move_idx = lead_idx;
                bIsDragAllowed = true;

                point = get(axes_move,'CurrentPoint');

                sample = round(point(1));

                if( bFixedWave )
                    bPreserveFix = true;
                else
                    [~, waveMode_idx] = sort(abs(manual_edited_position_matrix{lead_move_idx} - sample));
                    waveMode_idx = waveMode_idx(1);
                end            
                
                sample_move = sample;
                
                PrevStateWindowButtonMotionFcn = get(fig_hdl, 'WindowButtonMotionFcn');
                set(fig_hdl, 'WindowButtonMotionFcn', @WindowButtonMotion);

                hold(axes_move, 'on' )
                
            end
                
        end

    end

    function update_title_efimero( strTitle, delay )
       
        delete(findobj('Tag', 'title_efimero' ))
        
        for hdl_idx = rowvec(axes_hdl) 
        
            set(fig_hdl, 'CurrentAxes', hdl_idx);

            y_lims = get(hdl_idx, 'ylim');
            x_lims = get(hdl_idx, 'xlim');

            plotXmin = x_lims(1);
            plotXmax = x_lims(2);
            plotXrange = plotXmax - plotXmin;
            plotYmin = y_lims(1);
            plotYmax = y_lims(2);
            plotYrange = plotYmax - plotYmin;
            yTextOffset = 0.01*plotYrange;

            width_legend = 0.2*plotXrange;
            height_legend = 0.1*plotYrange;
            left_legend = plotXmax - width_legend - 5*xTextOffset;
            bottom_legend = plotYmin;

            aux_hdl = text( left_legend + width_legend/2, bottom_legend + height_legend/2, strTitle, 'FontSize', 8, 'HorizontalAlignment', 'center', 'BackgroundColor', 'r' );

            set(aux_hdl, 'Tag', 'title_efimero')
            
        end
        
        if( ~isinf(delay) && strcmpi(my_timer.Running, 'off') )
            my_timer.StartDelay = delay;
            start(my_timer)
        end
        
    end


end