PhysioNet Cardiovascular Signal Toolbox 1.0.0
(5,380 bytes)
function [anntime,type,subtype,chan,num,comments]=read_ann(recordName,annotator)
% Reads a WFDB annotation and returns:
%
% anntime
% Nx1 vector of the ints. The time of the annotation in samples
% with respect to the fist sample in the signals in WFDB dat file.
% To convert this vector to a string of time stamps see WFDBTIME.
%
% type
% Nx1 vector of the chars describing annotation type.
% For a list of standard type used by PhyioNet, please see:
% https://www.physionet.org/physiotools/wfdb/lib/ecgcodes.h
%
% subtype
% Nx1 vector of the ints describing annotation subtype, if not empty.
% For a list of standard annotation codes used by PhyioNet, please see:
% http://www.physionet.org/physiobank/annotations.shtml
%
% chan
% Nx1 vector of the ints describing annotation subtype, if not empty.
%
% num
% Nx1 vector of the ints describing annotation NUM, if not empty.
%
% comments
% Nx1 vector of the cells describing annotation comments, if not empty.
%
%
% Required Parameters:
%
% recorName
% String specifying the name of the record
%
% annotator
% String specifying the name of the annotation file
%
% ORIGINAL SOURCE AND AUTHORS:
% Qiao Li
%
% Dependent scripts written by various authors
% (see functions for details)
% COPYRIGHT (C) 2016
% LICENSE:
% This software is offered freely and without warranty under
% the GNU (v3 or later) public license. See license file for
% more information
%
if isnumeric(recordName)
recordName = num2str(recordName);
end
annfile=[recordName '.' annotator];
fid=fopen(annfile,'r');
A= fread(fid, [2, inf], 'uint8')';
fclose(fid);
anntime=[];
type=[];
chan=[];
num=[];
comments=[];
subtype_temp=[];
curnum=0;
curchn=0;
sa=size(A);
saa=sa(1);
i=1;
ann_n=0;
while i<=saa
% Each annotation occupies an even number of bytes. The first byte in
% each pair is the least significant byte. The six most significant
% bits (A) of each byte pair are the annotation type code, and the ten
% remaining bits (I) specify the time of the annotation, measured in
% sample intervals from the previous annotation (or from the beginning
% of the record for the first annotation). If 0 < A <= ACMAX, then A
% is defined in <wfdb/ecgcodes.h>. (MIT format)
typeh=bitshift(A(i,2),-2);
if typeh==59 % SKIP, the next 4 bytes are the interval
if bitshift(A(i+3,2),-2)~=0
type=[type;int2ann(bitshift(A(i+3,2),-2))];
anntime=[anntime;A(i+2,1)+bitshift(A(i+2,2),8)+...
bitshift(A(i+1,1),16)+bitshift(A(i+1,2),24)];
ann_n=ann_n+1;
num(ann_n)=curnum;
chan(ann_n)=curchn;
end
i=i+3;
elseif typeh==60 % NUM, I = annotation num field for current and subsequent annotations; otherwise, assume previous annotation num (initially 0).
% curnum=bitshift(bitand(A(i,2),3),8)+A(i,1);
curnum=A(i,1);
if curnum>127
curnum=curnum-255-1;
end
num(ann_n)=curnum;
elseif typeh==61 % SUB, I = annotation subtyp field for current annotation only; otherwise, assume subtyp = 0.
% cursub=bitshift(bitand(A(i,2),3),8)+A(i,1);
cursub=A(i,1);
if cursub>127
cursub=cursub-255-1;
end
subtype_temp(ann_n)=cursub;
elseif typeh==62 % CHN, I = annotation chan field for current and subsequent annotations; otherwise, assume previous chan (initially 0).
% curchn=bitshift(bitand(A(i,2),3),8)+A(i,1);
curchn=A(i,1);
if curchn>127
curchn=curchn-255-1;
end
chan(ann_n)=curchn;
elseif typeh==63 % AUX, I = number of bytes of auxiliary information (which is contained in the next I bytes); an extra null, not included in the byte count, is appended if I is odd.
hilfe=bitshift(bitand(A(i,2),3),8)+A(i,1);
hilfe=hilfe+mod(hilfe,2);
curaux=[];
for j=1:hilfe/2
curaux=[curaux char(A(i+j,1)) char(A(i+j,2))];
end
comments{ann_n}=curaux;
i=i+hilfe/2;
else
anntime=[anntime;bitshift(bitand(A(i,2),3),8)+A(i,1)];
type=[type;int2ann(bitshift(A(i,2),-2))];
ann_n=ann_n+1;
num(ann_n)=curnum;
chan(ann_n)=curchn;
end
i=i+1;
end
type(length(type))=[]; % last line = EOF (=0)
anntime(length(anntime))=[]; % last line = EOF
num(length(num))=[];
chan(length(chan))=[];
num=num';
chan=chan';
if ~isempty(comments)
comments=comments';
end
subtype=zeros(length(anntime),1);
if ~isempty(subtype_temp)
subtype(find(subtype_temp~=0))=subtype_temp(find(subtype_temp~=0));
end
clear A;
anntime= (cumsum(anntime));
end
function ann_type=int2ann(ann_int)
% input: ann_int, annotation code, integer
% output:ann_type, annotation type, char
Typestr='NLRaVFJASEj/Q~|sT*D"=pB^t+u?![]en@xf(`)''r';
codeint=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,39,40,40,41];
findp=find(codeint==ann_int);
if ~isempty(findp)
ann_type=Typestr(findp(1));
else
ann_type=' ';
end
end