|
| 1 | +function [DFAExponent, meanDF, windowSizes] = calculateDFA(Signal, windowSizes, windowOverlap) |
| 2 | +% Originally created by Richard Hardstone (2020), rhardstone@gmail.com |
| 3 | + |
| 4 | +% This program is free software: you can redistribute it and/or modify |
| 5 | +% it under the terms of the GNU General Public License as published by |
| 6 | +% the Free Software Foundation, either version 3 of the License, or |
| 7 | +% (at your option) any later version. |
| 8 | +% |
| 9 | +% This program is distributed in the hope that it will be useful, |
| 10 | +% but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | +% GNU General Public License for more details. |
| 13 | +% |
| 14 | +% You should have received a copy of the GNU General Public License |
| 15 | +% along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | + |
| 17 | +% Calculates DFA (on a set of window sizes) for signal |
| 18 | +% Steps refer to description of DFA algorithm in Figure 1 of: |
| 19 | + % Detrended fluctuation analysis: a scale-free view on neuronal oscillations |
| 20 | + % Hardstone, Richard, Simon-Shlomo Poil, Giuseppina Schiavone, Rick Jansen, Vadim V. Nikulin, Huibert D. Mansvelder, and Klaus Linkenkaer-Hansen |
| 21 | + % Frontiers in physiology 3 (2012): 450. |
| 22 | + |
| 23 | + |
| 24 | +% Signal dimensions (numSamples,numChannels) |
| 25 | +% windowSize in samples |
| 26 | +% windowOverlap is fraction of overlap between windows (0-1) |
| 27 | +% Signal dimensions (numSamples,numChannels) |
| 28 | +% windowSize in samples |
| 29 | +% windowOverlap in samples |
| 30 | + |
| 31 | + |
| 32 | +lengthSignal = size(Signal,1); |
| 33 | +numChannels = size(Signal,2); |
| 34 | +meanDF = zeros(numChannels,length(windowSizes)); |
| 35 | +DFAExponent = zeros(numChannels,1); |
| 36 | +windowSizes = windowSizes(:); |
| 37 | + |
| 38 | +for i_channel = 1:size(Signal,2) |
| 39 | + for i_windowSize = 1:length(windowSizes) |
| 40 | + windowOffset = floor(windowSizes(i_windowSize) * (1-windowOverlap)); |
| 41 | + allWindowIndex = createWindowIndices(lengthSignal, windowSizes(i_windowSize), windowOffset); |
| 42 | + originalAmplitude = Signal(:,i_channel); |
| 43 | + signalProfile = cumsum(originalAmplitude - mean(originalAmplitude)); %Step A->B |
| 44 | + xSignal = signalProfile(allWindowIndex); %Step B->C |
| 45 | + dSignal = detrend(xSignal'); %Step C |
| 46 | + w_detrendedFluctuations = std(dSignal,1); %std(dSignal,1) means normalized by N instead of N-1 |
| 47 | + meanDF(i_channel,i_windowSize) = mean(w_detrendedFluctuations); |
| 48 | + end |
| 49 | + |
| 50 | + X = [ones(length(windowSizes),1) log10(windowSizes)]; |
| 51 | + Y = log10(meanDF(i_channel,:))'; |
| 52 | + if length(windowSizes) > 1 |
| 53 | + regressOutput = regress(Y,X); |
| 54 | + DFAExponent(i_channel) = regressOutput(2,1); %Step D |
| 55 | + else |
| 56 | + DFAExponent(i_channel) = nan; |
| 57 | + end |
| 58 | +end |
| 59 | + |
| 60 | +function allWindowIndex = createWindowIndices(lengthSignal, lengthWindow, windowOffset) |
| 61 | +%Gets indices for a set of windows of size (lengthWindow) with a set overlap between them |
| 62 | + |
| 63 | +windowStarts = (1:windowOffset:lengthSignal-lengthWindow+1)-1; |
| 64 | +numWindows = length(windowStarts); |
| 65 | + |
| 66 | +oneWindowIndex = 1:lengthWindow; |
| 67 | +allWindowIndex = repmat(oneWindowIndex,[numWindows,1]); |
| 68 | + |
| 69 | +allWindowIndex = allWindowIndex + repmat(windowStarts',[1 lengthWindow]); |
| 70 | + |
0 commit comments