ECG-Kit 1.0
(16,071 bytes)
%% Convert heartbeat type of annotation from valid ECG formats to EC57 AAMI
% Map heartbeat annotations in the anntyp field of the ann structure to
% valid EC57 AAMI classes. Annotations that are not heartbeats are
% filtered out.
%
% Example
%
% ann = AnnotationFilterConvert(ann, recording_format, labeling_format)
%
% where:
% *ann is a annotation structure (ECG_annotations prop. in ECGwrapper
% object). Mandatory fields for this function are: time and anntyp.
% *recording_format is a string with a valid recording format read by
% read_ecg (cKnownFormats).
% *labeling_format is a string to map the annotations, possible values
% are AAMI (N,S,V,F,Q) or AAMI2 (N,S,V&F,Q).
%
% See also ECGwrapper, read_ECG
%
% Author: Mariano Llamedo Soria llamedom@electron.frba.utn.edu.ar
% Version: 0.1 beta
% Birthdate: 01/01/2012
% Last update: 18/10/2014
% Copyright 2008-2015% Version: 0.1 beta
% Birthdate: 01/01/2012
% Last update: 18/10/2014
% Copyright 2008-2015
function ann = AnnotationFilterConvert(ann, recording_format, labeling_format)
cLabelingFormats = {'AAMI', 'AAMI2'};
LabelingIndexes = [2; 3];
if( nargin < 1 || isempty(ann) )
ann = [];
return
end
if( isfield(ann,'time') && isempty(ann.time) )
return
end
if( nargin > 2 && ~isempty(labeling_format) )
LabConversion_idx = LabelingIndexes(find(strcmpi(labeling_format, cLabelingFormats)));
else
%default AAMI2
LabConversion_idx = LabelingIndexes(2);
end
if( strcmpi(recording_format, 'AHA') )
%%%%%%%%%%%%%%%%%
%%% AHA FORMAT %%%
%%%%%%%%%%%%%%%%%%%
% Esta matriz es OBSOLETA. Fue reemplazada por
% iLabListsTranslations. La deje para documentacion de las
% clases nada mas.
cTranslationMatrix = { ...
'Ventricular Escape' 'V Escape' 9 'E' 'E' ; ...
'Fusion Beat' 'Fusion Beat' 10 'F' 'F' ; ...
'Beat of Non-Ventricular Origin' 'Beat of Non-Ventricular Origin' 1 'N' 'N' ; ...
'Paced Beat' 'Paced Beat' 4 'P' 'P' ; ...
'Questionable Beat - Indeterminate Origin' 'Questionable Beat' 5 'Q' 'Q' ; ...
'R-on-T Beat' 'R-on-T Beat' 8 'R' 'R' ; ...
'Unreadable' 'Unreadable' 5 'U' 'U' ; ...
'Premature Ventricular Contraction' 'Ventricular' 8 'V' 'V' ; ...
'Beginning of Ventricular Fibrillation or Flutter' 'Start Flutter o Fib' 9 '[' '[' ; ...
'End of Ventricular Fibrillation or Flutter' 'End Flutter o Fib' 9 ']' ']' ; ...
'fv c/ NaN' 'fv c/ NaN' 9 'Ñ' 'Ñ' ; ...
};
cValidAnnotations = cTranslationMatrix(:,5);
% cAAMItranslation = cTranslationMatrix(:,4);
cAnnTranslation = cTranslationMatrix(:,2);
cValidAnnotationsString = cTranslationMatrix(:,1);
cLablists = { 'AHA' 'AAMI' 'AAMI2' 'Rrhythm' 'Morph '};
cLabListsLabels = { ...
cValidAnnotations;
{'Normal' 'Supraventricular' 'Ventricular' 'Fusion' 'Unclass' 'NoAAMI'};
{'Normal' 'Supraventricular' 'Ventricular' 'Unclass' 'NoAAMI'};
{'Prematuro' 'Normal' 'Escape' 'Unclass'};
{'Normal' 'Aberrada' 'Unclass'} };
cAAMItranslation = cLabListsLabels{LabConversion_idx};
iLabListsTranslations = [ ...
...% AHA labelling: 'E' 'F' 'N' 'P' 'Q' 'R' 'U' 'V' '[' ']' 'ñ'
1:size(cTranslationMatrix,1);
3 4 1 6 5 3 6 3 6 6 6;
3 3 1 5 4 3 5 3 5 5 5;
3 2 2 4 4 1 4 1 4 4 4;
2 1 1 3 3 2 3 2 3 3 3;
];
elseif( strcmpi(recording_format, 'HES') )
%%%%%%%%%%%%%%%%%%
%%% HES FORMAT %%%
%%%%%%%%%%%%%%%%%%
% Esta matriz es OBSOLETA. Fue reemplazada por
% iLabListsTranslations. La deje para documentacion de las
% clases nada mas.
cTranslationMatrix = { ...
'NO_TYPING' 'NO_TYPING' 5 'Q' 0 ; ...
'DOMINANT_TYPE_0' 'DOMINANT_TYPE_0' 1 'N' 1 ; ...
'DOMINANT_TYPE_1' 'DOMINANT_TYPE_1' 1 'N' 2 ; ...
'ABERRANT' 'ABERRANT' 2 'S' 4 ; ...
'ARTEFAKT' 'ARTEFAKT' 5 'Q' 5 ; ...
'VES' 'VES' 3 'V' 60 ; ...
'SVES' 'SVES' 2 'S' 70 ; ...
};
cValidAnnotations = cell2mat(cTranslationMatrix(:,5));
% cAAMItranslation = cTranslationMatrix(:,4);
cAnnTranslation = cTranslationMatrix(:,2);
cValidAnnotationsString = cTranslationMatrix(:,1);
cLablists = { 'HES' 'AAMI' 'AAMI2' 'Rrhythm' 'Morph '};
cLabListsLabels = { ...
cValidAnnotationsString;
{'Normal' 'Supraventricular' 'Ventricular' 'Fusion' 'Unclass' 'NoAAMI'};
{'Normal' 'Supraventricular' 'Ventricular' 'Unclass' 'NoAAMI'};
{'Prematuro' 'Normal' 'Escape' 'Unclass'};
{'Normal' 'Aberrada' 'Unclass'} };
cAAMItranslation = cLabListsLabels{LabConversion_idx};
iLabListsTranslations = [ ...
...% HES labelling: 'Q' 'N' 'N' 'S' 'Q' 'V' 'S'
1:size(cTranslationMatrix,1);
5 1 1 2 5 3 2;
4 1 1 2 4 3 2;
4 2 2 1 4 1 1;
3 1 1 2 3 2 1;
];
elseif( strcmpi(recording_format, 'ISHNE') )
%%%%%%%%%%%%%%%%%%
%%% ISHNE FORMAT %%%
%%%%%%%%%%%%%%%%%%%%%
% Esta matriz es OBSOLETA. Fue reemplazada por
% iLabListsTranslations. La deje para documentacion de las
% clases nada mas.
cTranslationMatrix = { ...
'Normal beat' 'Normal' 1 'N' 'N' ; ...
'Premature Ventricular Contraction' 'Ventricular' 8 'V' 'V' ; ...
'Supraventricular premature or ectopic beat' 'Supraventricular' 5 'S' 'S' ; ...
'Calibration pulse' 'Calibration' 5 'ñ' 'C' ; ...
'Bundel branch block beat' 'BBB' 9 'N' 'B' ; ...
'Pace' 'Paced Beat' 4 'Q' 'P' ; ...
'Artefact' 'Artefact' 9 'ñ' 'X' ; ...
'Unknown' 'Unknown' 5 'Q' 'Q' ; ...
'fv c/ NaN' 'fv c/ NaN' 9 'ñ' 'ñ' ; ...
};
cValidAnnotations = cTranslationMatrix(:,5);
cAnnTranslation = cTranslationMatrix(:,2);
cValidAnnotationsString = cTranslationMatrix(:,1);
cLablists = { 'ISHNE' 'AAMI' 'AAMI2' 'Rrhythm' 'Morph '};
cLabListsLabels = { ...
cValidAnnotations;
{'Normal' 'Supraventricular' 'Ventricular' 'Fusion' 'Unclass' 'NoAAMI'};
{'Normal' 'Supraventricular' 'Ventricular' 'Unclass' 'NoAAMI'};
{'Prematuro' 'Normal' 'Escape' 'Unclass'};
{'Normal' 'Aberrada' 'Unclass'} };
cAAMItranslation = cLabListsLabels{LabConversion_idx};
iLabListsTranslations = [ ...
...% ISHNE labelling: 'N' 'V' 'S' 'C' 'B' 'P' 'X' 'Q' 'ñ'
1:size(cTranslationMatrix,1);
1 3 2 6 1 5 6 5 6;
1 3 2 5 1 3 5 4 5;
2 1 1 4 2 4 4 4 4;
1 2 1 3 2 3 3 3 3;
];
elseif( strcmpi(recording_format, 'MIT') )
%%%%%%%%%%%%%%%%%
%%% MIT FORMAT %%%
%%%%%%%%%%%%%%%%%%%
% Esta matriz es OBSOLETA. Fue reemplazada por
% iLabListsTranslations. La deje para documentacion de las
% clases nada mas.
cTranslationMatrix = { ...
'Normal beat' 'Normal' 1 'N' 'N' ; ...
'Normal beat' 'puntoNormal' 1 'N' 'ñ' ; ...
'Left bundle branch block beat' 'L' 1 'N' 'L' ; ...
'Right bundle branch block beat' 'R' 1 'N' 'R' ; ...
'Atrial premature beat' 'APC' 8 'S' 'A' ; ...
'Aberrated atrial premature beat' 'aberrated APC' 8 'S' 'a' ; ...
'Nodal (junctional) premature beat' 'Nodal premature beat' 8 'S' 'J' ; ...
'Supraventricular premature beat' 'S' 8 'S' 'S' ; ...
'Premature ventricular contraction' 'V' 9 'V' 'V' ; ...
'Fusion of ventricular and normal beat' 'F' 10 'F' 'F' ; ...
'Start of ventricular flutter/fibrillation' '[' 11 '[' '[' ; ...
'Ventricular flutter wave' 'Ventricular flutter' 11 '!' '!' ; ...
'End of ventricular flutter/fibrillation' ']' 11 ']' ']' ; ...
'Atrial escape beat' 'Atrial Escape' 8 'S' 'e' ; ...
'Nodal (junctional) escape beat' 'Nodal Escape beat' 8 'S' 'j' ; ...
'Ventricular escape beat' 'Ventricular Escape' 9 'V' 'E' ; ...
'Paced beat' 'Paced' 21 'Q' '/' ; ...
'Fusion of paced and normal beat' 'fpn' 21 'Q' 'f' ; ...
'Non-conducted P-wave (blocked APB)' 'Non-conducted P-wave (blocked APB)' 11 'x' 'x' ; ...
'Non-conducted P-wave (blocked APB)' 'p' 11 'p' 'p' ; ...
'Unclassifiable beat' 'Q' 21 'Q' 'Q' ; ...
'Isolated QRS-like artifact' 'Isolated' 11 '|' '|' ; ...
'Beat not classified during learning' 'Beat not classified during learning' 11 '?' '?' ; ...
'Rhythm change ' 'Rhythm change' 11 '+' '+' ; ...
'R-on-T premature ventricular contraction' 'R-on-T' 9 'V' 'r' ; ...
'ST segment change' 'ST change' 11 's' 's' ; ...
'Bundle branch block beat (unspecified)' 'Bundle branch block beat' 1 'N' 'B' ; ...
'Supraventricular escape beat (atrial or nodal)' 'Supraventricular escape beat' 8 'S' 'n' ; ...
'fv c/ NaN' 'fv c/ NaN' 11 'ñ' 'ñ' ; ...
};
cValidAnnotations = cTranslationMatrix(:,5);
% cAAMItranslation = cTranslationMatrix(:,4);
cAnnTranslation = cTranslationMatrix(:,2);
cValidAnnotationsString = cTranslationMatrix(:,1);
cLablists = { 'MIT-BIH' 'AAMI' 'AAMI2' 'Rrhythm' 'Morph '};
cLabListsLabels = { ...
cValidAnnotationsString;
{'Normal' 'Supraventricular' 'Ventricular' 'Fusion' 'Unclass' 'NoAAMI'};
{'Normal' 'Supraventricular' 'Ventricular' 'Unclass' 'NoAAMI'};
{'Prematuro' 'Normal' 'Escape' 'Unclass'};
{'Normal' 'Aberrada' 'Unclass'} };
cAAMItranslation = cLabListsLabels{LabConversion_idx};
iLabListsTranslations = [ ...
...% MITBIH labelling: 'N' 'ñ' 'L' 'R' 'A' 'a' 'J' 'S' 'V' 'F' '[' '!' ']' 'e' 'j' 'E' '/' 'f' 'x' 'p' 'Q' '|' '?' '+' 'r' 's' 'B' 'n' 'ñ'
1:size(cTranslationMatrix,1);
1 1 1 1 2 2 2 2 3 4 6 6 6 1 1 3 5 5 6 6 5 6 6 6 3 6 1 1 6;
1 1 1 1 2 2 2 2 3 3 5 5 5 1 1 3 4 4 5 5 4 5 5 5 3 5 1 1 5;
2 2 2 2 1 1 1 1 1 1 4 4 4 3 3 3 4 4 4 4 4 4 4 4 1 4 2 3 4;
1 1 1 1 1 2 1 1 2 2 3 3 3 1 1 2 3 3 3 3 3 3 3 3 2 3 1 1 3;
];
else
% AAMI asumption
cprintf('[1,0.5,0]', 'Heartbeats annotations types in %s format no translated.\n', recording_format);
return
end
iAAMItranslation = iLabListsTranslations(2,:);
[ann_types, ~, ann_types_idx] = unique(ann.anntyp);
cant_types = length(ann_types);
[~, valid_ann_idx ann_types_valid_idx ] = intersect(cValidAnnotations, ann_types);
NotValidAnn_idx = find(iAAMItranslation(valid_ann_idx) == 6);
%descarta tambien los Unknown
% NotValidAnn_idx = find(iAAMItranslation(valid_ann_idx) >= 5);
NotValidAnn_idx = ann_types_valid_idx(NotValidAnn_idx);
%Termino de averiguar las anotaciones que no sean latidos.
aux = setdiff(1:cant_types, ann_types_valid_idx);
NotValidAnn_idx = [(NotValidAnn_idx(:))' aux];
ValidAnn_idx = setdiff(1:length(ann_types), NotValidAnn_idx);
[~, valid_ann_idx ] = intersect(cValidAnnotations, ann_types(ValidAnn_idx));
ann_types_translated = zeros(cant_types,1);
ann_types_translated(ValidAnn_idx) = valid_ann_idx;
%Resguardar� un vector con el c�digo de anotacion para cada latido.
ann_types_idx = ann_types_translated(ann_types_idx)';
bValidBeats = colvec(ann_types_idx ~= 0);
for field = rowvec(fieldnames(ann))
if( isempty(ann.(field{1})) )
ann = rmfield(ann, field{1} );
else
ann.(field{1}) = ann.(field{1})(bValidBeats);
end
end
%Convert to the proper labeling
aux_val = char(cAAMItranslation(colvec(iLabListsTranslations( LabConversion_idx, ann_types_idx(bValidBeats)))));
if( ~isempty(aux_val) )
ann.anntyp = aux_val(:,1);
end