PhysioNet Cardiovascular Signal Toolbox 1.0.0

File: <base>/Tools/PRSA_Tools/prsa.m (7,467 bytes)
function [ac_results, dc_results, prsa_ac, prsa_dc] = prsa(rr, rri, HRVparams, sqi, WinStarIdxs)
%   [ac_results, dc_results] = prsa(rr, rri, sqi, windows_all, HRVparams )
%
%   OVERVIEW:
%       Calculates acceleration and deceleration capacity values  
%   INPUT
%       rr           - rr intervals
%       rri          - index of rr intervals
%       HRVparams    - struct of settings for hrv_toolbox analysis
%       sqi          - Signal Quality Index; Requires a matrix with
%                      at least two columns. Column 1 should be
%                      timestamps of each sqi measure, and Column 2
%                      should be SQI on a scale from 0 to 1.
%       WinStarIdxs  - Starting index of each windows to analyze 
%
%   OUTPUT
%       ac_results   - Acceleration Capacity value
%       dc_results   - Deceleration Capacity value
%       prsa_ac      - PRSA signal for AC anchor points
%       prsa_dc      - PRSA signal for DC anchor points
%
%   AUTHORS
%       L. Campana
%       G. Clifford
%   REFERENCE   
%       http://adsabs.harvard.edu/abs/2007Chaos..17a5112K
%       http://h-r-t.org/prsa/en/
%	REPO:       
%       https://github.com/cliffordlab/PhysioNet-Cardiovascular-Signal-Toolbox
%   DEPENDENCIES & LIBRARIES
%	COPYRIGHT (C) 2016 AUTHORS (see above)
%       This code (and all others in this repository) are under the GNU General Public License v3
%       See LICENSE in this repo for details.

% Feb 13, 2017
% Code altered by Adriana N Vest for the HRV Toolbox. Most of code
% unchanged except for HRVparams and Initializations Section and the
% inclusion of windowing options.
% Oct 13, 2017
% Code altered by Giulia Da Poian to compute AC and DC value at different
% scale s 
%
% These default parameters were a part of the original PRSA code developed
% by the authors above. 
% tp = 20; thresh_per
% wl = 30; prsa_win_length
% fsd = 512; fs
%%
% Make vector a column
rr = rr(:);

if nargin < 5
    error('no data provided')
end
if isempty(sqi)
    sqi(:,1) = rri;
    sqi(:,2) = ones(length(rri),1);
end

time_stamp = rri;

prsaWinLength = HRVparams.prsa.win_length;
s = HRVparams.prsa.scale;
PRSA_th = HRVparams.prsa.thresh_per; 
plot_results = HRVparams.prsa.plot_results;
windowlength = HRVparams.windowlength;
SQI_th = HRVparams.sqi.LowQualityThreshold;        % SQI threshold
WinQuality_th = HRVparams.RejectionThreshold; % Low quality windows threshold

Anchor_Low_th = 1-PRSA_th/100-.0001; % The lower limit for the AC anchor selection
Anchor_High_th = 1+PRSA_th/100;      % The upper limit for the DC anchor selection

% Preallocation

ac_results = nan(length(WinStarIdxs),1);
dc_results = nan(length(WinStarIdxs),1);
prsa_ac = [];
prsa_dc = [];

