Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] onsets and confounds are saved in the proper dir when there are several tasks #659

Merged
merged 2 commits into from
Jun 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions scripts/group_rm_anova.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
% attempt at a full factorial design
%
%
% (C) Copyright 2019 Remi Gau

clear;
clc;

run ../../initEnv.m;

% in participants.tsv
group_field = 'Group';

opt = opt_stats_group_level();

opt = checkOptions(opt);

opt.verbosity = 2;

opt.pipeline.type = 'stats';

opt.model.bm = BidsModel('file', opt.model.file);

opt.space = opt.model.bm.Input.space;
opt.taskName = opt.model.bm.Input.task;

[BIDS, opt] = getData(opt, opt.dir.preproc);

% for folder naming
node_name = 'rm_anova';
contrasts = 'ALL';
groups = 'ALL';

% Levels names for each factor
group_labels = unique(BIDS.raw.participants.content.(group_field));
task_labels = opt.taskName;
odor_labels = {'almond', 'eucalyptus'};
side_labels = {'left', 'right'};
subject_labels = opt.subjects;

% list of constrasts and the levels they correspond to
contrasts_list = {'olfid_almond_left'; ...
'olfid_almond_right'; ...
'olfid_eucalyptus_left'; ...
'olfid_eucalyptus_right'; ...
'olfloc_almond_left'; ...
'olfloc_almond_right'; ...
'olfloc_eucalyptus_left'; ...
'olfloc_eucalyptus_right'};

contrast_levels = cartesian(1:numel(task_labels), ...
1:numel(odor_labels), ...
1:numel(side_labels));

%%
opt.dir.output = fullfile(opt.dir.stats, 'derivatives', 'cpp_spm-groupStats');
opt.dir.jobs = fullfile(opt.dir.output, 'jobs', strjoin(opt.taskName, ''));

% collect con images
for iSub = 1:numel(subject_labels)
sub_label = subject_labels{iSub};
contrasts_images_filenames{iSub} = findSubjectConImage(opt, ...
sub_label, ...
contrasts_list); %#ok<SAGROW>
end

%% set batch
factor = @(w, x, y, z) struct('name', w, ...
'levels', x, ...
'dept', y, ...
'variance', 1, ...
'gmsca', 0, ...
'ancova', 0);

factorial_design.des.fd.fact(1) = factor('group', numel(group_labels), false);
factorial_design.des.fd.fact(end + 1) = factor('task', numel(task_labels), true);
factorial_design.des.fd.fact(end + 1) = factor('odor', numel(odor_labels), true);
factorial_design.des.fd.fact(end + 1) = factor('side', numel(side_labels), true);
factorial_design.des.fd.fact(end + 1) = factor('subject', numel(subject_labels), false);

factorial_design.dir = {getRFXdir(opt, node_name, contrasts, groups)};

row = 1;

for iSub = 1:numel(subject_labels)

sub_label = opt.subjects{iSub};

sub_idx = strcmp(BIDS.raw.participants.content.participant_id, ['sub-' sub_label]);
participant_group = BIDS.raw.participants.content.(group_field){sub_idx};

group_index = ismember(participant_group, group_labels);

for iCon = 1:numel(contrasts_list)
icell = struct('levels', [group_index contrast_levels(iCon, :) iSub], ...
'scans', {contrasts_images_filenames{iSub}(iCon)});
factorial_design.des.fd.icell(row) = icell;
row = row + 1;
end

end

factorial_design.des.fd.contrasts = 1;

factorial_design.cov = struct('c', {}, ...
'cname', {}, ...
'iCFI', {}, ...
'iCC', {});
factorial_design.multi_cov = struct('files', {}, ...
'iCFI', {}, ...
'iCC', {});

factorial_design.masking.tm.tm_none = 1;
factorial_design.masking.im = 1;
factorial_design.masking.em = {''};

factorial_design.globalc.g_omit = 1;

factorial_design.globalm.gmsca.gmsca_no = 1;
factorial_design.globalm.glonorm = 1;

matlabbatch{1}.spm.stats.factorial_design = factorial_design;

matlabbatch = setBatchEstimateModel(matlabbatch, ...
opt, ...
node_name, ...
contrasts, ...
groups);

%% run

saveAndRunWorkflow(matlabbatch, 'RM ANOVA', opt);
2 changes: 1 addition & 1 deletion src/batches/stats/setBatchFactorialDesign.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

[BIDS, opt] = getData(opt, opt.dir.preproc);

printBatchName('specify group level fmri model', opt);
printBatchName(sprintf('specify group level fmri model for node "%s"', nodeName), opt);

contrasts = getContrastsListForFactorialDesign(opt, nodeName);

Expand Down
4 changes: 4 additions & 0 deletions src/subject_level/createAndReturnCounfoundMatFile.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
bf = bids.File(tsvFile);
bf.extension = '.mat';

% reset task query to original value
% in case we are merging several tasks in one GLM
opt.query.task = opt.taskName;

ffxDir = getFFXdir(bf.entities.sub, opt);
counfoundMatFile = fullfile(ffxDir, bf.filename);

Expand Down
5 changes: 5 additions & 0 deletions src/subject_level/createAndReturnOnsetFile.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@

% move file into the FFX directory
[~, filename, ext] = spm_fileparts(onsetFilename);

% reset task query to original value
% in case we are merging several tasks in one GLM
opt.query.task = opt.taskName;

ffxDir = getFFXdir(subLabel, opt);
movefile(onsetFilename, ffxDir);

Expand Down
2 changes: 2 additions & 0 deletions src/workflows/stats/bidsFFX.m
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,9 @@ function checkRootNode(opt)
end

function matlabbatch = setAction(action, matlabbatch, BIDS, opt, subLabel)

outputDir = getFFXdir(subLabel, opt);

switch action
case 'specify'
matlabbatch = setBatchSubjectLevelGLMSpec(matlabbatch, BIDS, opt, subLabel);
Expand Down
1 change: 1 addition & 0 deletions src/workflows/stats/bidsRFX.m
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
end

if ismember(lower(action), {'rfx', 'contrasts'})
% TODO add possibility to pass several nodeNames at once
if ~isempty(nodeName)
datasetNodes = opt.model.bm.get_nodes('Name', nodeName);
else
Expand Down