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

08MQ reproduction #121

Merged
merged 129 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
6986e90
[BUG] inside unit_tests workflow
bclenet Aug 31, 2023
d6e67f3
Merge branch 'Inria-Empenn:main' into main
bclenet Aug 31, 2023
c3bfc53
Merge branch 'Inria-Empenn:main' into main
bclenet Sep 4, 2023
4b30504
Merge branch 'Inria-Empenn:main' into main
bclenet Sep 19, 2023
fd15ffc
Merge branch 'Inria-Empenn:main' into main
bclenet Sep 21, 2023
6ebe5d2
Merge branch 'Inria-Empenn:main' into main
bclenet Sep 29, 2023
0a584dd
Merge branch 'Inria-Empenn:main' into main
bclenet Sep 29, 2023
e284b80
Merge branch 'Inria-Empenn:main' into main
bclenet Sep 29, 2023
5774813
Merge branch 'Inria-Empenn:main' into main
bclenet Oct 5, 2023
8f12d3d
Merge branch 'Inria-Empenn:main' into main
bclenet Oct 5, 2023
7fde1e1
[08MQ] Preprocessing script in progress
bclenet Oct 6, 2023
2b07afc
Working on preprocessing
bclenet Oct 9, 2023
a454652
Codespell
bclenet Oct 9, 2023
aca4896
Working on pipeline 08MQ
bclenet Oct 10, 2023
91dc744
Merge branch 'Inria-Empenn:main' into main
bclenet Oct 10, 2023
8b48823
Towards a running version of the pipeline
bclenet Oct 11, 2023
ecec8c2
Conforming to Pipeline class + init test module
bclenet Oct 11, 2023
c8db382
Merge branch 'main' into 08MQ_reproduction
bclenet Oct 11, 2023
632f4ef
Towards a running version of the pipeline
bclenet Oct 11, 2023
0e97a61
Towards a running version of the pipeline
bclenet Oct 11, 2023
d3dcc00
Towards a running version of the pipeline
bclenet Oct 13, 2023
988e536
[TEST] runner test not using 08MQ as example anymore
bclenet Oct 13, 2023
ffcdf6e
Issue with SelectFiles' base_directory
bclenet Oct 13, 2023
04d835e
Towards a running version of the pipeline
bclenet Oct 13, 2023
7525309
[TEST] stop using 08MQ in tests
bclenet Oct 13, 2023
da82396
08MQ preprocessing instantiable
bclenet Oct 16, 2023
8fd2195
Compute confounds node
bclenet Oct 17, 2023
9a63118
Group analysis workflow bug
bclenet Oct 17, 2023
95fe702
Group analysis workflow bug
bclenet Oct 17, 2023
1ac7267
Group analysis workflow bug
bclenet Oct 17, 2023
ecc4977
Issue with Registration and Threshold
bclenet Oct 17, 2023
d2cd3e4
Bug with shrink factors
bclenet Oct 17, 2023
0f186a8
Bug with shrink factors
bclenet Oct 17, 2023
2c73712
Bug with shrink factors
bclenet Oct 17, 2023
8dba3d3
ANTs registration [skip ci]
bclenet Oct 18, 2023
7371a95
Testing parameters for antsRegistration [skip ci]
bclenet Oct 18, 2023
82c4f0a
Inverse coregistration transform [skip ci]
bclenet Oct 20, 2023
6495767
Inverse coregistration transform [skip ci]
bclenet Oct 20, 2023
818de15
Compute confounds parameterization [skip ci]
bclenet Oct 20, 2023
735d2f7
ANTs composite transform [skip ci]
bclenet Oct 20, 2023
a1eb020
Trying ANTs' ApplyTransforms
bclenet Oct 23, 2023
3f61b5d
Preprocessing outputs [skip ci]
bclenet Oct 23, 2023
09111a5
Preprocessing outputs [skip ci]
bclenet Oct 23, 2023
cde9f37
Add smoothing [skip ci]
bclenet Oct 23, 2023
098de9f
Motion correction outputs [skip ci]
bclenet Oct 23, 2023
a335fd6
Parse segmentation maps [skip ci]
bclenet Oct 23, 2023
7579d53
Use partial volume files from segmentation [skip ci]
bclenet Oct 23, 2023
d26e188
Use partial volume files from segmentation [skip ci]
bclenet Oct 23, 2023
23d3af9
First try of run level analysis [skip ci]
bclenet Oct 23, 2023
6dfc51f
First try of run level analysis [skip ci]
bclenet Oct 23, 2023
4adfe43
First try of run level analysis [skip ci]
bclenet Oct 23, 2023
af08110
First try of run level analysis [skip ci]
bclenet Oct 23, 2023
dbfed24
First try of run level analysis [skip ci]
bclenet Oct 23, 2023
d2951b3
First try of run level analysis [skip ci]
bclenet Oct 23, 2023
1e46ec0
First try of run level analysis [skip ci]
bclenet Oct 23, 2023
3fe4ca2
First try of run level analysis [skip ci]
bclenet Oct 23, 2023
72635b1
First try of run level analysis [skip ci]
bclenet Oct 23, 2023
4c62bf2
ANT's apply transform bug [skip ci]
bclenet Oct 23, 2023
e7217da
ANT's apply transform bug [skip ci]
bclenet Oct 23, 2023
e029f37
ANT's apply transform bug [skip ci]
bclenet Oct 24, 2023
e8f475d
ANT's apply transform bug [skip ci]
bclenet Oct 24, 2023
04bdeba
ANT's apply transform bug [skip ci]
bclenet Oct 24, 2023
858004a
First try of run level analysis [skip ci]
bclenet Oct 24, 2023
b63a052
First try of run level analysis [skip ci]
bclenet Oct 24, 2023
8ba967f
First try of subject level analysis [skip ci]
bclenet Oct 24, 2023
d39fc44
First try of subject level analysis [skip ci]
bclenet Oct 24, 2023
98abcfc
FSL's Merge disambiguataion [skip ci]
bclenet Oct 24, 2023
77515c0
Use MNI masks [skip ci]
bclenet Oct 24, 2023
8d907cd
Preprocessing sieable files removing
bclenet Oct 24, 2023
1ea7e12
Bug with contrasts Node naming
bclenet Oct 24, 2023
e79239f
Base directories
bclenet Oct 25, 2023
4dad129
Remove alignment_func_to_mni's output [skip ci]
bclenet Oct 25, 2023
26ddc3a
Autoremove intermediate results [skip ci]
bclenet Oct 25, 2023
bedc2b5
Autoremove intermediate results [skip ci]
bclenet Oct 25, 2023
fa2ebd7
Revert "Remove alignment_func_to_mni's output [skip ci]"
bclenet Oct 25, 2023
7832af2
Bug after revert [skip ci]
bclenet Oct 25, 2023
c575158
Bug after revert [skip ci]
bclenet Oct 25, 2023
f6844a5
[TEST] tests updates
bclenet Oct 26, 2023
ed4f11e
Bug with big files removal
bclenet Oct 26, 2023
8770d81
Deletinglarge files after datasink
bclenet Oct 27, 2023
8992184
[BUG] group level workflow connections [skip ci]
bclenet Nov 15, 2023
f488a7b
[BUG] group level [skip ci]
bclenet Nov 15, 2023
d93e3a6
[REFAC] equalRange > equal_range [skip ci]
bclenet Nov 15, 2023
bd13c53
Regressors function + group output [skip ci]
bclenet Nov 15, 2023
0f8f35e
Typo in regressors [skip ci]
bclenet Nov 15, 2023
3025305
Issue with list of regressors [skip ci]
bclenet Nov 15, 2023
8d14472
Issue with list of regressors [skip ci]
bclenet Nov 15, 2023
817ec31
Issue with list of regressors [skip ci]
bclenet Nov 15, 2023
e092bc5
[TEST] adding unit tests to 08MQ [skip ci]
bclenet Nov 15, 2023
4892f5c
[TEST] typo [skip ci]
bclenet Nov 15, 2023
517fc41
[TEST] static methods testing [skip ci]
bclenet Nov 15, 2023
fd9bbf3
[TEST] adding unit tests for 08MQ
bclenet Nov 15, 2023
7252864
[CODESPELL] typos
bclenet Nov 15, 2023
68adef4
[BUG] inversion between groups [skip ci]
bclenet Nov 16, 2023
c03e9d1
Merge branch 'Inria-Empenn:main' into main
bclenet Nov 20, 2023
e7e9f48
Merge branch 'main' into 08MQ_reproduction
bclenet Nov 20, 2023
c6ae521
[REFAC] Using narps_open.core functions
bclenet Nov 20, 2023
7433106
[REFAC] using narps_open.core functions [TEST] events data in a file
bclenet Nov 20, 2023
053d72c
[BUG] remove_file input naming [skip ci]
bclenet Nov 21, 2023
34b649e
[BUG] remove sub- from participants id [skip ci]
bclenet Nov 22, 2023
9700166
[BUG] typo in get_two_sample_t_test_regressors inputs [skip ci]
bclenet Nov 22, 2023
8c73773
Compute brightness threshold for SUSAN [skip ci]
bclenet Nov 28, 2023
8e736f7
Use ANTs ApplyTransforms for alignment_func_to_anat Node [skip ci]
bclenet Nov 28, 2023
36e8fdd
[narps_open.core] adding list_to_file function [skip ci]
bclenet Nov 29, 2023
b979f1c
[08MQ] custom timings as input of SliceTimer [skip ci]
bclenet Nov 29, 2023
839e53d
Typo preprocessing
bclenet Nov 30, 2023
153e747
Computing masks : output of preprocessing [skip ci]
bclenet Dec 5, 2023
01bfb8e
Computing masks : output of preprocessing [skip ci]
bclenet Dec 5, 2023
9a16b06
Back to ApplyXFM, with no_resample option [skip ci]
bclenet Dec 5, 2023
502c206
Back to ApplyXFM, with no_resample option [skip ci]
bclenet Dec 5, 2023
8adcf86
Back to ApplyXFM, with no_resample option [skip ci]
bclenet Dec 5, 2023
eb8ae1c
Mask intersection of func as input of subject_level estimate model [s…
bclenet Dec 5, 2023
2789d44
Mask intersection of func as input of subject_level estimate model [s…
bclenet Dec 5, 2023
5e02694
Mask intersection in group_level analysis [skip ci]
bclenet Dec 5, 2023
26f0e09
Mask input + mask intersection inside group level analysis [skip ci]
bclenet Dec 6, 2023
8ac81d1
Adding mask to randomise Node [skip ci]
bclenet Dec 6, 2023
ad0b24f
Actually passing mask tu compute median node [skip ci]
bclenet Dec 11, 2023
cb99973
Actually passing mask tu compute median node [skip ci]
bclenet Dec 11, 2023
09cfe2f
Actually passing mask tu compute median node [skip ci]
bclenet Dec 11, 2023
bfd163e
Adding mask to compute median node [skip ci]
bclenet Dec 11, 2023
7f5191c
Adding wm sgmentation to coregistration_sbref node working with bbr c…
bclenet Dec 12, 2023
d83d066
Adding brain extraction of sbrefs [skip ci]
bclenet Dec 12, 2023
86da1a1
Using unthresholded wm for coregistration_sbref node [skip ci]
bclenet Dec 12, 2023
483a4d0
Bug with WM selection [skip ci]
bclenet Dec 12, 2023
843eb1f
Adding back remove functions for testing on 20 subjects [skip ci]
bclenet Dec 12, 2023
e0f599f
Removing more intermediate results [skip ci]
bclenet Dec 18, 2023
6c228f9
Force 2.0mm resampling for alignment_func_to_anat node [skip ci]
bclenet Dec 20, 2023
40a67e1
Force 2.0mm resampling for alignment_func_to_anat node [skip ci]
bclenet Dec 20, 2023
3250a6d
[TEST][PEP8] [skip ci]
bclenet Dec 20, 2023
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
21 changes: 21 additions & 0 deletions narps_open/core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,24 @@ def list_intersection(list_1: list, list_2: list) -> list:
- list, the intersection of list_1 and list_2
"""
return [e for e in list_1 if e in list_2]

def list_to_file(input_list: list, file_name: str = 'elements.tsv') -> str:
"""
Create a tsv file containing elements of the input list.
This function is meant to be used in a Nipype Function Node.

Parameters :
- input_list: list

Returns:
- output_file: path to the created file
"""
from os.path import abspath
output_file = abspath(file_name)

# Write un element per line
with open(output_file, 'w') as writer:
for element in input_list:
writer.write(f'{element}\n')

return output_file
8 changes: 4 additions & 4 deletions narps_open/data/participants.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ def get_participants_subset(nb_participants: int = 108) -> list:
return get_all_participants()[0:nb_participants]

def get_group(group_name: str) -> list:
""" Return a list containing all the participants inside the group_name group
""" Return a list containing all the participants inside the group_name group """

Warning : the subject ids are return as written in the participants file (i.e.: 'sub-*')
"""
participants = get_participants_information()
return participants.loc[participants['group'] == group_name]['participant_id'].values.tolist()
group = participants.loc[participants['group'] == group_name]['participant_id'].values.tolist()

return [p.replace('sub-', '') for p in group]
2 changes: 1 addition & 1 deletion narps_open/pipelines/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# List all the available pipelines and the corresponding class for each
implemented_pipelines = {
'08MQ': None,
'08MQ': 'PipelineTeam08MQ',
'0C7Q': None,
'0ED6': None,
'0H5E': None,
Expand Down
1,050 changes: 1,050 additions & 0 deletions narps_open/pipelines/team_08MQ.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions narps_open/utils/configuration/testing_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ title = "Testing configuration for the NARPS open pipelines project"
config_type = "testing"

[directories]
dataset = "run/data/ds001734/"
dataset = "data/original/ds001734/"
reproduced_results = "run/data/reproduced/"
narps_results = "run/data/results/"
narps_results = "data/results/"
test_data = "tests/test_data/"
test_runs = "run/"

Expand Down
63 changes: 63 additions & 0 deletions tests/core/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,66 @@ def test_connect_list_intersection(remove_test_dir):
test_file_2 = join(TEMPORARY_DIR, 'test_workflow', 'node_2', '_report', 'report.rst')
with open(test_file_2, 'r', encoding = 'utf-8') as file:
assert f'* out_value : {output_list_2}' in file.read()

@staticmethod
@mark.unit_test
def test_node_list_to_file_1():
""" Test the list_to_file function as a nipype.Node """

# Inputs
input_list = ['001', 23.560, 'azerty', False, None]

# Create a Nipype Node using list_to_file
test_node = Node(Function(
function = co.list_to_file,
input_names = ['input_list'],
output_names = ['out_file']
), name = 'test_node')
test_node.inputs.input_list = input_list
test_node.run()

# Expected output (in the Node's working directory)
out_file = join(test_node.output_dir(), 'elements.tsv')
out_list = [str(a) for a in input_list]

# Check file was created
assert exists(out_file)

# Check file was created
with open(out_file, 'r', encoding = 'utf-8') as file:
for list_element, file_element in zip(out_list, file.read().split('\n')):
assert list_element == file_element

@staticmethod
@mark.unit_test
def test_node_list_to_file_2():
""" Test the list_to_file function as a nipype.Node
Test changing name of output file
"""

# Inputs
input_list = ['001', 23.560, [2.0, 1, 53, True], False, None]
file_name = 'custom_filename.txt'

# Create a Nipype Node using list_to_file
test_node = Node(Function(
function = co.list_to_file,
input_names = ['input_list', 'file_name'],
output_names = ['out_file']
), name = 'test_node')
test_node.inputs.input_list = input_list
test_node.inputs.file_name = file_name
test_node.run()

# Expected output
out_file = join(test_node.output_dir(), file_name)
out_list = [str(a) for a in input_list]

# Check file was created
assert exists(out_file)

# Check file was created
with open(out_file, 'r', encoding = 'utf-8') as file:
for list_element, file_element in zip(out_list, file.read().split('\n')):
assert list_element == file_element

4 changes: 2 additions & 2 deletions tests/data/test_participants.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,5 @@ def test_get_group(mock_participants_data):
""" Test the get_group function """

assert part.get_group('') == []
assert part.get_group('equalRange') == ['sub-002', 'sub-004']
assert part.get_group('equalIndifference') == ['sub-001', 'sub-003']
assert part.get_group('equalRange') == ['002', '004']
assert part.get_group('equalIndifference') == ['001', '003']
Empty file removed tests/pipelines/__init__.py
Empty file.
143 changes: 143 additions & 0 deletions tests/pipelines/test_team_08MQ.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#!/usr/bin/python
# coding: utf-8

""" Tests of the 'narps_open.pipelines.team_08MQ' module.

Launch this test with PyTest

Usage:
======
pytest -q test_team_08MQ.py
pytest -q test_team_08MQ.py -k <selected_test>
"""
from os.path import join

from pytest import helpers, mark
from numpy import isclose
from nipype import Workflow
from nipype.interfaces.base import Bunch

from narps_open.utils.configuration import Configuration
from narps_open.pipelines.team_08MQ import PipelineTeam08MQ

class TestPipelinesTeam08MQ:
""" A class that contains all the unit tests for the PipelineTeam08MQ class."""

@staticmethod
@mark.unit_test
def test_create():
""" Test the creation of a PipelineTeam08MQ object """

pipeline = PipelineTeam08MQ()

# 1 - check the parameters
assert pipeline.fwhm == 6.0
assert pipeline.team_id == '08MQ'
assert pipeline.contrast_list == ['1', '2', '3']
assert pipeline.run_level_contasts == [
('positive_effect_gain', 'T', ['gain', 'loss'], [1, 0]),
('positive_effect_loss', 'T', ['gain', 'loss'], [0, 1]),
('negative_effect_loss', 'T', ['gain', 'loss'], [0, -1])
]

# 2 - check workflows
assert isinstance(pipeline.get_preprocessing(), Workflow)
assert isinstance(pipeline.get_run_level_analysis(), Workflow)
assert isinstance(pipeline.get_subject_level_analysis(), Workflow)

group_level = pipeline.get_group_level_analysis()
assert len(group_level) == 3
for sub_workflow in group_level:
assert isinstance(sub_workflow, Workflow)

@staticmethod
@mark.unit_test
def test_outputs():
""" Test the expected outputs of a PipelineTeam08MQ object """
pipeline = PipelineTeam08MQ()
# 1 - 1 subject outputs
pipeline.subject_list = ['001']
assert len(pipeline.get_preprocessing_outputs()) == 4*4
assert len(pipeline.get_run_level_outputs()) == 8+4*3*4
assert len(pipeline.get_subject_level_outputs()) == 4*3
assert len(pipeline.get_group_level_outputs()) == 0
assert len(pipeline.get_hypotheses_outputs()) == 18

# 2 - 4 subjects outputs
pipeline.subject_list = ['001', '002', '003', '004']
assert len(pipeline.get_preprocessing_outputs()) == 4*4*4
assert len(pipeline.get_run_level_outputs()) == (8+4*3*4)*4
assert len(pipeline.get_subject_level_outputs()) == 4*3*4
assert len(pipeline.get_group_level_outputs()) == 0
assert len(pipeline.get_hypotheses_outputs()) == 18

@staticmethod
@mark.unit_test
def test_subject_information():
""" Test the get_subject_information method """

information = PipelineTeam08MQ.get_subject_information(join(
Configuration()['directories']['test_data'],
'pipelines',
'events.tsv'
))[0]

assert isinstance(information, Bunch)
assert information.conditions == ['event', 'gain', 'loss', 'response']

reference_amplitudes = [
[1.0, 1.0, 1.0, 1.0, 1.0],
[14.0, 34.0, 38.0, 10.0, 16.0],
[6.0, 14.0, 19.0, 15.0, 17.0],
[1.0, 1.0, 0.0, -1.0, -1.0]
]
for reference_array, test_array in zip(reference_amplitudes, information.amplitudes):
assert isclose(reference_array, test_array).all()

reference_durations = [
[4.0, 4.0, 4.0, 4.0, 4.0],
[4.0, 4.0, 4.0, 4.0, 4.0],
[4.0, 4.0, 4.0, 4.0, 4.0],
[4.0, 4.0, 4.0, 4.0, 4.0]
]
for reference_array, test_array in zip(reference_durations, information.durations):
assert isclose(reference_array, test_array).all()

reference_onsets = [
[4.071, 11.834, 19.535, 27.535, 36.435],
[4.071, 11.834, 19.535, 27.535, 36.435],
[4.071, 11.834, 19.535, 27.535, 36.435],
[4.071, 11.834, 19.535, 27.535, 36.435]
]
for reference_array, test_array in zip(reference_onsets, information.onsets):
assert isclose(reference_array, test_array).all()

@staticmethod
@mark.unit_test
def test_one_sample_t_test_regressors():
""" Test the get_one_sample_t_test_regressors method """

regressors = PipelineTeam08MQ.get_one_sample_t_test_regressors(['001', '002'])
assert regressors == {'group_mean': [1, 1]}

@staticmethod
@mark.unit_test
def test_two_sample_t_test_regressors():
""" Test the get_two_sample_t_test_regressors method """

regressors, groups = PipelineTeam08MQ.get_two_sample_t_test_regressors(
['001', '003'], # equalRange group
['002', '004'], # equalIndifference group
['001', '002', '003', '004'] # all subjects
)
assert regressors == dict(
equalRange = [1, 0, 1, 0],
equalIndifference = [0, 1, 0, 1]
)
assert groups == [1, 2, 1, 2]

@staticmethod
@mark.pipeline_test
def test_execution():
""" Test the execution of a PipelineTeam08MQ and compare results """
helpers.test_pipeline_evaluation('08MQ')
6 changes: 6 additions & 0 deletions tests/test_data/pipelines/events.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
onset duration gain loss RT participant_response
4.071 4 14 6 2.388 weakly_accept
11.834 4 34 14 2.289 strongly_accept
19.535 4 38 19 0 NoResp
27.535 4 10 15 2.08 strongly_reject
36.435 4 16 17 2.288 weakly_reject
4 changes: 2 additions & 2 deletions tests/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def test_create():

# 3 - Instantiate a runner with a not implemented team id
with raises(NotImplementedError):
PipelineRunner('08MQ')
PipelineRunner('1K0E')

# 4 - Instantiate a runner with an implemented team id
runner = PipelineRunner('2T6S')
Expand All @@ -204,7 +204,7 @@ def test_create():

# 5 - Modify team id for an existing runner (with a not implemented team id)
with raises(NotImplementedError):
runner.team_id = '08MQ'
runner.team_id = '1K0E'

@staticmethod
@mark.unit_test
Expand Down