% Run PRSA by Window
% Loop through each window of RR data
for i_win = 1:length(WinStarIdxs)
	% Check window for sufficient data
    if isnan(WinStarIdxs(i_win))

    end
    if ~isnan(WinStarIdxs(i_win))
        % Isolate data in this window
        % idx_NN_in_win = find(rri >= windows_all(i_win) & rri < windows_all(i_win) + windowlength);
        % idx_sqi_win = find(sqi(:,1) >= windows_all(i_win) & sqi(:,1) < windows_all(i_win) + windowlength);
        sqi_win = sqi( sqi(:,1) >= WinStarIdxs(i_win) & sqi(:,1) < WinStarIdxs(i_win) + windowlength,:);
        nn_win = rr( rri >= WinStarIdxs(i_win) & rri < WinStarIdxs(i_win) + windowlength );
         
        % Analysis of SQI for the window
        lowqual_idx = find(sqi_win(:,2) < SQI_th);

        % If enough data has an adequate SQI, perform the calculations
        if numel(lowqual_idx)/length(sqi_win(:,2)) < WinQuality_th

            % intialize
            acm = [];
            dcm = [];
            drr_per = nn_win(2:end)./nn_win(1:end-1);

            ac_anchor = (drr_per > Anchor_Low_th) & (drr_per <= .9999); % defines ac anchors, no changes greater then 5%
            dc_anchor = (drr_per > 1) & (drr_per <= Anchor_High_th);
            ac_anchor = [0; ac_anchor(:)];
            dc_anchor = [0; dc_anchor(:)];
            ac_anchor(1:prsaWinLength) = 0;                                        % sets first window to 0
            ac_anchor(length(ac_anchor)-prsaWinLength+1:length(ac_anchor)) = 0;    % sets last window to 0
            dc_anchor(1:prsaWinLength) = 0;                                        % sets first window to 0
            dc_anchor(length(dc_anchor)-prsaWinLength+1:length(dc_anchor)) = 0;    % sets last window to 0
            ac_ind = find(ac_anchor);
            dc_ind = find(dc_anchor);

            for i = 1:length(dc_ind)
                dcm(i,:) = 1000*nn_win(dc_ind(i)-prsaWinLength:dc_ind(i)+prsaWinLength-1); % convert from sec to msec
            end
            
            for i = 1:length(ac_ind)
                acm(i,:) = 1000*nn_win(ac_ind(i)-prsaWinLength:ac_ind(i)+prsaWinLength-1); % convert from sec to msec
            end

            prsa_ac = mean(acm);
            prsa_dc = mean(dcm);
            
            % Edited by Adriana Vest: Added the following if statements to
            % deal with scenarios when ac or dc is not computable for a
            % particular window. An example scenario is when the RR
            % intervals are flat.
            if ~isnan(prsa_dc) % Edited by Giulia Da Poian
                dc = (sum(prsa_dc(prsaWinLength+1:prsaWinLength+s)) - sum(prsa_dc(prsaWinLength-(s-1):prsaWinLength))) ./ (2*s);
                dc_results(i_win,1) = dc; % assign output of window
            end
            if ~isnan(prsa_ac) % Edited by Giulia Da Poian
                ac = (sum(prsa_ac(prsaWinLength+1:prsaWinLength+s)) - sum(prsa_ac(prsaWinLength-(s-1):prsaWinLength))) ./ (2*s);
                ac_results(i_win,1) = ac; % assign output of window
            end

            % Load custom colors
            custom_colors.red = [72 11 11] / 100;
            custom_colors.green = [30 69 31] / 100;

            % Plot results
            if plot_results == 1
                figure(1);
                plot(time_stamp,nn_win,'k+');
                hold on;

                figure(2)
                subplot(2,1,2)
                plot(dcm,'k--');
                legend('Deceleration');
                hold on;

                figure(2)
                subplot(2,1,1)
                plot(acm,'k--');
                legend('Acceleration');    
                hold on;

                figure(3)
                plot(time_stamp,nn_win,'k-+');
                hold on;
                plot(time_stamp(ac_ind),nn_win(ac_ind), 'color', custom_colors.green, 'marker', '+');
                plot(time_stamp(dc_ind),nn_win(dc_ind), 'color', custom_colors.red, 'marker', '+');
                legend('non-anchor','ac anchor','dc anchor');
                title('RR anchors');

                figure(4);
                subplot(2,1,1)
                plot([-2:2*prsaWinLength-2],dcm,'k--')
                title('dc matrix')
                hold on
                plot([-2:2*prsaWinLength-2],prsa_dc,'r');
                subplot(2,1,2)
                plot([-2:2*prsaWinLength-2],acm,'k--')
                hold on
                plot([-2:2*prsaWinLength-2],prsa_ac,'r');
                title('ac matrix')
            end % end of plotting condition
        else % else, if SQI is not adequate
        end % end of conditional statements run when SQI is adequate
    else % else, if window is NaN
    end % end of check for sufficient data
end % end of loop through windows


end % end of function