ECG-Kit 1.0

File: <base>/common/a2hbc/scripts/ExpertUserInterface.m (14,009 bytes)
function [ Label bRefresh bCancel ] = ExpertUserInterface(cCentroid, cCloserExamples, cDistantExamples)

Ventricular_ptr = @(a,b)(ChooseLabel(a,b,'Ventricular'));
Normal_ptr = @(a,b)(ChooseLabel(a,b,'Normal'));
Supraventricular_ptr = @(a,b)(ChooseLabel(a,b,'Supraventricular'));
Unknown_ptr = @(a,b)(ChooseLabel(a,b,'Unknown'));

% open a new figure
fig_hnd = figure();

set(fig_hnd, 'Tag', 'a2hbc' );
screen_size = get(0,'ScreenSize');
set(fig_hnd, 'Name', 'Expert interface' );
set(fig_hnd, 'position', [10 screen_size(4)*0.43 screen_size(3)*0.97 screen_size(4)*0.5] );

%no expert opinion
user_data.Label = [];
user_data.Refresh = false;
user_data.Cancel = false;

%% Plots
CentroidPanel = uipanel(    'Title', [ 'Centroid heartbeat. Total of ' num2str(cCentroid{7}) ' heartbeats in this cluster.' ], ... 
                            'FontSize',12,...
                            'Position', [0.0011    0.0177    0.3146    0.9693]);

ECG_centroid_hdl = axes('Parent', CentroidPanel);
set(ECG_centroid_hdl, 'units','normalized' );
set(ECG_centroid_hdl, 'position', [0.08    0.48    0.9096    0.4638] )

RR_centroid_hdl = axes('Parent', CentroidPanel);
set(RR_centroid_hdl, 'units','normalized' );
set(RR_centroid_hdl, 'position', [0.08    0.045    0.36    0.35] )

Morph_centroid_hdl = axes('Parent', CentroidPanel);
set(Morph_centroid_hdl, 'units','normalized' );
set(Morph_centroid_hdl, 'position', [0.44    0.045    0.5402    0.35] )


CloserPanel = uipanel(    'Title', [ 'Closer heartbeats. Showing  ' num2str(length(cCloserExamples{1})) ' heartbeats.' ], ... 
                            'FontSize',12,...
                            'Position', [0.3171    0.0177    0.3146    0.9693]);

ECG_closer_hdl = axes('Parent', CloserPanel);
set(ECG_closer_hdl, 'units','normalized' );
set(ECG_closer_hdl, 'position', [0.08    0.48    0.9096    0.4638] )

RR_closer_hdl = axes('Parent', CloserPanel);
set(RR_closer_hdl, 'units','normalized' );
set(RR_closer_hdl, 'position', [0.08    0.045    0.36    0.35] )

Morph_closer_hdl = axes('Parent', CloserPanel);
set(Morph_closer_hdl, 'units','normalized' );
set(Morph_closer_hdl, 'position', [0.44    0.045    0.5402    0.35] )

DistantPanel = uipanel(    'Title',[ 'Distant heartbeats. Showing  ' num2str(length(cDistantExamples{1})) ' heartbeats.' ], ... 
                            'FontSize',12,...
                            'Position', [0.6336    0.0177    0.3146    0.9693]);

ECG_distant_hdl = axes('Parent', DistantPanel);
set(ECG_distant_hdl, 'units','normalized' );
set(ECG_distant_hdl, 'position', [0.08    0.48    0.9096    0.4638] )

RR_distant_hdl = axes('Parent', DistantPanel);
set(RR_distant_hdl, 'units','normalized' );
set(RR_distant_hdl, 'position', [0.08    0.045    0.36    0.35] )

Morph_distant_hdl = axes('Parent', DistantPanel);
set(Morph_distant_hdl, 'units','normalized' );
set(Morph_distant_hdl, 'position', [0.44    0.045    0.5402    0.35] )

%% Buttons

ControlPanel = uipanel( 'Position', [0.9503    0.0177    0.0485    0.9480]);
                      
uicontrol('style','pushbutton', ...
          'Parent', ControlPanel, ...
          'string', 'Ventricular', ...
          'FontName','Arial', ...
          'FontSize',10, ...
          'FontWeight','Bold', ...
          'ForegroundColor',[1 0 0], ...
          'units','normalized', ...
          'position', [ 0.05    0.7119    0.9    0.0500 ], ...
          'callback', Ventricular_ptr );

uicontrol('style','pushbutton', ...
          'Parent', ControlPanel, ...
          'string', 'Supraventricular', ...
          'FontName','Arial', ...
          'FontSize',10, ...
          'FontWeight','Bold', ...
          'ForegroundColor',[0 0.5 0], ...
          'units','normalized', ...
          'position', [ 0.05    0.7843    0.9    0.0500 ], ...
          'callback', Supraventricular_ptr);

