%% Gait Variability Analysis CLBP
% Table of Contents
% Clear and close;
% Load data;
% Settings;
% Plot the data;
% Calculate parameters;
%     Index of harmonicity (Lamoth et al. 2002)
%     Lyapunov exponents (Wolfs vs. Rosenstein)
% Visualize step detection;
% AggregateFunction (seperate analysis per minute);
% Dimension Reduction

% Gait Variability Analysis 
% Script created for MAP 2020-2021
% adapted from Claudine Lamoth and Iris Hagoort
% version1 October 2020

% Input: needs mat file which contains all raw accelerometer data
% Input: needs excel file containing the participant information including
% leg length.

%
%% Clear and close;

clear;
close all;

%
%% Load data;
% Select 1 trial. For loop to import all data will be used at a later stage

[FNaam,FilePad] = uigetfile('*.xls','Load phyphox data...');
filename =[FilePad FNaam];
PhyphoxData = xlsread(filename)

%load('Phyphoxdata.mat'); % loads accelerometer data, is stored in struct with name AccData
%load('ExcelInfo.mat');
%Participants = fields(AccData);

%
%% Settings;

LegLength = 98 % LegLength info not available!
%LegLengths = excel.data.GeneralInformation(:,5); % leglength info is in 5th column
LegLengthsM = LegLength/100;           % convert to m
t1 = length(PhyphoxData(:,1));         % Number of Samples


FS = 100;                                  % sample frequency
Time_ms = PhyphoxData(:,1);
accX = PhyphoxData(:,2);
accY = PhyphoxData(:,3);
accZ = PhyphoxData(:,4);
AccData = (PhyphoxData(:,[1 2 3 4]));      % matrix with accelerometer data

Start = 1;                  % Start time (s) for plot
End = 60;                   % End time (s) for plot
T1 = Start*FS;              % Start time calculated from Hz
T2 = End*FS;                % End time calculated from Hz
c = (Start:(1/FS):End)';    % Time STEPSIZE = 1/100

%
%% Plot the data;
% (1) first step in notebook
% 1st column is time data (ms)
% 2nd column is X, medio-lateral: + left, - right
% 3rd column is Y, vertical: + downwards, - upwards
% 4th column is Z, anterior- posterior : + forwards, - backwards

AccX = accX(T1:T2);                         % Signal over timeframe
AccY = accY(T1:T2);                         % Signal over timeframe
AccZ = accZ(T1:T2);                         % Signal over timeframe

figure(1);
plot(c,AccX,c,AccY,c,AccZ);                % Plot signal over timeframe
title('acc signal not filtered - First Minute')
xlabel('Time (s)');
ylabel('acceleration (g)');
legend('X - ML','Y - Vertical','Z - AP')

%%
%%
%% Calculate parameters;
% calculate only for the first participant;

inputData = AccData;
WindowLength = FS*10;               % why FS*10? 
ApplyRealignment = true;            % reorder data to  1 = V; 2= ML, 3 = AP
ApplyRemoveSteps = false;           % if true - removes first 30 and last 30 steps
[ResultStruct] = GaitOutcomesTrunkAccFuncIH(inputData,FS,LegLength,WindowLength,ApplyRealignment,ApplyRemoveSteps)

