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

[ENH] implement one-way ANOVA at group level to compare groups #1296

Merged
merged 34 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
6e3313f
start adding a 3 group dataset
Remi-Gau Jul 24, 2024
d5384db
[ENH] use sub commands for python CLI (#1292)
Remi-Gau Jul 24, 2024
443282e
add temp script for boutiques and bids model graph
Remi-Gau Jul 10, 2024
10d8055
start adding tweaks
Remi-Gau Jul 24, 2024
0fbb44c
Merge remote-tracking branch 'upstream/main' into enh/1229
Remi-Gau Jul 24, 2024
df5e0a0
try 3 groups
Remi-Gau Jul 24, 2024
e1ee976
rename file
Remi-Gau Jul 25, 2024
ab138de
update code and tests
Remi-Gau Jul 25, 2024
ed1e2b3
add multi group demo
Remi-Gau Jul 25, 2024
40fc905
Merge remote-tracking branch 'upstream/main' into enh/1229
Remi-Gau Jul 25, 2024
7f0d048
fixes
Remi-Gau Jul 25, 2024
e79deeb
adapt example
Remi-Gau Jul 25, 2024
8efb9ad
fix contrasts
Remi-Gau Jul 25, 2024
2d23f73
deal with results
Remi-Gau Jul 28, 2024
79c07c1
update doc
Remi-Gau Jul 28, 2024
51ceec6
minor changes
Remi-Gau Jul 28, 2024
0e0cafe
tmp
Remi-Gau Jul 28, 2024
b6aa23f
refactor
Remi-Gau Jul 29, 2024
b472555
refactor
Remi-Gau Jul 29, 2024
ffc5837
refactor
Remi-Gau Jul 29, 2024
5f5f4f9
several fixes
Remi-Gau Jul 29, 2024
be76730
several fixes
Remi-Gau Jul 29, 2024
186d10b
fix and refactor
Remi-Gau Jul 29, 2024
e3e33bc
fix and refactor
Remi-Gau Jul 29, 2024
3918ad5
fix and refactor
Remi-Gau Jul 29, 2024
71ea4d4
fix models
Remi-Gau Jul 29, 2024
5884be4
fix
Remi-Gau Jul 29, 2024
8a01281
fix
Remi-Gau Jul 29, 2024
4f103ed
fix fast tests
Remi-Gau Jul 30, 2024
b3722d5
fixes
Remi-Gau Jul 30, 2024
1101fa4
fix and implement F test
Remi-Gau Jul 30, 2024
642ac8f
run group level node by node
Remi-Gau Jul 30, 2024
c844907
add F test to demo
Remi-Gau Jul 30, 2024
f84cbb3
octave fix
Remi-Gau Jul 30, 2024
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
1 change: 1 addition & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ exclude =
tests/*
_version.py
demos/*
WIP/*
count = True
show-source = True
statistics = True
14 changes: 7 additions & 7 deletions .github/workflows/run_tests_cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ jobs:
coverage run --source src -m pytest
coverage xml

- name: Code coverage
uses: codecov/codecov-action@v4
with:
file: coverage.xml
flags: cli
name: codecov-cli
fail_ci_if_error: false
# - name: Code coverage
# uses: codecov/codecov-action@v4
# with:
# file: coverage.xml
# flags: cli
# name: codecov-cli
# fail_ci_if_error: false
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

* [ENH] add support for one-way ANOVA across groups at the group level #1296 by @Remi-Gau
* [ENH] allow for 2 sample T-Test, within group T-Test and one-way ANOVA to ne more flexible with respect to what praticipants.tsv column to use to allocate subjects in each group #1296 by @Remi-Gau
* [ENH] make `addConfoundsToDesignMatrix` a method of `BidsModel` #1294 by @Remi-Gau
* [ENH] add Apptainer definition #1254 by @Remi-Gau and @monique2208
* [ENH] allow to copy anat only on raw datasets #1181 by @Remi-Gau
Expand All @@ -43,7 +45,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed


* [ENH] align specification of F contrasts on the BIDS stats model: they should now be specified as a 2D matrix and not a 1D vector. #1276 @Remi-Gau
* [DOC] change theme and structure of the documentation #1256 @Remi-Gau
* [REF] Refactor and update CLI in #1096 @Remi-Gau
Expand Down
43 changes: 43 additions & 0 deletions WIP/find_data_set_with_3_groups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from pathlib import Path

import pandas as pd
from pandas.errors import ParserError

openneuro = Path("/home/remi/datalad/datasets.datalad.org/openneuro")

for ds in openneuro.iterdir():
file = ds / "participants.tsv"

if file.exists():

try:
df = pd.read_csv(file, sep="\t")
except ParserError:
...

if len(df) < 10:
continue
if "group" in df.columns:
col = "group"
elif "Group" in df.columns:
col = "Group"
else:
continue
if len(df[col].value_counts()) < 3:
continue
if "age" in df.columns and df["age"].mean() < 18:
continue
bold_files = list(ds.glob("**/*bold*"))

has_func = len(bold_files) > 0
if not has_func:
continue

tasks = {x.name.split("task-")[1].split("_")[0] for x in bold_files}
if len(tasks) == 1 and "rest" in tasks:
continue

print()
print(file)
print(df[col].value_counts())
print(tasks)
10 changes: 10 additions & 0 deletions demos/openneuro/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,13 @@ data_ds002799:
datalad get -d inputs/ds002799 inputs/ds002799/derivatives/fmriprep/sub-292/*/func/*tsv
datalad get -d inputs/ds002799 inputs/ds002799/derivatives/fmriprep/sub-30[27]/*/func/*MNI152NLin2009cAsym* -J 2
datalad get -d inputs/ds002799 inputs/ds002799/derivatives/fmriprep/sub-30[27]/*/func/*tsv -J 2

data_ds003397:
mkdir -p inputs
cd inputs && datalad install ///openneuro/ds003397
cd inputs && datalad install https://github.com/OpenNeuroDerivatives/ds003397-fmriprep
cd inputs/ds003397-fmriprep && datalad get sub-[01][1267]/anat/*MNI152NLin2009cAsym*T1w.nii.gz -J 12
cd inputs/ds003397-fmriprep && datalad get sub-[01][1267]/anat/*mask*.nii.gz -J 12
cd inputs/ds003397-fmriprep && datalad get sub-[01][1267]/func/*time*tsv -J 12
cd inputs/ds003397-fmriprep && datalad get sub-[01][1267]/func/*json -J 12
cd inputs/ds003397-fmriprep && datalad get sub-[01][1267]/func/*MNI152NLin2009cAsym*desc-preproc*bold.nii.gz -J 12
2 changes: 2 additions & 0 deletions demos/openneuro/ds000114_run.m
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
% Demo to compare activations across sessions.

% (C) Copyright 2023 bidspm developers

clear;
Expand Down
61 changes: 61 additions & 0 deletions demos/openneuro/ds003397_run.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
% Run a one-way ANOVA across group
%
% Only a few subjects are run because of the large size of each run.

% (C) Copyright 2024 bidspm developers

clear;
clc;

addpath(fullfile(pwd, '..', '..'));
bidspm();

task = 'checkerboard';

% The directory where the data are located
root_dir = fileparts(mfilename('fullpath'));
bids_dir = fullfile(root_dir, 'inputs', 'ds003397');
fmriprep_dir = fullfile(root_dir, 'inputs', 'ds003397-fmriprep');
output_dir = fullfile(root_dir, 'outputs', 'ds003397', 'derivatives');

space = {'MNI152NLin2009cAsym'};
participant_label = {'01', '06', '11', '12'};

% Copy (& smooth)
FWHM = 0;
bidspm(fmriprep_dir, output_dir, 'subject', ...
'participant_label', participant_label, ...
'action', 'smooth', ...
'task', task, ...
'space', space, ...
'fwhm', FWHM, ...
'verbosity', 3);

%% Stats
preproc_dir = fullfile(output_dir, 'bidspm-preproc');

model_file = fullfile(root_dir, ...
'models', ...
'model-ds003397_smdl.json');

bidspm(bids_dir, output_dir, 'subject', ...
'participant_label', participant_label, ...
'action', 'stats', ...
'preproc_dir', preproc_dir, ...
'model_file', model_file, ...
'roi_atlas', 'hcpex', ...
'space', space, ...
'fwhm', 0, ...
'skip_validation', true, ...
'verbosity', 3);

bidspm(bids_dir, output_dir, 'dataset', ...
'participant_label', participant_label, ...
'action', 'stats', ...
'preproc_dir', preproc_dir, ...
'model_file', model_file, ...
'roi_atlas', 'hcpex', ...
'space', space, ...
'fwhm', 0, ...
'skip_validation', true, ...
'verbosity', 3);
218 changes: 218 additions & 0 deletions demos/openneuro/models/model-ds003397_smdl.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
{
"Name": "1_way_ANOVA",
"BIDSModelVersion": "1.0.0",
"Input": {
"task": [
"checkerboard"
],
"space": [
"MNI152NLin2009cAsym"
]
},
"Nodes": [
{
"Level": "Run",
"Name": "run_level",
"GroupBy": [
"run",
"subject"
],
"Model": {
"Type": "glm",
"X": [
"trial_type.flashing checkerboard",
"trans_?",
"rot_?"
],
"HRF": {
"Variables": [
"trial_type.flashing checkerboard"
],
"Model": "spm"
}
},
"Contrasts": [
{
"Name": "flashing checkerboard",
"ConditionList": [
"trial_type.flashing checkerboard"
],
"Weights": [
1
],
"Test": "t"
}
]
},
{
"Level": "Subject",
"Name": "subject_level",
"GroupBy": [
"contrast",
"subject"
],
"Model": {
"Type": "glm",
"X": [
1
],
"Software": {
"bidspm": {
"Results": [
{
"name": [
"flashing checkerboard"
],
"p": 0.05,
"MC": "FWE",
"png": true,
"binary": false,
"nidm": false,
"montage": {
"do": true,
"slices": [
-4,
0,
4,
8,
16
],
"background": {
"suffix": "T1w",
"desc": "preproc",
"modality": "anat"
}
}
}
]
}
}
},
"DummyContrasts": {
"Test": "t"
}
},
{
"Level": "Dataset",
"Name": "dataset_level",
"Description": "average across all subjects",
"GroupBy": [
"contrast"
],
"Model": {
"Type": "glm",
"X": [
1
]
}
},
{
"Level": "Dataset",
"Name": "between_groups",
"Description": "one way anova",
"GroupBy": [
"contrast"
],
"Model": {
"Type": "glm",
"X": [
1,
"group"
],
"Software": {
"bidspm": {
"Results": [
{
"name": [
"B > I",
"average across groups"
],
"p": 0.01,
"MC": "FWE",
"png": true,
"binary": false,
"nidm": false,
"montage": {
"do": false
}
}
]
}
}
},
"Contrasts": [
{
"Name": "B > I",
"ConditionList": [
"group.B",
"group.I"
],
"Weights": [
1,
-1
],
"Test": "t"
},
{
"Name": "average across groups",
"ConditionList": [
"group.B",
"group.I",
"group.BI"
],
"Weights": [
1,
1,
1
],
"Test": "t"
},
{
"Name": "some F test",
"ConditionList": [
"group.B",
"group.BI",
"group.I"
],
"Weights": [
[
1,
0,
0
],
[
0,
1,
0
],
[
0,
0,
1
]
],
"Test": "F"
}
]
}
],
"Edges": [
{
"Source": "run_level",
"Destination": "subject_level"
},
{
"Source": "subject_level",
"Destination": "dataset_level"
},
{
"Source": "subject_level",
"Destination": "between_groups",
"Filter": {
"contrast": [
"flashing checkerboard"
]
}
}
]
}
Loading
Loading