uicontrol('style','pushbutton', ...
          'Parent', ControlPanel, ...
          'string', 'Normal', ...
          'FontName','Arial', ...
          'FontSize',10, ...
          'FontWeight','Bold', ...
          'ForegroundColor',[0 0 1], ...
          'units','normalized', ...
          'position', [ 0.05    0.8586    0.9    0.0500 ], ...
          'callback', Normal_ptr);

uicontrol('style','pushbutton', ...
          'Parent', ControlPanel, ...
          'string', 'Unknown', ...
          'FontName','Arial', ...
          'FontSize',10, ...
          'FontWeight','Bold', ...
          'ForegroundColor',[1 1 1], ...
          'units','normalized', ...
          'position', [ 0.05    0.64    0.9    0.0500 ], ...
          'callback', Unknown_ptr);

uicontrol('style','pushbutton', ...
          'Parent', ControlPanel, ...
          'string', 'Skip', ...
          'FontName','Arial', ...
          'FontSize',10, ...
          'FontWeight','Bold', ...
          'ForegroundColor',[0 0 1], ...
          'units','normalized', ...
          'position', [ 0.05    0.5    0.9    0.0500 ], ...
          'callback', @SkipCluster);

uicontrol('style','pushbutton', ...
          'Parent', ControlPanel, ...
          'string', 'Refresh', ...
          'FontName','Arial', ...
          'FontSize',10, ...
          'FontWeight','Bold', ...
          'ForegroundColor',[0 0 1], ...
          'units','normalized', ...
          'position', [ 0.05    0.43    0.9    0.0500 ], ...
          'callback',@RefreshExamples);

uicontrol('style','pushbutton', ...
          'Parent', ControlPanel, ...
          'string', 'Cancel', ...
          'FontName','Arial', ...
          'FontSize',10, ...
          'FontWeight','Bold', ...
          'ForegroundColor',[1 0 0], ...
          'units','normalized', ...
          'position', [ 0.05    0.05    0.9    0.0500 ], ...
          'callback',@CancelButton);

      
%% plot data

set(fig_hnd,'ToolBar','figure');
    
%plot signals

% cCloserExamples = { aux_rel_posQRS ... %relative position of the heartbeat
%                     aux_ECGslices ... % ecg excerpt
%                     aux_rel_posRR ... % relative position of the heartbeat 
%                     aux_RRslices ... % RR interval sequence
%                     };
% cCentroid, cCloserExamples, cDistantExamples

box(ECG_closer_hdl, 'off');
box(RR_closer_hdl, 'off');
box(ECG_distant_hdl, 'off');
box(RR_distant_hdl, 'off');

%% Centroid heartbeat

plot( ECG_centroid_hdl,  cCentroid{2} );
hold(ECG_centroid_hdl, 'on');
plot( ECG_centroid_hdl,  [ cCentroid{1} cCentroid{1}], [ min(min(cCentroid{2})) max(max(cCentroid{2}))], '--r' );
hold(ECG_centroid_hdl, 'off');
TightAxes(ECG_centroid_hdl);
TimeRes = 0.4;
TimeGrid = fliplr(cCentroid{1}:-TimeRes*360:1);
TimeGrid = [ TimeGrid(1:end-1) cCentroid{1}:TimeRes*360:size(cCentroid{2},1)];
set(ECG_centroid_hdl, 'XTick', colvec(TimeGrid));
set(ECG_centroid_hdl, 'XTickLabel', Seconds2HMS((TimeGrid-cCentroid{1})/360) );
title(ECG_centroid_hdl, 'First Two PCA Components' );
box(ECG_centroid_hdl, 'off');

plot( RR_centroid_hdl,  cCentroid{4}, '--ob' );
hold(RR_centroid_hdl, 'on');
plot( RR_centroid_hdl,  [ cCentroid{3} cCentroid{3}], [ min(min(cCentroid{4})) max(max(cCentroid{4}))], '--r' );
hold(RR_centroid_hdl, 'off');
TightAxes(RR_centroid_hdl);
set(RR_centroid_hdl, 'XTick', cCentroid{3});
set(RR_centroid_hdl, 'XTickLabel', 'Current heartbeat' );
title(RR_centroid_hdl, 'Local RR interval evolution' );
box(RR_centroid_hdl, 'off');

