function varargout=wrann(varargin) % % wrann(recordName,annotator,ann,anntype,subtype,chan,num,comments) % % Wrapper to WFDB WRANN: % http://www.physionet.org/physiotools/wag/wrann-1.htm % % Writes data into a WFDB annotation file. The file will be saved at the % current directory (if the record is in the current directory) or, if a using % a PhysioNet web record , a subdirectory in the current directory, with % the relative path determined by recordName. The files will have the % name 'recordName" with the 'annotator' extension. You can use RDANN to % verify that the write was completed sucessfully (see example below). % % % % NOTE: The WFDB Toolbox uses 0 based index, and MATLAB uses 1 based index. % Due to this difference annotation values ('ann') are shifted inside % this function in order to be compatible with the WFDB native % library. The MATLAB user should leave the indexing conversion to % the WFDB Toolbox. % % Required Parameters: % % recordName % String specifying the name of the record in the WFDB path or % in the current directory. % % annotator % String specifying file extension of the annotation file to be % written. % % ann % Nx1 integer vector containing the sample numbers of the annotations % with respect to the begining of the record. Samples must be >=1. % % anntype % Nx1 (single) character vector, or single character, describing each annotation type. % Default is 'N'. For a list of standard annotation codes used by PhyioNet, % please see: http://www.physionet.org/physiobank/annotations.shtml % If the description is longer than one character, use the 'comments' % field. % % subtype % Nx1 integer vector, or single scalar, describing annotation subtype. % Default is '0'. Range must be from -128 to 127. % % chan % Nx1 integer vector, or single scalar, describing annotation CHAN. % Default is 0. Range must be from 0 to 255. % % num % Nx1 integer vector, or single scalar, describing annotation NUM. % Default is 0. Range must be from -128 to 127. % % comments % Nx1 or single cell of strings describing annotation comments. % Default is blank {''}. % % Note: annType, subType, chan, num, and comments can be of dimension Nx1 % or 1x1. If they are 1x1, this function will repeat the element N times. % % %%Example- Creates a *.test file in your current directory %[ann,type,subtype,chan,num]=rdann('challenge/2013/set-a/a01','fqrs'); % wrann('challenge/2013/set-a/a01','test',ann,type,subtype,chan,num) % % % %Reading the file again should give the same results %[ann,type,subtype,chan,num]=rdann('challenge/2013/set-a/a01','fqrs'); %wrann('challenge/2013/set-a/a01','test',ann,type,subtype,chan,num); %[ann2,type2,subtype2,chan2,num2]=rdann('challenge/2013/set-a/a01','test',[],[],1); %err=sum(ann ~= ann2) % % % % %Example 2 %[ann,type,subtype,chan,num]=rdann('mitdb/100','atr'); %wrann('mitdb/100','test',ann,type,subtype,chan,num); % % Written by Ikaro Silva, 2013 % Last Modified: November 4, 2014 % Version 1.4 % Since 0.0.1 % % See also RDANN, RDSAMP, WFDBDESC % %endOfHelp persistent javaWfdbExec if(isempty(javaWfdbExec)) javaWfdbExec=getWfdbClass('wrann'); end % Set default pararamter values inputs={'recordName','annotator','ann','annType','subType','chan','num','comments'}; annType='N'; subType=0; chan=0; num=0; comments={''}; % Read in input arguments for n=1:nargin if(~isempty(varargin{n})) eval([inputs{n} '=varargin{n};']) end end wfdb_argument={'-r',recordName,'-a',annotator}; % Check the main input variable ann - the annotation samples if(any(isnan(ann(:)))) error('Annotation array contains NaNs. Not able to write file.'); end if (min(ann)<0) error('Annotation samples must be positive'); end N=length(ann); % Convert all the annoation to 0 based index and then to strings ann=ann-1; ann=num2str(reshape(ann, [], 1)); % Check all other input variables: % - Check data type % - Check input shape % - Convert integers to strings % - Extend length 1 inputs to length N % annType - characters if(~ischar(annType)) error('annType must be a character or an Nx1 character vector'); end checksize(annType, 'annType', N); if(length(annType)==1) annType=repmat(annType,[N 1]); end % subType, chan, and num - integers checksize(subType, 'subType', N); subType = num2chararray(subType, 'subType', N); checksize(chan, 'chan', N); chan = num2chararray(chan, 'chan', N); checksize(num, 'num', N); num = num2chararray(num, 'num', N); % comments - cells if (~iscell(comments)) error('comments must be a 1x1 or Nx1 cell of strings'); end checksize(comments, 'comments', N); if(length(comments)==1) comments=repmat(comments,N, 1); end % Create the strings to feed into wrann data=cell(N,1); % The cells storing the input strings to feed into wrann tab=char(9); for i=1:N % wrann reads in the following format: % HH:MM:SS.mmm %d %c %d %d %d\t%s % But since it doesn't actually use the time/date, and just uses the samples, % put in any filler. WFDB annotation files only store samples (and possibly a fs). if isempty(comments{i}) data{i}=['--------- ' ann(i,:) ' ' annType(i) ' ' ... subType(i,:) ' ' chan(i,:) ' ' num(i,:)]; else % Only write aux field if user specifies a non-empty string. data{i}=['--------- ' ann(i,:) ' ' annType(i) ' ' ... subType(i,:) ' ' chan(i,:) ' ' num(i,:) tab comments{i}]; end end % Run the wfdb wrann executable javaWfdbExec.setArguments(wfdb_argument); err=javaWfdbExec.execWithStandardInput(data); if(~isempty(strfind(err.toString,['annopen: can''t']))) error(char(err.toString)) end end % Check that the input argument dimension is consistent with the number of % annotations. function [] = checksize(inputarg, argname, numannots) inputsize = size(inputarg); if ((inputsize ~= [1,1]) & (inputsize ~= [numannots,1]) & (inputsize ~= [1, numannots])) error(strcat(argname, ' must have length 1 or N, where N = the number of annotations.')); end end % Convert an integer scalar or integer vector into a Nx[] character array % Raises error if input argument is not a numeric. function chararray = num2chararray(intarg, argname, numannots) if(~isnumeric(intarg)) error(strcat(argname, ' must be an integer or an Nx1 integer vector')); end if(length(intarg)==1) chararray=repmat(num2str(intarg),[numannots 1]); else if (size(intarg) == [1, numannots]) intarg = intarg'; end chararray = num2str(intarg); end end