Model for Simulating ECG and PPG Signals with Arrhythmia Episodes 1.3.0

File: <base>/ECG_PPG_model/simPAF_gen_multilead_VA.m (11,939 bytes)
function [QRSindex, rr, multileadVA, ecgLength] = simPAF_gen_multilead_VA(ecgLength, targets_SR_AF, rr, AFburden, realVAon, realAAon)
% 
% [] = simPAF_gen_multilead_VA() returns multilead (15 lead) ventricular
% activity. A set of 100 15-lead ECGs with SR selected from the PTB Diagnostic
% ECG Database is used as a basis for modeling ventricular activity. The ECGs 
% of the PTB database are first subjected to baseline removal and QRST delineation. 
% The original T-waves are then resampled to a fixed width and, depending on 
% the type of rhythm, width-adjusted to match prevailing heart rate. Since 
% the original ECGs last just for about 2 min, QRST complexes are subjected
% to repeated concatenation until desired length of ECG is obtained. The TQ 
% interval is interpolated using a cubic spline interpolation.
%
% Copyright (C) 2017  Andrius Petrenas
% Biomedical Engineering Institute, Kaunas University of Technology
%
% Available under the GNU General Public License version 3
% - please see the accompanying file named "LICENSE"
%
% Generated leads:
% multileadVA(1,:) - I        multileadVA(7,:) - V1      multileadVA(13,:) - X     
% multileadVA(2,:) - II       multileadVA(8,:) - V2      multileadVA(14,:) - Y  
% multileadVA(3,:) - III      multileadVA(9,:) - V3      multileadVA(15,:) - Z  
% multileadVA(4,:) - aVR      multileadVA(10,:) - V4 
% multileadVA(5,:) - aVL      multileadVA(11,:) - V5 
% multileadVA(6,:) - aVF      multileadVA(12,:) - V6 

rr = round(rr*1000);    % rr intervals in miliseconds

% Generate PQRST complexes
switch realVAon 
    case 0 % Generate synthetic PQRST complexes
        [data.pqrst, data.Qind, data.Rind, data.Sind, data.Tind] = simPAF_gen_syn_VA(100);  
    case 1 % Load random patch of PQRST complexes extracted from PTB database
        sigNum = randi([1 100]);
        load('DATA_PQRST_real')
        data.pqrst = DATApqrst(sigNum).pqrst;
        data.Qind = DATApqrst(sigNum).Qind;
        data.Rind = DATApqrst(sigNum).Rind;
        data.Sind = DATApqrst(sigNum).Sind;
        data.Tind = DATApqrst(sigNum).Tind;
end

% Original PQRST is subjected to repeated concatenation until required
% number of beats is obtained
arraySize = length(data.pqrst(1,:,1));
pqrstLength = length(data.pqrst(1,1,:));
pqrst = zeros(15, ecgLength,pqrstLength);

j = 1;
for i = 1:ecgLength+1 % Additonal is required to meat exact number of RR intervals
    pqrst(:,i,:) = data.pqrst(:,j,:);
    j = j + 1;
    if j > arraySize
        j = 1; 
    end
end