plot( Morph_centroid_hdl,  cCentroid{6} );
hold(Morph_centroid_hdl, 'on');
plot( Morph_centroid_hdl,  [ cCentroid{5} cCentroid{5}], [ min(min(cCentroid{6})) max(max(cCentroid{6}))], '--r' );
hold(Morph_centroid_hdl, 'off');
TightAxes(Morph_centroid_hdl);
TimeRes = 0.1;
TimeGrid = fliplr(cCentroid{5}:-TimeRes*360:1);
TimeGrid = [ TimeGrid(1:end-1) cCentroid{5}:TimeRes*360:size(cCentroid{6},1)];
set(Morph_centroid_hdl, 'XTick', colvec(TimeGrid));
set(Morph_centroid_hdl, 'YTick', []);
set(Morph_centroid_hdl, 'XTickLabel', Seconds2HMS((TimeGrid-cCentroid{5})/360) );
title(Morph_centroid_hdl, 'Morphology details' );
box(Morph_centroid_hdl, 'off');


%% Closer heartbeats

QRS_positions = cCloserExamples{1};
ECG = cCloserExamples{2};

plot( ECG_closer_hdl, (1:size(ECG{1},1))-QRS_positions(1), ECG{1} );
hold(ECG_closer_hdl, 'on');
cellfun(@(a,b)(plot( ECG_closer_hdl, (1:size(a,1))-b, a )), ECG(min(end,2):end), num2cell(QRS_positions(min(end,2):end)) );
plot( ECG_closer_hdl,  [ 0 0 ], [ min(min(cell2mat(ECG))) max(max(cell2mat(ECG)))], '--r' );
hold(ECG_closer_hdl, 'off');
TightAxes(ECG_closer_hdl);
TimeRes = 0.4;
TimeGrid = fliplr(QRS_positions(1):-TimeRes*360:1);
TimeGrid = [ TimeGrid(1:end-1) QRS_positions(1):TimeRes*360:size(ECG{1},1)]-QRS_positions(1);
set(ECG_closer_hdl, 'XTick', colvec(TimeGrid));
set(ECG_closer_hdl, 'XTickLabel', Seconds2HMS((TimeGrid)/360) );
title(ECG_closer_hdl, 'First Two PCA Components' );
box(ECG_closer_hdl, 'off');

QRS_positions = cCloserExamples{3};
RR_series = cCloserExamples{4};

plot( RR_closer_hdl, (1:size(RR_series{1},1))-QRS_positions(1), RR_series{1}, ':xb' );
hold(RR_closer_hdl, 'on');
cellfun(@(a,b)(plot( RR_closer_hdl, (1:size(a,1))-b, a, ':xb' )), RR_series(min(end,2):end), num2cell(QRS_positions(min(end,2):end)) );
plot( RR_closer_hdl,  [ 0 0 ], [ min(min(cell2mat(RR_series))) max(max(cell2mat(RR_series)))], '--r' );
hold(RR_closer_hdl, 'off');
TightAxes(RR_closer_hdl);
set(RR_closer_hdl, 'XTick', 0);
set(RR_closer_hdl, 'XTickLabel', 'Current heartbeat' );
title(RR_closer_hdl, 'Local RR interval evolution' );
box(RR_closer_hdl, 'off');

QRS_positions = cCloserExamples{5};
ECG = cCloserExamples{6};

plot( Morph_closer_hdl, (1:size(ECG{1},1))-QRS_positions(1), ECG{1} );
hold(Morph_closer_hdl, 'on');
cellfun(@(a,b)(plot( Morph_closer_hdl, (1:size(a,1))-b, a )), ECG(min(end,2):end), num2cell(QRS_positions(min(end,2):end)) );
hold(Morph_closer_hdl, 'off');
TightAxes(Morph_closer_hdl);
TimeRes = 0.1;
TimeGrid = fliplr(QRS_positions(1):-TimeRes*360:1);
TimeGrid = [ TimeGrid(1:end-1) QRS_positions(1):TimeRes*360:size(ECG{1},1)]-QRS_positions(1);
set(Morph_closer_hdl, 'XTick', colvec(TimeGrid));
set(Morph_closer_hdl, 'XTickLabel', Seconds2HMS((TimeGrid)/360) );
set(Morph_closer_hdl, 'YTick', []);
title(Morph_closer_hdl, 'Morphology details' );
box(Morph_closer_hdl, 'off');

%% Distant heartbeats

QRS_positions = cDistantExamples{1};
ECG = cDistantExamples{2};

