Skip to content

Commit

Permalink
[ENH][DOC] node generators in core module
Browse files Browse the repository at this point in the history
  • Loading branch information
bclenet committed Jan 25, 2024
1 parent 88b4aa2 commit 6f2047c
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 21 deletions.
43 changes: 43 additions & 0 deletions docs/core.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,46 @@ This module contains a set of functions dedicated to computations on images.
# 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')
```

## narps_open.core.nodes

This module contains a set of node creators inheriting form the `narps_open.core.nodes.NodeCreator` abstract class.
These are responsible for creating nipype `Node` objects (for now, only based on the `Function` interface, with functions defined in the `narps_open.core.common` module) to be used inside pipeline code. This allows to factorize code, hence making code simpler to read inside pipeline definition.

Here is an example how to use the node creators :

```python
from narps_open.core.nodes import RemoveDirectoryNodeCreator, RemoveFileNodeCreator

# Create a Node to remove a directory
remove_smoothed = RemoveDirectoryNodeCreator.create_node('remove_smoothed')
remove_smoothed.inputs.directory_name = 'my_directory'

# Create a Node to remove a file
remove_gunzip = RemoveFileNodeCreator.create_node('remove_gunzip')
remove_gunzip.inputs.file_name = 'my_file'
```

For your information, this is how an equivalent code would look like without node creators.

```python
from nipype import Node
from nipype.interfaces.utility import Function
from narps_open.core.common import remove_directory, remove_file

# Create a Node to remove a directory
remove_smoothed = Node(Function(
function = remove_directory,
input_names = ['_', 'directory_name'],
output_names = []
), name = 'remove_smoothed')
remove_smoothed.inputs.directory_name = 'my_directory'

# Create a Node to remove a file
remove_gunzip = Node(Function(
function = remove_file,
input_names = ['_', 'file_name'],
output_names = []
), name = 'remove_gunzip')
remove_gunzip.inputs.file_name = 'my_file'
```
9 changes: 6 additions & 3 deletions narps_open/core/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
class NodeCreator(ABC):
""" An abstract class to shape what node creators must provide """

@staticmethod
@abstractmethod
def create_node(self, name: str) -> Node:
def create_node(name: str) -> Node:
""" Return a new Node (the interface of the Node is defined by specialized classes)
Arguments:
name, str : the name of the node
Expand All @@ -23,7 +24,8 @@ def create_node(self, name: str) -> Node:
class RemoveDirectoryNodeCreator(NodeCreator):
""" A node creator that provides an interface allowing to remove a directory """

def create_node(self, name: str) -> Node:
@staticmethod
def create_node(name: str) -> Node:
return Node(Function(
function = remove_directory,
input_names = ['_', 'directory_name'],
Expand All @@ -33,7 +35,8 @@ def create_node(self, name: str) -> Node:
class RemoveFileNodeCreator(NodeCreator):
""" A node creator that provides an interface allowing to remove a file """

def create_node(self, name: str) -> Node:
@staticmethod
def create_node(name: str) -> Node:
return Node(Function(
function = remove_file,
input_names = ['_', 'file_name'],
Expand Down
23 changes: 5 additions & 18 deletions tests/core/test_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,13 @@ class TestNodeCreator:
def test_create_node():
""" Test the create_node method """

# It is not possible to create an instance of a NodeCreator
with raises(Exception):
nd.NodeCreator().create_node('node_name')

# Define a child for NodeCreator
class ErrorNC(nd.NodeCreator):
def random_method(self):
pass

# Test it cannot be instanciated
with raises(Exception):
ErrorNC().create_node('node_name')

# Define another child for NodeCreator
class ValidNC(nd.NodeCreator):
def create_node(self, name: str) -> Node:
def create_node(name: str) -> Node:
return Node(Select(), name = name)

# Test it can be instanciated
test_node = ValidNC().create_node('node_name')
# Test it can be instantiated
test_node = ValidNC.create_node('node_name')
assert isinstance(test_node, Node)
assert isinstance(test_node.interface, Select)
assert test_node.name == 'node_name'
Expand All @@ -59,7 +46,7 @@ class TestRemoveDirectoryNodeCreator:
def test_create_node():
""" Test the create_node method """

test_node = nd.RemoveDirectoryNodeCreator().create_node('node_name')
test_node = nd.RemoveDirectoryNodeCreator.create_node('node_name')
assert isinstance(test_node, Node)
assert isinstance(test_node.interface, Function)
assert test_node.name == 'node_name'
Expand All @@ -72,7 +59,7 @@ class TestRemoveFileNodeCreator:
def test_create_node():
""" Test the create_node method """

test_node = nd.RemoveFileNodeCreator().create_node('node_name')
test_node = nd.RemoveFileNodeCreator.create_node('node_name')
assert isinstance(test_node, Node)
assert isinstance(test_node.interface, Function)
assert test_node.name == 'node_name'

0 comments on commit 6f2047c

Please sign in to comment.