MAP_Gait_Dynamics/HarmonicityFrequency.m

80 lines
4.0 KiB
Matlab
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

function [ResultStruct] = HarmonicityFrequency(dataAccCut_filt,P,F, StrideFrequency,dF,LowFrequentPowerThresholds,N_Harm,FS,AccVectorLen,ResultStruct)
%LD 15-04-2021: Solve problem finding fundamental frequency in power
%spectral density STRIDE - VS STEP frequency.
% Add sum of power spectra (as a rotation-invariant spectrum)
P = [P,sum(P,2)];
PS = sqrt(P);
% Calculate the measures for the power per separate dimension
for i=1:size(P,2);
% Relative cumulative power and frequencies that correspond to these cumulative powers
PCumRel = cumsum(P(:,i))/sum(P(:,i));
PSCumRel = cumsum(PS(:,i))/sum(PS(:,i));
FCumRel = F+0.5*dF;
% Derive relative cumulative power for threshold frequencies
Nfreqs = size(LowFrequentPowerThresholds,2);
LowFrequentPercentage(i,1:Nfreqs) = interp1(FCumRel,PCumRel,LowFrequentPowerThresholds)*100;
% Calculate relative power of first 10 harmonics, taking the power of each harmonic with a band of + and - 10% of the first
% harmonic around it
PHarm = zeros(N_Harm,1);
PSHarm = zeros(N_Harm,1);
for Harm = 1:N_Harm,
FHarmRange = (Harm+[-0.1 0.1])*(StrideFrequency); % In view of possible drift, which could lead to missing or widening peaks, the power spectral density of each peak was calculated within the frequency bands of +0.1 and 0.1 Hz of the peak frequency value.
PHarm(Harm) = diff(interp1(FCumRel,PCumRel,FHarmRange));
PSHarm(Harm) = diff(interp1(FCumRel,PSCumRel,FHarmRange));
end
% Derive index of harmonicity; which is the spectral power of the basic harmonic divided by the sum of the power of first six harmonics
if i == 2 % for ML we expect odd instead of even harmonics
IndexHarmonicity(i) = PHarm(1)/sum(PHarm(1:2:12));
elseif i == 4
IndexHarmonicity(i) = sum(PHarm(1:2))/sum(PHarm(1:12));
else
IndexHarmonicity(i) = PHarm(2)/sum(PHarm(2:2:12));
end
% Calculate the phase speed fluctuations
StrideFreqFluctuation = nan(N_Harm,1);
StrSamples = round(FS/StrideFrequency);
for h=1:N_Harm,
CutOffs = [StrideFrequency*(h-(1/3)) , StrideFrequency*(h+(1/3))]/(FS/2);
if all(CutOffs<1) % for Stride frequencies above FS/20/2, the highest harmonics are not represented in the power spectrum
[b,a] = butter(2,CutOffs);
if i==4 % Take the vector length as a rotation-invariant signal
AccFilt = filtfilt(b,a,AccVectorLen);
else
AccFilt = filtfilt(b,a,dataAccCut_filt(:,i));
end
Phase = unwrap(angle(hilbert(AccFilt)));
SmoothPhase = sgolayfilt(Phase,1,2*(floor(FS/StrideFrequency/2))+1); % This is in fact identical to a boxcar filter with linear extrapolation at the edges
StrideFreqFluctuation(h) = std(Phase(1+StrSamples:end,1)-Phase(1:end-StrSamples,1));
end
end
FrequencyVariability(i) = nansum(StrideFreqFluctuation./(1:N_Harm)'.*PHarm)/nansum(PHarm);
if i<4,
% Derive harmonic ratio (two variants) --> Ratio of the even and
% odd harmonics!
if i == 2 % for ML we expect odd instead of even harmonics
HarmonicRatio(i) = sum(PSHarm(1:2:end-1))/sum(PSHarm(2:2:end)); % relative to summed 3d spectrum
HarmonicRatioP(i) = sum(PHarm(1:2:end-1))/sum(PHarm(2:2:end)); % relative to own spectrum
else
HarmonicRatio(i) = sum(PSHarm(2:2:end))/sum(PSHarm(1:2:end-1));
HarmonicRatioP(i) = sum(PHarm(2:2:end))/sum(PHarm(1:2:end-1));
end
end
end
ResultStruct.IndexHarmonicity_V = IndexHarmonicity(1); % higher smoother more regular patter
ResultStruct.IndexHarmonicity_ML = IndexHarmonicity(2); % higher smoother more regular patter
ResultStruct.IndexHarmonicity_AP = IndexHarmonicity(3); % higher smoother more regular patter
ResultStruct.HarmonicRatio_V = HarmonicRatio(1);
ResultStruct.HarmonicRatio_AP = HarmonicRatio(3);
ResultStruct.StrideFrequency = StrideFrequency;