% output:
% - NaN GaitSymm_V:
% Gait Synmmetry is only informative in AP/V direction: See Tura A, Raggi M, Rocchi L, Cutti AG, Chiari L: Gait symmetry and regularity in                         transfemoral amputees assessed by trunk accelerations. J Neuroeng Rehabil 2010, 7:4
% - SampEn has two advantages over ApEn: data length independence and a relatively trouble-free implementation.
% - Some Settings ResultStruct
% IgnoreMinMaxStrides = 0.10;                   % Number or percentage of highest&lowest values ignored for improved variability estimation
% N_Harm = 12;                                             % Number of harmonics used for harmonic ratio, index of harmonicity and phase fluctuation
% Lyap_m = 7;                                                % Embedding dimension (used in Lyapunov estimations)
% Lyap_FitWinLen = round(60/100*FS);       % Fitting window length (used in Lyapunov estimations Rosenstein's method)
% Sen_m = 5;                                                 % Dimension, the length of the subseries to be matched (used in sample entropy estimation)
% Sen_r = 0.3;                                                % Tolerance, the maximum distance between two samples to qualify as match, relative to std of DataIn (used in sample entropy estimation)
%% Index of harmonicity (Lamoth et al. 2002)
% by means of a discrete Fourier transform (DFT). The peak power at the first six harmonics was estimated and, subsequently, the index of harmonicity was defined as ; FORMULA
% where P0 is the power spectral density of the fundamental frequency (first harmonic) and $ Pi the cumulative sum of power spectral density of the fundamental frequency and the first five superharmonics. A power ratio of 1 indicates that the rotation of the pelvis or the thorax is perfectly harmonic. 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. All power spectral densities were normalized by dividing the power by the sum of the total power spectrum, which equals the variance.
%% Lyapunov exponents (Wolfs vs. Rosenstein)
% The W-algorithm is advocated for use when examining local dynamic stability with small gait data sets.
%% Visualize step detection;
% function [ResultStruct] = GaitVariabilityAnalysisIH_WithoutTurns(inputData,FS,LegLength,ApplyRealignment,ApplyRemoveSteps);
% script for analysing straight parts
% (1) Realign Data

%% Realign data
data = inputData(:, [3,2,4]); % reorder data to  1 = V; 2= ML, 3 = AP

%Realign sensor data to VT-ML-AP frame
if ApplyRealignment % apply relignment as described in Rispens S, Pijnappels M, van Schooten K, Beek PJ, Daffertshofer A, van Die?n JH (2014).
    % Consistency of gait characteristics as determined from acceleration data collected at different trunk locations. Gait Posture 2014;40(1):187-92.
    [RealignedAcc, ~] = RealignSensorSignalHRAmp(data, FS);
    dataAcc = RealignedAcc;
end

% (2) Filter Data


%% Filter data strongly & Determine location of steps

% Filter  data
[B,A] = butter(2,3/(FS/2),'low'); % Filters data very strongly which is needed to determine turns correctly
dataStepDetection = filtfilt(B,A,dataAcc);

% (3) Determine Location of steps

% Determine steps;

%%%%%%% HIER MISSCHIEN ALTERNATIEF VOOR VAN RISPENS %%%%%%%%%%%%%

% Explanation of method: https://nl.mathworks.com/help/supportpkg/beagleboneblue/ref/counting-steps-using-beagleboneblue-hardware-example.html
% From website: To convert the XYZ acceleration vectors at each point in time into scalar values,
% calculate the magnitude of each vector. This way, you can detect large changes in overall acceleration,
% such as steps taken while walking, regardless of device orientation.

magfilt = sqrt(sum((dataStepDetection(:,1).^2) + (dataStepDetection(:,2).^2) + (dataStepDetection(:,3).^2), 2));
magNoGfilt = magfilt - mean(magfilt);
minPeakHeight2 = std(magNoGfilt);
[pks, locs] = findpeaks(magNoGfilt, 'MINPEAKHEIGHT', minPeakHeight2); % for step detection
numStepsOption2_filt = numel(pks); % counts number of steps;

% (4) Determine location of turns

%% Determine locations of turns;

diffLocs = diff(locs); % calculates difference in step location
avg_diffLocs = mean(diffLocs); % average distance between steps
std_diffLocs = std(diffLocs); % standard deviation of distance between steps

figure(2);
findpeaks(diffLocs, 'MINPEAKHEIGHT', avg_diffLocs, 'MINPEAKDISTANCE',5); % these values have been chosen based on visual inspection of the signal
line([1 length(diffLocs)],[avg_diffLocs avg_diffLocs])
[pks_diffLocs, locs_diffLocs] = findpeaks(diffLocs, 'MINPEAKHEIGHT', avg_diffLocs,'MINPEAKDISTANCE',5);
locsTurns =  [locs(locs_diffLocs),  locs(locs_diffLocs+1)];

% (5) Visualize turns

%% Visualizing turns

% Duplying signal + visualing
% to make second signal with the locations of the turns filled with NaN, so
% that both signals can be plotted above each other in a different colour

magNoGfilt_copy = magNoGfilt;
for k = 1: size(locsTurns,1);
    magNoGfilt_copy(locsTurns(k,1):locsTurns(k,2)) = NaN;
end


% visualising signal;
figure;
subplot(2,1,1)
hold on;
plot(magNoGfilt,'b')
plot(magNoGfilt_copy, 'r');
title('Inside Straight: Filtered data with turns highlighted in blue')
hold off;

% (6) CALCULATIONS

%% Calculation
% VRAAG LAURENS zie blauwe blaadje

startPos = 1;
for i = 1: size(locsTurns,1);
    endPos = locsTurns(i,1)-1;
    
    inputData = dataAcc(startPos:endPos,:);
    WindowLen = size(inputData,1);
    ApplyRealignment = false;
    [ResultStruct] = GaitOutcomesTrunkAccFuncIH(inputData,FS,LegLength,WindowLen,ApplyRealignment,ApplyRemoveSteps); % Naam van deze moet nog aangepast.
    
    if i ==1 % only the firs time
        Parameters = fieldnames(ResultStruct);
        NrParameters = length(Parameters);
    end
    
    for j = 1:NrParameters % only works if for every bin we get the same outcomes (which is the case in this script)
        DataStraight.([char(Parameters(j))])(i) = ResultStruct.([char(Parameters(j))]);
    end
    startPos = locsTurns(i,2)+1;
    
end

clear ResultStruct;

% Calculate mean over the bins without turns to get 1 outcome value per parameter for inside
% straight;

for j = 1:NrParameters;
    ResultStruct.([char(Parameters(j))]) = nanmean(DataStraight.([char(Parameters(j))]))
end

%% AggregateFunction (seperate analysis per minute);
% see AggregateEpisodeValues.m
%
%% Dimension Reduction
% relationship between pain score?
% PCA
%
%
%