function HRV=get_hrv(hrv_now)
% Loads QRS peak detector location file and calculates all heart rate
% variability features (HRV).
%
% Time domain features:
%               SDNN: Standard deviation of all NN intervals
%              SDANN: Standard deviation of mean of NN intervals in 5 min
%                     windows
%              RMSSD: Square root of mean of squares of differences between
%                     adjacent NN intervals
%          SDNNindex: mean of standard deviation of all NN intervals in all
%                     5 mins windows
%               SDSD: Standard deviation of differences between adjacent NN
%                     intervals
%               NN50: Number of pairs of adjacent NN intervals differing by
%                     more than 50ms
%              pNN50: Percentage NN50 (NN50/totan number of NN intervals)
%
% Frequency domain features
%           VLF_peak: Frequency of maximum peak in very low frequency range
%            LF_peak: Frequency of maximum peak in low frequency range
%            HF_peak: Frequency of maximum peak in high frequency range
%     VLF_power_perc: Percentage of total power in VLF range
%      LF_power_perc: Percentage of total power in LF range
%      HF_power_perc: Percentage of total power in HF range
%      LF_power_norm: Percentage of low and high frequency power in the low
%                     frequency range
%      HF_power_norm: Percentage of low and high frequency power in the
%                     high frequency range
%        LF_HF_ratio: Ratio of low to high frequency power
%
% Non-linear features
%                SD1: Standard deviation in y=-x direction of Poincare plot
%                SD2: Standard deviation in y=x direction of Poincare plot
%               saen: Sample Entropy
%               apen: Approximate Entropy
%
%            Recurrence Quantification Analysis 
%                 RR: Recurrence Rate
%                Det: Determinism
%               ENTR: Shannon Entropy
%                  L: Average diagonal line length
%
%               TKEO: Mean Teager-Kaiser Energy Operator%   
%             DFA_a2: Detrended Fluctuation Analysis Exponent%                 
%                 LZ: Lempel Ziv Complexity
%
%
% --
% ECG classification from single-lead segments using Deep Convolutional Neural 
% Networks and Feature-Based Approaches - December 2017
% 
% Released under the GNU General Public License
%
% Copyright (C) 2017  Fernando Andreotti, Oliver Carr
% University of Oxford, Insitute of Biomedical Engineering, CIBIM Lab - Oxford 2017
% fernando.andreotti@eng.ox.ac.uk
%
% 
% For more information visit: https://github.com/fernandoandreotti/cinc-challenge2017
% 
% Referencing this work
%
% Andreotti, F., Carr, O., Pimentel, M.A.F., Mahdi, A., & De Vos, M. (2017). 
% Comparing Feature Based Classifiers and Convolutional Neural Networks to Detect 
% Arrhythmia from Short Segments of ECG. In Computing in Cardiology. Rennes (France).
%
% Last updated : December 2017
% 
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
% 
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
% 
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


% load QRS time data

vlow_thresh=0.003;
low_thresh=0.04; % set frequency ranges for very low, low and high ranges (Hz)
mid_thresh=0.15;
high_thresh=0.4;

HRV=struct; % create HRV structure

%%

NN=1000*(hrv_now(:,1)-hrv_now(1,1));  % convert data points to time (ms)

NN_int_sec=1000*hrv_now(:,2); % find NN intervals (ms)

NN_mat=[NN,NN_int_sec]; %(ms)

HRV.mRR=mean(NN_int_sec);

HRV.medRR=median(NN_int_sec);

HRV.SDNN=std(NN_int_sec); 

D=diff(NN_int_sec);

D_sq=D.^2;

N=length(NN_int_sec);

mean_diff_int=sum((D_sq))/(N-1);

HRV.RMSSD=sqrt(mean_diff_int);

HRV.SDSD=std(D);
  
HRV.NN50=sum(abs(D)>50);   

HRV.pNN50=HRV.NN50/length(NN_int_sec);

% Power SPectral Density analysis ***** FOR UNEVEN TIME SPACING??? *****
if length(NN_mat(:,2))>3
[Pxx,F]=plomb(NN_mat(:,2)./1000-mean(NN_mat(:,2)./1000),NN_mat(:,1)./1000,0.001:0.001:0.7);

[~,vlow_index]=min(abs(F-vlow_thresh));
[~,low_index]=min(abs(F-low_thresh));
[~,mid_index]=min(abs(F-mid_thresh));
[~,high_index]=min(abs(F-high_thresh));

% VLF=Pxx(vlow_index:low_index);
LF=Pxx(low_index+1:mid_index);
HF=Pxx(mid_index+1:high_index);

% [~,very_low_peak_index]=max(VLF);
[~,low_peak_index]=max(LF);
[~,high_peak_index]=max(HF);

