forked from Inria-Empenn/narps_open_pipelines
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'Inria-Empenn:main' into main
- Loading branch information
Showing
25 changed files
with
846 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -139,3 +139,6 @@ dmypy.json | |
# Pyre type checker | ||
.pyre/ | ||
*pyscript* | ||
|
||
# For mac users | ||
*.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
### Contents overview | ||
|
||
- :snake: :package: `narps_open/` contains the Python package with all the pipelines logic. | ||
- :brain: `data/` contains data that is used by the pipelines, as well as the (intermediate or final) results data. Instructions to download data are available in [INSTALL.md](/INSTALL.md#data-download-instructions). | ||
- :blue_book: `docs/` contains the documentation for the project. Start browsing it with the entry point [docs/README.md](/docs/README.md) | ||
- :orange_book: `examples/` contains notebooks examples to launch of the reproduced pipelines. | ||
- :microscope: `tests/` contains the tests of the narps_open package. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
# Core functions you can use to write pipelines | ||
|
||
Here are a few functions that could be useful for creating a pipeline with Nipype. These functions are meant to stay as unitary as possible. | ||
|
||
These are intended to be inserted in a nipype.Workflow inside a [nipype.Function](https://nipype.readthedocs.io/en/latest/api/generated/nipype.interfaces.utility.wrappers.html#function) interface, or for some of them (see associated docstring) as part of a [nipype.Workflow.connect](https://nipype.readthedocs.io/en/latest/api/generated/nipype.pipeline.engine.workflows.html#nipype.pipeline.engine.workflows.Workflow.connect) method. | ||
|
||
In the following example, we use the `list_intersection` function of `narps_open.core.common`, in both of the mentioned cases. | ||
|
||
```python | ||
from nipype import Node, Function, Workflow | ||
from narps_open.core.common import list_intersection | ||
|
||
# First case : a Function Node | ||
intersection_node = Node(Function( | ||
function = list_intersection, | ||
input_names = ['list_1', 'list_2'], | ||
output_names = ['output'] | ||
), name = 'intersection_node') | ||
intersection_node.inputs.list_1 = ['001', '002', '003', '004'] | ||
intersection_node.inputs.list_2 = ['002', '004', '005'] | ||
print(intersection_node.run().outputs.output) # ['002', '004'] | ||
|
||
# Second case : inside a connect node | ||
# We assume that there is a node_0 returning ['001', '002', '003', '004'] as `output` value | ||
test_workflow = Workflow( | ||
base_dir = '/path/to/base/dir', | ||
name = 'test_workflow' | ||
) | ||
test_workflow.connect([ | ||
# node_1 will receive the evaluation of : | ||
# list_intersection(['001', '002', '003', '004'], ['002', '004', '005']) | ||
# as in_value | ||
(node_0, node_1, [(('output', list_intersection, ['002', '004', '005']), 'in_value')]) | ||
]) | ||
test_workflow.run() | ||
``` | ||
|
||
> [!TIP] | ||
> Use a [nipype.MapNode](https://nipype.readthedocs.io/en/latest/api/generated/nipype.pipeline.engine.nodes.html#nipype.pipeline.engine.nodes.MapNode) to run these functions on lists instead of unitary contents. E.g.: the `remove_file` function of `narps_open.core.common` only removes one file at a time, but feel free to pass a list of files using a `nipype.MapNode`. | ||
```python | ||
from nipype import MapNode, Function | ||
from narps_open.core.common import remove_file | ||
|
||
# Create the MapNode so that the `remove_file` function handles lists of files | ||
remove_files_node = MapNode(Function( | ||
function = remove_file, | ||
input_names = ['_', 'file_name'], | ||
output_names = [] | ||
), name = 'remove_files_node', iterfield = ['file_name']) | ||
|
||
# ... A couple of lines later, in the Worlflow definition | ||
test_workflow = Workflow(base_dir = '/home/bclenet/dev/tests/nipype_merge/', name = 'test_workflow') | ||
test_workflow.connect([ | ||
# ... | ||
# Here we assume the select_node's output `out_files` is a list of files | ||
(select_node, remove_files_node, [('out_files', 'file_name')]) | ||
# ... | ||
]) | ||
``` | ||
|
||
## narps_open.core.common | ||
|
||
This module contains a set of functions that nearly every pipeline could use. | ||
|
||
* `remove_file` remove a file when it is not needed anymore (to save disk space) | ||
|
||
```python | ||
from narps_open.core.common import remove_file | ||
|
||
# Remove the /path/to/the/image.nii.gz file | ||
remove_file('/path/to/the/image.nii.gz') | ||
``` | ||
|
||
* `elements_in_string` : return the first input parameter if it contains one element of second parameter (None otherwise). | ||
|
||
```python | ||
from narps_open.core.common import elements_in_string | ||
|
||
# Here we test if the file 'sub-001_file.nii.gz' belongs to a group of subjects. | ||
elements_in_string('sub-001_file.nii.gz', ['005', '006', '007']) # Returns None | ||
elements_in_string('sub-001_file.nii.gz', ['001', '002', '003']) # Returns 'sub-001_file.nii.gz' | ||
``` | ||
|
||
> [!TIP] | ||
> This can be generalised to a group of files, using a `nipype.MapNode`! | ||
* `clean_list` : remove elements of the first input parameter (list) if it is equal to the second parameter. | ||
|
||
```python | ||
from narps_open.core.common import clean_list | ||
|
||
# Here we remove subject 002 from a group of subjects. | ||
clean_list(['002', '005', '006', '007'], '002') | ||
``` | ||
|
||
* `list_intersection` : return the intersection of two lists. | ||
|
||
```python | ||
from narps_open.core.common import list_intersection | ||
|
||
# Here we keep only subjects that are in the equalRange group and selected for the analysis. | ||
equal_range_group = ['002', '004', '006', '008'] | ||
selected_for_analysis = ['002', '006', '010'] | ||
list_intersection(equal_range_group, selected_for_analysis) # Returns ['002', '006'] | ||
``` | ||
|
||
## narps_open.core.image | ||
|
||
This module contains a set of functions dedicated to computations on images. | ||
|
||
* `get_voxel_dimensions` : returns the voxel dimensions of an image | ||
|
||
```python | ||
# Get dimensions of voxels along x, y, and z in mm (returns e.g.: [1.0, 1.0, 1.0]). | ||
get_voxel_dimensions('/path/to/the/image.nii.gz') | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
#!/usr/bin/python | ||
# coding: utf-8 | ||
|
||
""" Common functions to write pipelines """ | ||
|
||
def remove_file(_, file_name: str) -> None: | ||
""" | ||
Fully remove files generated by a Node, once they aren't needed anymore. | ||
This function is meant to be used in a Nipype Function Node. | ||
Parameters: | ||
- _: input only used for triggering the Node | ||
- file_name: str, a single absolute filename of the file to remove | ||
""" | ||
# This import must stay inside the function, as required by Nipype | ||
from os import remove | ||
|
||
try: | ||
remove(file_name) | ||
except OSError as error: | ||
print(error) | ||
|
||
def elements_in_string(input_str: str, elements: list) -> str: #| None: | ||
""" | ||
Return input_str if it contains one element of the elements list. | ||
Return None otherwise. | ||
This function is meant to be used in a Nipype Function Node. | ||
Parameters: | ||
- input_str: str | ||
- elements: list of str, elements to be searched in input_str | ||
""" | ||
if any(e in input_str for e in elements): | ||
return input_str | ||
return None | ||
|
||
def clean_list(input_list: list, element = None) -> list: | ||
""" | ||
Remove elements of input_list that are equal to element and return the resultant list. | ||
This function is meant to be used in a Nipype Function Node. It can be used inside a | ||
nipype.Workflow.connect call as well. | ||
Parameters: | ||
- input_list: list | ||
- element: any | ||
Returns: | ||
- input_list with elements equal to element removed | ||
""" | ||
return [f for f in input_list if f != element] | ||
|
||
def list_intersection(list_1: list, list_2: list) -> list: | ||
""" | ||
Returns the intersection of two lists. | ||
This function is meant to be used in a Nipype Function Node. It can be used inside a | ||
nipype.Workflow.connect call as well. | ||
Parameters: | ||
- list_1: list | ||
- list_2: list | ||
Returns: | ||
- list, the intersection of list_1 and list_2 | ||
""" | ||
return [e for e in list_1 if e in list_2] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#!/usr/bin/python | ||
# coding: utf-8 | ||
|
||
""" Image functions to write pipelines """ | ||
|
||
def get_voxel_dimensions(image: str) -> list: | ||
""" | ||
Return the voxel dimensions of a image in millimeters. | ||
Arguments: | ||
image: str, string that represent an absolute path to a Nifti image. | ||
Returns: | ||
list, size of the voxels in the image in millimeters. | ||
""" | ||
# This import must stay inside the function, as required by Nipype | ||
from nibabel import load | ||
|
||
voxel_dimensions = load(image).header.get_zooms() | ||
|
||
return [ | ||
float(voxel_dimensions[0]), | ||
float(voxel_dimensions[1]), | ||
float(voxel_dimensions[2]) | ||
] |
Oops, something went wrong.