plot( ECG_distant_hdl, (1:size(ECG{1},1))-QRS_positions(1), ECG{1} );
hold(ECG_distant_hdl, 'on');
cellfun(@(a,b)(plot( ECG_distant_hdl, (1:size(a,1))-b, a )), ECG(min(end,2):end), num2cell(QRS_positions(min(end,2):end)) );
plot( ECG_distant_hdl,  [ 0 0 ], [ min(min(cell2mat(ECG))) max(max(cell2mat(ECG)))], '--r' );
hold(ECG_distant_hdl, 'off');
TightAxes(ECG_distant_hdl);
TimeRes = 0.4;
TimeGrid = fliplr(QRS_positions(1):-TimeRes*360:1);
TimeGrid = [ TimeGrid(1:end-1) QRS_positions(1):TimeRes*360:size(ECG{1},1)]-QRS_positions(1);
set(ECG_distant_hdl, 'XTick', colvec(TimeGrid));
set(ECG_distant_hdl, 'XTickLabel', Seconds2HMS((TimeGrid)/360) );
title(ECG_distant_hdl, 'First Two PCA Components' );
box(ECG_distant_hdl, 'off');

QRS_positions = cDistantExamples{3};
RR_series = cDistantExamples{4};

plot( RR_distant_hdl, (1:size(RR_series{1},1))-QRS_positions(1), RR_series{1}, ':xb' );
hold(RR_distant_hdl, 'on');
cellfun(@(a,b)(plot( RR_distant_hdl, (1:size(a,1))-b, a, ':xb' )), RR_series(min(end,2):end), num2cell(QRS_positions(min(end,2):end)) );
plot( RR_distant_hdl,  [ 0 0 ], [ min(min(cell2mat(RR_series))) max(max(cell2mat(RR_series)))], '--r' );
hold(RR_distant_hdl, 'off');
TightAxes(RR_distant_hdl);
set(RR_distant_hdl, 'XTick', 0);
set(RR_distant_hdl, 'XTickLabel', 'Current heartbeat' );
title(RR_distant_hdl, 'Local RR interval evolution' );
box(RR_distant_hdl, 'off');

QRS_positions = cDistantExamples{5};
ECG = cDistantExamples{6};

plot( Morph_distant_hdl, (1:size(ECG{1},1))-QRS_positions(1), ECG{1} );
hold(Morph_distant_hdl, 'on');
cellfun(@(a,b)(plot( Morph_distant_hdl, (1:size(a,1))-b, a )), ECG(min(end,2):end), num2cell(QRS_positions(min(end,2):end)) );
hold(Morph_distant_hdl, 'off');
TightAxes(Morph_distant_hdl);
TimeRes = 0.1;
TimeGrid = fliplr(QRS_positions(1):-TimeRes*360:1);
TimeGrid = [ TimeGrid(1:end-1) QRS_positions(1):TimeRes*360:size(ECG{1},1)]-QRS_positions(1);
set(Morph_distant_hdl, 'XTick', colvec(TimeGrid));
set(Morph_distant_hdl, 'XTickLabel', Seconds2HMS((TimeGrid)/360) );
set(Morph_distant_hdl, 'YTick', []);
title(Morph_distant_hdl, 'Morphology details' );
box(Morph_distant_hdl, 'off');


%% Wait for user interaction

set(fig_hnd , 'User', user_data );

uiwait(fig_hnd); 

if( ishandle(fig_hnd) )
    user_data = get(fig_hnd , 'User');

    Label  = user_data.Label;
    bRefresh = user_data.Refresh;
    bCancel = user_data.Cancel;
    
    close(fig_hnd);
else
    bCancel = true;
    Label  = [];
    bRefresh = [];
end


function ChooseLabel(obj, event_obj, strLabel)

fig_hnd = gcf();
user_data = get(fig_hnd , 'User');
user_data.Label = strLabel;
set(fig_hnd , 'User', user_data );
uiresume(fig_hnd); 

function SkipCluster(obj, event_obj)

fig_hnd = gcf();
uiresume(fig_hnd); 

function CancelButton(obj, event_obj)
fig_hnd = gcf();
user_data = get(fig_hnd , 'User');
user_data.Cancel = true;
set(fig_hnd , 'User', user_data );
uiresume(fig_hnd); 

function RefreshExamples(obj, event_obj)

fig_hnd = gcf();
user_data = get(fig_hnd , 'User');
user_data.Refresh = true;
set(fig_hnd , 'User', user_data );
uiresume(fig_hnd); 


function TightAxes(axes_hdl)

axis(axes_hdl, 'tight')
xlimits = xlim(axes_hdl);
xrange = diff(xlimits);
ylimits = ylim(axes_hdl);
yrange = diff(ylimits);
xlim(axes_hdl,  xlimits + [ -0.05*xrange 0.05*xrange ] )
ylim(axes_hdl, ylimits + [ -0.05*yrange 0.05*yrange ] )