% HRV.VLF_peak=F(very_low_peak_index);
HRV.LF_peak=F(low_peak_index+low_index);
HRV.HF_peak=F(high_peak_index+mid_index);

HRV.total_power=trapz(F,Pxx)*1000000;
if vlow_index~=1
%     HRV.VLF_power=trapz(F(vlow_index-1:low_index),Pxx(vlow_index-1:low_index))*1000000;%sum(VLF)*1000000;
    HRV.LF_power=trapz(F(low_index-1:mid_index),Pxx(low_index-1:mid_index))*1000000;%sum(LF)*1000000;
    HRV.HF_power=trapz(F(mid_index-1:high_index),Pxx(mid_index-1:high_index))*1000000;%sum(HF)*1000000;
elseif low_index~=1
%     HRV.VLF_power=trapz(F(vlow_index:low_index),Pxx(vlow_index:low_index))*1000000;%sum(VLF)*1000000;
    HRV.LF_power=trapz(F(low_index-1:mid_index),Pxx(low_index-1:mid_index))*1000000;%sum(LF)*1000000;
    HRV.HF_power=trapz(F(mid_index-1:high_index),Pxx(mid_index-1:high_index))*1000000;%sum(HF)*1000000;
elseif mid_index~=1
%     HRV.VLF_power=trapz(F(vlow_index:low_index),Pxx(vlow_index:low_index))*1000000;%sum(VLF)*1000000;
    HRV.LF_power=trapz(F(low_index:mid_index),Pxx(low_index:mid_index))*1000000;%sum(LF)*1000000;
    HRV.HF_power=trapz(F(mid_index-1:high_index),Pxx(mid_index-1:high_index))*1000000;%sum(HF)*1000000;
elseif high_index<length(Pxx)
%     HRV.VLF_power=trapz(F(vlow_index:low_index),Pxx(vlow_index:low_index))*1000000;%sum(VLF)*1000000;
    HRV.LF_power=trapz(F(low_index:mid_index),Pxx(low_index:mid_index))*1000000;%sum(LF)*1000000;
    HRV.HF_power=trapz(F(mid_index:high_index+1),Pxx(mid_index:high_index+1))*1000000;%sum(HF)*1000000;
else
%     HRV.VLF_power=trapz(F(vlow_index:low_index),Pxx(vlow_index:low_index))*1000000;%sum(VLF)*1000000;
    HRV.LF_power=trapz(F(low_index:mid_index),Pxx(low_index:mid_index))*1000000;%sum(LF)*1000000;
    HRV.HF_power=trapz(F(mid_index:high_index),Pxx(mid_index:high_index))*1000000;%sum(HF)*1000000;    
end

HRV.LF_power_norm=100*HRV.LF_power/(trapz(F,Pxx)*1000000);
HRV.HF_power_norm=100*HRV.HF_power/(trapz(F,Pxx)*1000000);

HRV.LF_HF_ratio=HRV.LF_power/HRV.HF_power;
else
    HRV.VLF_power=NaN;
    HRV.LF_power=NaN;
    HRV.HF_power=NaN;

    HRV.LF_power_norm=NaN;
    HRV.HF_power_norm=NaN;

    HRV.LF_HF_ratio=NaN;
end

HRV.SD1=sqrt(var(((1/sqrt(2))*hrv_now(1:end-1,2))-((1/sqrt(2))*hrv_now(2:end,2))));
HRV.SD2=sqrt(abs((2*std(hrv_now(:,2))^2)-HRV.SD1^2));

if length(hrv_now(:,2))<5
    HRV.saen=NaN;
    HRV.apen=NaN;
else
    HRV.saen = SampEn( 2, 0.2*std(hrv_now(:,2)), hrv_now(:,2) );
    HRV.apen = ApEn( 2, 0.2*std(hrv_now(:,2)), hrv_now(:,2), 1);
end

[RP,~] = RPplot(hrv_now(:,2)',3,1,0.5,0);
[RR1,DET1,ENTR1,L1] = Recu_RQA(RP,0);

HRV.RR=RR1; % Recurrence Rate
HRV.DET=DET1; %Determinism
HRV.ENTR=ENTR1; %Shannon Entropy
HRV.L=L1; %Average diagonal line length

% Teager-Kaiser Energy Operator
HRV.TKEO=mean(TKEO(hrv_now(:,2)));

% Detrended Fluctuation Analysis
[~,alpha2]=DFA_main_a2(hrv_now(:,2)');

HRV.DFA_a2=alpha2;

% Lempel Ziv Complexity
bin_sig=zeros(size(hrv_now(:,2)));
bin_sig(hrv_now(:,2)>nanmedian(hrv_now(:,2)))=1;
if length(bin_sig)<3
    HRV.LZ=NaN;
else
[C,~,~]=calc_lz_complexity(bin_sig, 'exhaustive', 1);

HRV.LZ=C;
end






