-
Notifications
You must be signed in to change notification settings - Fork 0
/
RandomizationMethod.m
108 lines (99 loc) · 4.83 KB
/
RandomizationMethod.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
classdef RandomizationMethod
% Non-parametric combining method, e.g. Stouffer's Z.
enumeration
None
Unconstrained
MotionBlocks
end
methods
function i = randomize(this, motion)
arguments
this RandomizationMethod
motion {mustBeNumeric,mustBeVectorOrEmpty} % time x 1 vector of motion, e.g. framewise displacement
end
switch(this)
case RandomizationMethod.Unconstrained
i = RandomizationMethod.randomize_unconstrained(motion);
case RandomizationMethod.MotionBlocks
i = RandomizationMethod.randomize_motion_blocks(motion);
end
end
end
methods (Static)
function obj = getDefaultValue()
% Default method for non-parametric combining is Stouffer's Z score.
obj = RandomizationMethod.MotionBlocks;
end
function i = randomize_none(motion)
arguments
motion {mustBeNumeric,mustBeVectorOrEmpty} % time x 1 vector of motion, e.g. framewise displacement
end
% Don't perform randomization. Simply return the elements of
% the timeseries vector in order.
i = 1:length(motion);
end
function i = randomize_unconstrained(motion)
arguments
motion {mustBeNumeric,mustBeVectorOrEmpty} % time x 1 vector of motion, e.g. framewise displacement
end
% Randomize individual timepoints without any constraints.
%
% Input: time x 1 vector of motion, e.g. framewise displaement
% Output: time x 1 vector of randomized indices
i = randperm(length(motion));
end
function i = randomize_motion_blocks(motion)
arguments
motion {mustBeNumeric,mustBeVectorOrEmpty} % time x 1 vector of motion, e.g. framewise displacement
end
% Divide the data into blocks of consecutive timepoints whose
% motion is either above or below the median, mimicking the
% sizes of consecutive blocks in the unrandomized split half
% model. Then randomize the order of the blocks while
% preserving the number, sizes, and ordering of the data within
% each block.
%
% Input: time x 1 vector of motion, e.g. framewise displaement
% Output: time x 1 vector of randomized indices
% Initialize state.
median_motion = median(motion); % The median motion.
motion_was_high = motion(1) >= median_motion; % True if a time point is above median motion.
num_timepoints = 0; % Number of time points a block.
start_idx = 1; % Starting index of a block.
blocks = []; % Data structure to store block information.
% Iterate over timepoints from start to end.
for j = 1:length(motion)
motion_is_high = motion(j) >= median_motion;
if motion_is_high == motion_was_high
% Increment number of timepoints in this block.
num_timepoints = num_timepoints + 1;
end
if motion_is_high ~= motion_was_high || j == length(motion)
% We have reached the end of a block.
% Append current block information to blocks array.
blocks = [blocks, struct('start_idx', start_idx, 'num_timepoints', num_timepoints)];
% Reset state for next block.
num_timepoints = 1;
start_idx = j;
end
if motion_is_high ~= motion_was_high && j == length(motion)
% Add final block if it has just one timepoint.
blocks = [blocks, struct('start_idx', start_idx, 'num_timepoints', num_timepoints)];
end
% Store motion state for next iteration.
motion_was_high = motion_is_high;
end
% Shuffle the order of the blocks.
blocks = blocks(randperm(numel(blocks)));
% Generate randomized timeseries indices from the blocks.
i = zeros(1, length(motion)); % prellocate memory
j_idx = 1; % starting position
for j_block = 1:numel(blocks)
start_idx = blocks(j_block).start_idx; % starting index for this block
num_timepoints = blocks(j_block).num_timepoints; % number of timepoints in this block
i(j_idx : j_idx+num_timepoints-1) = start_idx : (start_idx + num_timepoints - 1); % fill in indices for this block
j_idx = j_idx + num_timepoints; % advance position in i for next iteration
end
end
end
end