%Load QRST complexes for all leads
cnt = 0;
for lead = 1:15
    ecgSig = [];
    AFend = 0;
    cnt = cnt + 1;
    switch realAAon
        case 0 % Synthetic atrial activity
            rIndex = data.Rind - data.Qind;
            Qind = data.Qind; Rind = data.Rind - data.Qind; 
            Sind = data.Sind - data.Qind; Tind = data.Tind - data.Qind;
            for beatNr = 1:ecgLength
                QRSTtemp = pqrst(lead,beatNr,Qind+1:end);
                QRSTtemp = simPAF_correct_baseline(QRSTtemp);
                QRSTtempNext = pqrst(lead,beatNr+1,Qind+1:end);
                QRSTtempNext = simPAF_correct_baseline(QRSTtempNext);
                % Divide PQRST into two parts 
                QRST_PS = QRSTtemp(1,1:Sind); % The PQRS part 
                QRST_ST = QRSTtemp(1,Sind+1:Tind); % The ST part 
                % Resample T wave according to current RR interval
                % Signal is prolonged in order to avoid boundary effects of resampling
                QRST_ST  = [QRST_ST(1,1)*ones(1,20) QRST_ST QRST_ST(1,end)*ones(1,20)];
        
                % Gradual prolongation of T wave after AF is terminated
                if targets_SR_AF(beatNr) == 0
                    if AFend == 1
                        ST_length = round(length(QRST_ST)*sqrt((0.3+m*0.1)*rr(beatNr)/1000));
                        m = m + 1;
                        if m == 7
                            AFend = 0;
                        end
                    else
                        ST_length = round(length(QRST_ST)*sqrt(rr(beatNr)/1000));
                    end
                else
                    ST_length = round(length(QRST_ST)*sqrt(0.35));
                    AFend = 1;
                    m = 1;
                end
                
                QRST_ST = resample(QRST_ST, ST_length+40, length(QRST_ST));  % T wave length correction QT = QTc*sqrt(RR) ~ T = Tc*sqrt(RR)
                QRSTc = [QRST_PS QRST_ST(21:end-20)]; % Corrected PQRST
                % Find TQ length
                TQlength = rr(beatNr) - length(QRSTc);
                % Protect against the error of to low heart rate
                if  TQlength < 2
                    TQlength = 2;
                end
                % Interpolate TQ interval
                x = [1 TQlength];
                xi = 1:1:TQlength;
                y = [QRSTc(1,end) QRSTtempNext(1, 1)];
                TQ = interp1(x,y,xi,'linear');
                ecgSig = [ecgSig QRSTc TQ];
                if lead == 15
                    rIndex = [rIndex (rIndex(1,end) + TQlength + length(QRSTc))];
                end
            end
        case 1 % Real atrial activity
            if AFburden == 1 % Entire signal is AF
                rIndex = data.Rind - data.Qind;
            else
                rIndex = data.Rind;
            end
            for beatNr = 1:ecgLength
                if beatNr == 1
                    if AFburden == 1
                        Qind = data.Qind; Rind = data.Rind - data.Qind; 
                        Sind = data.Sind - data.Qind; Tind = data.Tind - data.Qind;
                        QRSTtemp = pqrst(lead,beatNr,Qind + 1:end);
                        QRSTtemp = simPAF_correct_baseline(QRSTtemp);
                    else
                        Qind = data.Qind; Rind = data.Rind;
                        Sind = data.Sind; Tind = data.Tind;
                        QRSTtemp = pqrst(lead,beatNr,1:end);
                        QRSTtemp = simPAF_correct_baseline(QRSTtemp);
                    end
                else
                    if targets_SR_AF(beatNr) == 0
                        if targets_SR_AF(beatNr-1) == 0
                            QRSTtemp = pqrst(lead,beatNr,1:end);
                            QRSTtemp = simPAF_correct_baseline(QRSTtemp);
                            Qind = data.Qind; Rind = data.Rind; 
                            Sind = data.Sind; Tind = data.Tind;
                        else % targets_SR_AF(beatNr-1) == 1
                            QRSTtemp = pqrst(lead,beatNr,Qind+1:end);
                            QRSTtemp = simPAF_correct_baseline(QRSTtemp);
                            Qind = data.Qind; Rind = data.Rind - data.Qind; 
                            Sind = data.Sind - data.Qind; Tind = data.Tind - data.Qind;  
                        end
                    else % targets_SR_AF(beatNr) == 1
                        if targets_SR_AF(beatNr-1) == 1
                            QRSTtemp = pqrst(lead,beatNr,Qind+1:end);
                            QRSTtemp = simPAF_correct_baseline(QRSTtemp);
                            Qind = data.Qind; Rind = data.Rind - data.Qind; 
                            Sind = data.Sind - data.Qind; Tind = data.Tind - data.Qind;      
                        else % targets_SR_AF(beatNr-1) == 0
                            QRSTtemp = pqrst(lead,beatNr,1:end);
                            QRSTtemp = simPAF_correct_baseline(QRSTtemp);
                            Qind = data.Qind; Rind = data.Rind; 
                            Sind = data.Sind; Tind = data.Tind;  
                        end
                    end
                end
                
                if beatNr == length(targets_SR_AF)
                    if targets_SR_AF(beatNr) == 0
                        RindNext = data.Rind; 
                        QRSTtempNext = pqrst(lead,beatNr,1:end);
                        QRSTtempNext = simPAF_correct_baseline(QRSTtempNext);
                    else
                        RindNext = data.Rind-data.Qind;
                        QRSTtempNext = pqrst(lead,beatNr,Qind+1:end);
                        QRSTtempNext = simPAF_correct_baseline(QRSTtempNext);
                    end
                else
                    if targets_SR_AF(beatNr+1) == 0
                        if targets_SR_AF(beatNr) == 1
                            RindNext = data.Rind-data.Qind;
                            QRSTtempNext = pqrst(lead,beatNr+1,Qind+1:end);
                            QRSTtempNext = simPAF_correct_baseline(QRSTtempNext);
                        else
                            RindNext = data.Rind;
                            QRSTtempNext = pqrst(lead,beatNr+1,1:end);
                            QRSTtempNext = simPAF_correct_baseline(QRSTtempNext);
                        end
                    else
                        if targets_SR_AF(beatNr) == 0
                            RindNext = data.Rind;
                            QRSTtempNext = pqrst(lead,beatNr+1,1:end);
                            QRSTtempNext = simPAF_correct_baseline(QRSTtempNext);
                        else
                            RindNext = data.Rind-data.Qind;
                            QRSTtempNext = pqrst(lead,beatNr+1,Qind+1:end);
                            QRSTtempNext = simPAF_correct_baseline(QRSTtempNext);
                        end
                    end
                end
                % Divide PQRST into two parts
                QRST_PS = QRSTtemp(1,1:Sind); % The PQRS part 
                QRST_ST = QRSTtemp(1,Sind+1:Tind); % The ST part 
                % Resample T wave according to current RR interval
                % Signal is prolonged in order to avoid boundary effects of resampling            
                QRST_ST = [QRST_ST(1,1)*ones(1,20) QRST_ST QRST_ST(1,end)*ones(1,20)];
                % Gradual prolongation of T wave after AF is terminated
                if targets_SR_AF(beatNr) == 0
                    if AFend == 1
                        ST_length = round(length(QRST_ST)*sqrt((0.3+m*0.1)*rr(beatNr)/1000));
                        m = m + 1;
                        if m == 7
                            AFend = 0;
                        end
                    else
                        ST_length = round(length(QRST_ST)*sqrt(rr(beatNr)/1000));
                    end
                else
                    ST_length = round(length(QRST_ST)*sqrt(0.35));
                    AFend = 1;
                    m = 1;
                end               
                QRST_ST = resample(QRST_ST, ST_length+40, length(QRST_ST));  % T wave length correction QT = QTc*sqrt(RR) ~ T = Tc*sqrt(RR)
                QRSTc = [QRST_PS QRST_ST(21:end-20)]; % Corrected PQRST
                % Find TQ length
                TQlength = rr(beatNr) - length(QRSTc) + Rind - RindNext;
                % Protect against the error of to low heart rate
                if  TQlength < 2
                    TQlength = 2;
                end
                % Interpolate TQ interval
                x = [1 TQlength];
                xi = 1:1:TQlength;
                y = [QRSTc(1,end) QRSTtempNext(1, 1)];
                TQ = interp1(x,y,xi,'linear');
                ecgSig = [ecgSig QRSTc TQ];             
                if lead == 15
                    rIndex = [rIndex (rIndex(1,end) + TQlength + length(QRSTc) - Rind + RindNext)];
                end
            end
    if cnt == 1        
    multileadVA = zeros(15, length(ecgSig));
    end
    end
    if lead == 15
        rr = diff(rIndex);
        QRSindex = rIndex(1:end-1);  
    end
    multileadVA(lead, :) = ecgSig;
end
ecgLength = length(ecgSig);
end